From 1c0bbb10cbb20b8dd0bdc1cb748bb5ec9e538b42 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 26 May 2010 08:27:24 +0000 Subject: 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 --- engines/sci/engine/script.cpp | 17 +----- engines/sci/engine/scriptdebug.cpp | 40 ++------------ engines/sci/engine/segment.cpp | 104 ++++++++++++++++++++++++++++++++++--- engines/sci/engine/segment.h | 36 +++++-------- engines/sci/engine/vm.cpp | 5 +- 5 files changed, 120 insertions(+), 82 deletions(-) (limited to 'engines/sci') 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 _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 _variables; uint16 _methodCount; int _flags; uint16 _offset; @@ -414,7 +405,6 @@ public: private: int relocateLocal(SegmentId segment, int location); int relocateBlock(Common::Array &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 { -- cgit v1.2.3