aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2010-05-26 08:27:24 +0000
committerFilippos Karapetis2010-05-26 08:27:24 +0000
commit1c0bbb10cbb20b8dd0bdc1cb748bb5ec9e538b42 (patch)
tree1e81f1578e48386f02fc5bb426c134ebe59b2362
parent60dd3106885b9784af15cb96122d28a5f0bf33f1 (diff)
downloadscummvm-rg350-1c0bbb10cbb20b8dd0bdc1cb748bb5ec9e538b42.tar.gz
scummvm-rg350-1c0bbb10cbb20b8dd0bdc1cb748bb5ec9e538b42.tar.bz2
scummvm-rg350-1c0bbb10cbb20b8dd0bdc1cb748bb5ec9e538b42.zip
More work on controlling access to members of the Object class:
- Moved the code for initializing the object class, species and base object inside the Object class - Made propertyOffsetToId() a method of the Object class - Made relocateObject() a method of the Object class - The Object getVariable() method now returns a reference to the requested variable Only SegManager::reconstructScripts() is left needing direct access to the members of the Object class svn-id: r49228
-rw-r--r--engines/sci/engine/script.cpp17
-rw-r--r--engines/sci/engine/scriptdebug.cpp40
-rw-r--r--engines/sci/engine/segment.cpp104
-rw-r--r--engines/sci/engine/segment.h36
-rw-r--r--engines/sci/engine/vm.cpp5
5 files changed, 120 insertions, 82 deletions
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index e9b1ce3f28..aa3fbc995a 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -318,8 +318,6 @@ int script_instantiate_common(ResourceManager *resMan, SegManager *segMan, int s
return seg_id;
}
-#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segMan->getClassAddress(id, SCRIPT_GET_LOCK, addr))
-
int script_instantiate_sci0(ResourceManager *resMan, SegManager *segMan, int script_nr) {
int objType;
uint32 objLength = 0;
@@ -429,21 +427,10 @@ int script_instantiate_sci0(ResourceManager *resMan, SegManager *segMan, int scr
case SCI_OBJ_OBJECT:
case SCI_OBJ_CLASS: { // object or class?
Object *obj = scr->scriptObjInit(addr);
+ obj->initSpecies(segMan, addr);
- // Instantiate the superclass, if neccessary
- obj->setSpeciesSelector(INST_LOOKUP_CLASS(obj->getSpeciesSelector().offset));
-
- Object *baseObj = segMan->getObject(obj->getSpeciesSelector());
-
- if (baseObj) {
- obj->setVarCount(baseObj->getVarCount());
- // Copy base from species class, as we need its selector IDs
- obj->_baseObj = baseObj->_baseObj;
-
- obj->setSuperClassSelector(INST_LOOKUP_CLASS(obj->getSuperClassSelector().offset));
- } else {
+ if (!obj->initBaseObject(segMan, addr)) {
warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
-
scr->scriptObjRemove(addr);
}
} // if object or class
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 4b60626b2e..608260ec50 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -67,37 +67,6 @@ extern const char *selector_name(EngineState *s, int selector);
DebugState g_debugState;
-int propertyOffsetToId(SegManager *segMan, int prop_ofs, reg_t objp) {
- Object *obj = segMan->getObject(objp);
- byte *selectoroffset;
- int selectors;
-
- if (!obj) {
- warning("Applied propertyOffsetToId on non-object at %04x:%04x", PRINT_REG(objp));
- return -1;
- }
-
- selectors = obj->getVarCount();
-
- if (getSciVersion() < SCI_VERSION_1_1)
- selectoroffset = ((byte *)(obj->_baseObj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2;
- else {
- if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS)) {
- obj = segMan->getObject(obj->getSuperClassSelector());
- selectoroffset = (byte *)obj->_baseVars;
- } else
- selectoroffset = (byte *)obj->_baseVars;
- }
-
- if (prop_ofs < 0 || (prop_ofs >> 1) >= selectors) {
- warning("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d]) on object at %04x:%04x",
- prop_ofs, prop_ofs >> 1, selectors - 1, PRINT_REG(objp));
- return -1;
- }
-
- return READ_SCI11ENDIAN_UINT16(selectoroffset + prop_ofs);
-}
-
// Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered.
reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode) {
SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT);
@@ -224,10 +193,11 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
if (pos == scriptState.xs->addr.pc) { // Extra information if debugging the current opcode
if ((opcode == op_pTos) || (opcode == op_sTop) || (opcode == op_pToa) || (opcode == op_aTop) ||
(opcode == op_dpToa) || (opcode == op_ipToa) || (opcode == op_dpTos) || (opcode == op_ipTos)) {
- int prop_ofs = scr[pos.offset + 1];
- int prop_id = propertyOffsetToId(s->_segMan, prop_ofs, scriptState.xs->objp);
-
- printf(" (%s)", selector_name(s, prop_id));
+ Object *obj = s->_segMan->getObject(scriptState.xs->objp);
+ if (!obj)
+ warning("Attempted to reference on non-object at %04x:%04x", PRINT_REG(scriptState.xs->objp));
+ else
+ printf(" (%s)", selector_name(s, obj->propertyOffsetToId(s->_segMan, scr[pos.offset + 1])));
}
}
diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp
index ab1a68d165..0c468a3cc2 100644
--- a/engines/sci/engine/segment.cpp
+++ b/engines/sci/engine/segment.cpp
@@ -247,10 +247,6 @@ int Script::relocateLocal(SegmentId segment, int location) {
return 0; // No hands, no cookies
}
-int Script::relocateObject(Object &obj, SegmentId segment, int location) {
- return relocateBlock(obj._variables, obj.getPos().offset, segment, location);
-}
-
void Script::scriptAddCodeBlock(reg_t location) {
CodeBlock cb;
cb.pos = location;
@@ -276,7 +272,7 @@ void Script::scriptRelocate(reg_t block) {
ObjMap::iterator it;
const ObjMap::iterator end = _objects.end();
for (it = _objects.begin(); !done && it != end; ++it) {
- if (relocateObject(it->_value, block.segment, pos))
+ if (it->_value.relocate(block.segment, pos, _scriptSize))
done = true;
}
@@ -321,7 +317,7 @@ void Script::heapRelocate(reg_t block) {
ObjMap::iterator it;
const ObjMap::iterator end = _objects.end();
for (it = _objects.begin(); !done && it != end; ++it) {
- if (relocateObject(it->_value, block.segment, pos))
+ if (it->_value.relocate(block.segment, pos, _scriptSize))
done = true;
}
@@ -673,6 +669,27 @@ void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback
//-------------------- object ----------------------------
+void Object::init(byte *buf, reg_t obj_pos) {
+ byte *data = (byte *)(buf + obj_pos.offset);
+ _baseObj = data;
+ _pos = obj_pos;
+
+ if (getSciVersion() < SCI_VERSION_1_1) {
+ _variables.resize(READ_LE_UINT16(data + SCRIPT_SELECTORCTR_OFFSET));
+ _baseVars = (uint16 *)(_baseObj + _variables.size() * 2);
+ _baseMethod = (uint16 *)(data + READ_LE_UINT16(data + SCRIPT_FUNCTAREAPTR_OFFSET));
+ _methodCount = READ_LE_UINT16(_baseMethod - 1);
+ } else {
+ _variables.resize(READ_SCI11ENDIAN_UINT16(data + 2));
+ _baseVars = (uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 4));
+ _baseMethod = (uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 6));
+ _methodCount = READ_SCI11ENDIAN_UINT16(_baseMethod);
+ }
+
+ for (uint i = 0; i < _variables.size(); i++)
+ _variables[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(data + (i * 2)));
+}
+
Object *Object::getClass(SegManager *segMan) {
return isClass() ? this : segMan->getObject(getSuperClassSelector());
}
@@ -698,6 +715,81 @@ int Object::locateVarSelector(SegManager *segMan, Selector slc) {
return -1; // Failed
}
+bool Object::relocate(SegmentId segment, int location, size_t scriptSize) {
+ int rel = location - getPos().offset;
+
+ if (rel < 0)
+ return false;
+
+ uint idx = rel >> 1;
+
+ if (idx >= _variables.size())
+ return false;
+
+ if (rel & 1) {
+ warning("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, getPos().offset);
+ return false;
+ }
+ _variables[idx].segment = segment; // Perform relocation
+ if (getSciVersion() >= SCI_VERSION_1_1)
+ _variables[idx].offset += scriptSize;
+
+ return true;
+}
+
+int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) {
+ int selectors = getVarCount();
+
+ if (propertyOffset < 0 || (propertyOffset >> 1) >= selectors) {
+ warning("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d])",
+ propertyOffset, propertyOffset >> 1, selectors - 1);
+ return -1;
+ }
+
+ if (getSciVersion() < SCI_VERSION_1_1) {
+ byte *selectoroffset = ((byte *)(_baseObj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2;
+ return READ_SCI11ENDIAN_UINT16(selectoroffset + propertyOffset);
+ } else {
+ Object *obj = this;
+ if (!(getInfoSelector().offset & SCRIPT_INFO_CLASS))
+ obj = segMan->getObject(getSuperClassSelector());
+
+ return READ_SCI11ENDIAN_UINT16((byte *)obj->_baseVars + propertyOffset);
+ }
+}
+
+void Object::initSpecies(SegManager *segMan, reg_t addr) {
+ uint16 speciesOffset = getSpeciesSelector().offset;
+
+ if (speciesOffset == 0xffff) // -1
+ setSpeciesSelector(NULL_REG); // no species
+ else
+ setSpeciesSelector(segMan->getClassAddress(speciesOffset, SCRIPT_GET_LOCK, addr));
+}
+
+void Object::initSuperClass(SegManager *segMan, reg_t addr) {
+ uint16 superClassOffset = getSuperClassSelector().offset;
+
+ if (superClassOffset == 0xffff) // -1
+ setSuperClassSelector(NULL_REG); // no superclass
+ else
+ setSuperClassSelector(segMan->getClassAddress(superClassOffset, SCRIPT_GET_LOCK, addr));
+}
+
+bool Object::initBaseObject(SegManager *segMan, reg_t addr) {
+ Object *baseObj = segMan->getObject(getSpeciesSelector());
+
+ if (baseObj) {
+ setVarCount(baseObj->getVarCount());
+ // Copy base from species class, as we need its selector IDs
+ _baseObj = baseObj->_baseObj;
+ initSuperClass(segMan, addr);
+ return true;
+ }
+
+ return false;
+}
+
//-------------------- dynamic memory --------------------
reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) {
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 1089ada475..876a081295 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -270,28 +270,9 @@ public:
void setVarCount(uint size) { _variables.resize(size); }
uint getVarCount() { return _variables.size(); }
- void init(byte *buf, reg_t obj_pos) {
- byte *data = (byte *)(buf + obj_pos.offset);
- _baseObj = data;
- _pos = obj_pos;
-
- if (getSciVersion() < SCI_VERSION_1_1) {
- _variables.resize(READ_LE_UINT16(data + SCRIPT_SELECTORCTR_OFFSET));
- _baseVars = (uint16 *)(_baseObj + _variables.size() * 2);
- _baseMethod = (uint16 *)(data + READ_LE_UINT16(data + SCRIPT_FUNCTAREAPTR_OFFSET));
- _methodCount = READ_LE_UINT16(_baseMethod - 1);
- } else {
- _variables.resize(READ_SCI11ENDIAN_UINT16(data + 2));
- _baseVars = (uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 4));
- _baseMethod = (uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 6));
- _methodCount = READ_SCI11ENDIAN_UINT16(_baseMethod);
- }
+ void init(byte *buf, reg_t obj_pos);
- for (uint i = 0; i < _variables.size(); i++)
- _variables[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(data + (i * 2)));
- }
-
- reg_t getVariable(uint var) { return _variables[var]; }
+ reg_t &getVariable(uint var) { return _variables[var]; }
uint16 getMethodCount() { return _methodCount; }
reg_t getPos() { return _pos; }
@@ -304,13 +285,23 @@ public:
_baseVars = obj ? obj->_baseVars : NULL;
}
+ bool relocate(SegmentId segment, int location, size_t scriptSize);
+
+ int propertyOffsetToId(SegManager *segMan, int propertyOffset);
+
+ void initSpecies(SegManager *segMan, reg_t addr);
+ void initSuperClass(SegManager *segMan, reg_t addr);
+ bool initBaseObject(SegManager *segMan, reg_t addr);
+
// TODO: make private
- Common::Array<reg_t> _variables;
+ // Only SegManager::reconstructScripts() is left needing direct access to these
+public:
byte *_baseObj; /**< base + object offset within base */
uint16 *_baseVars; /**< Pointer to the varselector area for this object */
uint16 *_baseMethod; /**< Pointer to the method selector area for this object */
private:
+ Common::Array<reg_t> _variables;
uint16 _methodCount;
int _flags;
uint16 _offset;
@@ -414,7 +405,6 @@ public:
private:
int relocateLocal(SegmentId segment, int location);
int relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location);
- int relocateObject(Object &obj, SegmentId segment, int location);
public:
// script lock operations
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 7b6763f8f2..d37628da20 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -120,7 +120,7 @@ static reg_t &validate_property(Object *obj, int index) {
return dummyReg;
}
- return obj->_variables[index];
+ return obj->getVariable(index);
}
static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) {
@@ -1758,8 +1758,7 @@ void quit_vm() {
reg_t* ObjVarRef::getPointer(SegManager *segMan) const {
Object *o = segMan->getObject(obj);
- if (!o) return 0;
- return &(o->_variables[varindex]);
+ return o ? &o->getVariable(varindex) : 0;
}
reg_t* ExecStack::getVarPointer(SegManager *segMan) const {