diff options
author | Filippos Karapetis | 2010-05-26 08:27:24 +0000 |
---|---|---|
committer | Filippos Karapetis | 2010-05-26 08:27:24 +0000 |
commit | 1c0bbb10cbb20b8dd0bdc1cb748bb5ec9e538b42 (patch) | |
tree | 1e81f1578e48386f02fc5bb426c134ebe59b2362 /engines/sci/engine/segment.cpp | |
parent | 60dd3106885b9784af15cb96122d28a5f0bf33f1 (diff) | |
download | scummvm-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
Diffstat (limited to 'engines/sci/engine/segment.cpp')
-rw-r--r-- | engines/sci/engine/segment.cpp | 104 |
1 files changed, 98 insertions, 6 deletions
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) { |