aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorMax Horn2009-09-22 00:36:24 +0000
committerMax Horn2009-09-22 00:36:24 +0000
commit5f5ab54810e979f230e4410fc4805c36abfe6dc1 (patch)
treecdf71bc5b729f4d9eff4cfba3990aadff225ffda /engines/sci/engine
parent97d1f79e2d0c23dc337e85888ffa67aca98f7358 (diff)
downloadscummvm-rg350-5f5ab54810e979f230e4410fc4805c36abfe6dc1.tar.gz
scummvm-rg350-5f5ab54810e979f230e4410fc4805c36abfe6dc1.tar.bz2
scummvm-rg350-5f5ab54810e979f230e4410fc4805c36abfe6dc1.zip
SCI: Add new type SegmentRef which ultimately will allow us to distinguish between raw and 'reg_t' memory blocks in client code
svn-id: r44244
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/seg_manager.cpp17
-rw-r--r--engines/sci/engine/seg_manager.h3
-rw-r--r--engines/sci/engine/segment.cpp84
-rw-r--r--engines/sci/engine/segment.h30
4 files changed, 84 insertions, 50 deletions
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 6449272bdc..e7e8d4197b 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -863,29 +863,30 @@ Hunk *SegManager::alloc_Hunk(reg_t *addr) {
return &(table->_table[offset]);
}
-byte *SegManager::dereference(reg_t pointer, int *size) {
+SegmentRef SegManager::dereference(reg_t pointer) {
+ SegmentRef ret;
+
if (!pointer.segment || (pointer.segment >= _heap.size()) || !_heap[pointer.segment]) {
// This occurs in KQ5CD when interacting with certain objects
warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
- return NULL; /* Invalid */
+ return ret; /* Invalid */
}
SegmentObj *mobj = _heap[pointer.segment];
- return mobj->dereference(pointer, size);
+ return mobj->dereference(pointer);
}
static void *_kernel_dereference_pointer(SegManager *segMan, reg_t pointer, int entries) {
- int maxsize;
- void *retval = segMan->dereference(pointer, &maxsize);
+ SegmentRef ret = segMan->dereference(pointer);
- if (!retval)
+ if (!ret.raw)
return NULL;
- if (entries > maxsize) {
+ if (entries > ret.maxSize) {
warning("Trying to dereference pointer %04x:%04x beyond end of segment", PRINT_REG(pointer));
return NULL;
}
- return retval;
+ return ret.raw;
}
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index 8c6676d0ec..61b0c76e2e 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -279,10 +279,9 @@ public:
/**
* Dereferences a raw memory pointer
* @param[in] reg The reference to dereference
- * @param[out] size (optional) The theoretical maximum size
* @return The data block referenced
*/
- byte *dereference(reg_t reg, int *size);
+ SegmentRef dereference(reg_t pointer);
/**
* Dereferences a heap pointer pointing to raw memory.
diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp
index 80027dbb39..7d2889aefc 100644
--- a/engines/sci/engine/segment.cpp
+++ b/engines/sci/engine/segment.cpp
@@ -214,79 +214,97 @@ int16 Script::getHeap(uint16 offset) const {
// return (_buf[offset] | (_buf[offset+1]) << 8);
}
-byte *SegmentObj::dereference(reg_t pointer, int *size) {
+SegmentRef SegmentObj::dereference(reg_t pointer) {
error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment",
PRINT_REG(pointer));
- return NULL;
+ return SegmentRef();
}
bool Script::isValidOffset(uint16 offset) const {
return offset < _bufSize;
}
-byte *Script::dereference(reg_t pointer, int *size) {
+SegmentRef Script::dereference(reg_t pointer) {
if (pointer.offset > _bufSize) {
- warning("Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n",
+ warning("Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)",
PRINT_REG(pointer), (uint)_bufSize);
- return NULL;
+ return SegmentRef();
}
- if (size)
- *size = _bufSize - pointer.offset;
- return _buf + pointer.offset;
+
+ SegmentRef ret;
+ ret.isRaw = true;
+ ret.maxSize = _bufSize - pointer.offset;
+ ret.raw = _buf + pointer.offset;
+ return ret;
}
bool LocalVariables::isValidOffset(uint16 offset) const {
return offset < _locals.size() * sizeof(reg_t);
}
-byte *LocalVariables::dereference(reg_t pointer, int *size) {
- if (size)
- *size = _locals.size() * sizeof(reg_t);
-
+SegmentRef LocalVariables::dereference(reg_t pointer) {
// FIXME: The following doesn't seem to be endian safe.
// To fix this, we'd have to always treat the reg_t
// values stored here as in the little endian format.
- byte *base = (byte *)&_locals[0];
- return base + pointer.offset;
+ // Anyway, generate a warning for now to see if this ever
+ // happens.
+ // One has to wonder whether we return the right value anyway.
+ // Here are three potential options:
+ // 1: ((byte *)&_locals[0]) + pointer.offset
+ // 2: ((byte *)&_locals[pointer.offset/2]) + (pointer.offset % 2)
+ // 3: ((byte *)&_locals[pointer.offset])
+ // So which one is correct? :)
+ if (pointer.offset & 1)
+ warning("LocalVariables::dereference: Odd offset in pointer %04x:%04x", PRINT_REG(pointer));
+
+ SegmentRef ret;
+ ret.isRaw = false; // reg_t based data!
+ ret.maxSize = _locals.size() * sizeof(reg_t);
+ ret.raw = (byte *)&_locals[0] + pointer.offset;
+ return ret;
}
bool DataStack::isValidOffset(uint16 offset) const {
return offset < _capacity * sizeof(reg_t);
}
-byte *DataStack::dereference(reg_t pointer, int *size) {
- if (size)
- *size = _capacity * sizeof(reg_t);
-
- byte *base = (byte *)_entries;
- return base + pointer.offset;
+SegmentRef DataStack::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = false; // reg_t based data!
+ ret.maxSize = _capacity * sizeof(reg_t);
+ // FIXME: Is this correct? See comment in LocalVariables::dereference
+ ret.raw = (byte *)_entries + pointer.offset;
+ return ret;
}
bool DynMem::isValidOffset(uint16 offset) const {
return offset < _size;
}
-byte *DynMem::dereference(reg_t pointer, int *size) {
- if (size)
- *size = _size;
-
- byte *base = (byte *)_buf;
- return base + pointer.offset;
+SegmentRef DynMem::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = true;
+ ret.maxSize = _size;
+ ret.raw = _buf + pointer.offset;
+ return ret;
}
bool SystemStrings::isValidOffset(uint16 offset) const {
return offset < SYS_STRINGS_MAX && !strings[offset]._name.empty();
}
-byte *SystemStrings::dereference(reg_t pointer, int *size) {
- if (size)
- *size = strings[pointer.offset].max_size;
+SegmentRef SystemStrings::dereference(reg_t pointer) {
+ SegmentRef ret;
+ ret.isRaw = false; // FIXME: Raw or not raw? the sys strings code is totally incoherent in this regard
+ ret.maxSize = strings[pointer.offset].max_size;
if (isValidOffset(pointer.offset))
- return (byte *)(strings[pointer.offset].value);
+ ret.raw = (byte *)(strings[pointer.offset].value);
+ else {
+ // This occurs in KQ5CD when interacting with certain objects
+ warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
+ }
- // This occurs in KQ5CD when interacting with certain objects
- warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
- return NULL;
+ return ret;
}
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 81da9c2488..1f446957d5 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -34,6 +34,23 @@
namespace Sci {
+struct SegmentRef {
+ bool isRaw; ///! true if data is raw, false if it is a reg_t sequence
+ union {
+ byte *raw;
+ reg_t *reg;
+ };
+ int maxSize; ///! number of available bytes
+ // TODO: Add this?
+ //reg_t pointer; // Original pointer
+
+ // TODO: Add this?
+ //SegmentType type;
+
+ SegmentRef() : isRaw(true), raw(0), maxSize(0) {}
+};
+
+
enum SegmentType {
SEG_TYPE_INVALID = 0,
SEG_TYPE_SCRIPT = 1,
@@ -73,10 +90,9 @@ public:
/**
* Dereferences a raw memory pointer.
* @param reg reference to dereference
- * @param size if not NULL, set to the theoretical maximum size of the referenced data block
* @return the data block referenced
*/
- virtual byte *dereference(reg_t pointer, int *size);
+ virtual SegmentRef dereference(reg_t pointer);
/**
* Finds the canonic address associated with sub_reg.
@@ -161,7 +177,7 @@ public:
}
virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
+ virtual SegmentRef dereference(reg_t pointer);
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -176,7 +192,7 @@ public:
}
virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
+ virtual SegmentRef dereference(reg_t pointer);
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
@@ -309,7 +325,7 @@ public:
bool init(int script_nr, ResourceManager *resMan);
virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
+ virtual SegmentRef dereference(reg_t pointer);
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
@@ -467,7 +483,7 @@ public:
}
virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
+ virtual SegmentRef dereference(reg_t pointer);
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
@@ -624,7 +640,7 @@ public:
}
virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
+ virtual SegmentRef dereference(reg_t pointer);
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);