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/segment.cpp | 104 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 6 deletions(-) (limited to 'engines/sci/engine/segment.cpp') 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) { -- cgit v1.2.3 From bfaba64c6a3aee6875bf135147c2f29a621c876b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 26 May 2010 14:25:51 +0000 Subject: Made find_unique_script_block() a member of the Script class svn-id: r49241 --- engines/sci/engine/segment.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 0c468a3cc2..b26ac4f78e 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -395,6 +395,30 @@ int Script::getSynonymsNr() const { return _numSynonyms; } +byte *Script::findBlock(int type) { + byte *buf = _buf; + bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); + + if (oldScriptHeader) + buf += 2; + + do { + int seekerType = READ_LE_UINT16(buf); + + if (seekerType == 0) + break; + if (seekerType == type) + return buf; + + int seekerSize = READ_LE_UINT16(buf + 2); + assert(seekerSize > 0); + buf += seekerSize; + } while (1); + + return NULL; +} + + // memory operations void Script::mcpyInOut(int dst, const void *src, size_t n) { -- cgit v1.2.3 From 0197e9f6a19738054a4b847e3217cd3794ef3ce3 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 26 May 2010 16:30:10 +0000 Subject: SCI: Making various object and script related things const svn-id: r49246 --- engines/sci/engine/segment.cpp | 73 ++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 34 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index b26ac4f78e..c43c195e6b 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -194,6 +194,13 @@ Object *Script::getObject(uint16 offset) { return 0; } +const Object *Script::getObject(uint16 offset) const { + if (_objects.contains(offset)) + return &_objects[offset]; + else + return 0; +} + Object *Script::scriptObjInit(reg_t obj_pos) { Object *obj; @@ -355,8 +362,8 @@ void Script::setLockers(int lockers) { void Script::setExportTableOffset(int offset) { if (offset) { - _exportTable = (uint16 *)(_buf + offset + 2); - _numExports = READ_SCI11ENDIAN_UINT16((byte *)(_exportTable - 1)); + _exportTable = (const uint16 *)(_buf + offset + 2); + _numExports = READ_SCI11ENDIAN_UINT16((const byte *)(_exportTable - 1)); } else { _exportTable = NULL; _numExports = 0; @@ -373,7 +380,7 @@ uint16 Script::validateExportFunc(int pubfunct) { if (exportsAreWide) pubfunct *= 2; - uint16 offset = READ_SCI11ENDIAN_UINT16((byte *)(_exportTable + pubfunct)); + uint16 offset = READ_SCI11ENDIAN_UINT16((const byte *)(_exportTable + pubfunct)); VERIFY(offset < _bufSize, "invalid export function pointer"); return offset; @@ -383,7 +390,7 @@ void Script::setSynonymsOffset(int offset) { _synonyms = _buf + offset; } -byte *Script::getSynonyms() const { +const byte *Script::getSynonyms() const { return _synonyms; } @@ -547,13 +554,13 @@ void Script::freeAtAddress(SegManager *segMan, reg_t addr) { segMan->deallocateScript(_nr); } -void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { +void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const { (*note)(param, make_reg(segId, 0)); } -void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) { +void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) { - Object *obj = getObject(addr.offset); + const Object *obj = getObject(addr.offset); if (obj) { // Note all local variables, if we have a local variable environment if (_localsSegment) @@ -573,16 +580,14 @@ void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback not //-------------------- clones -------------------- -void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) { - Clone *clone; - +void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { // assert(addr.segment == _segId); if (!isValidEntry(addr.offset)) { error("Unexpected request for outgoing references from clone at %04x:%04x", PRINT_REG(addr)); } - clone = &(_table[addr.offset]); + const Clone *clone = &(_table[addr.offset]); // Emit all member variables (including references to the 'super' delegate) for (uint i = 0; i < clone->getVarCount(); i++) @@ -626,7 +631,7 @@ reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) { return make_reg(owner_seg, 0); } -void LocalVariables::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) { +void LocalVariables::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { // assert(addr.segment == _segId); for (uint i = 0; i < _locals.size(); i++) @@ -640,7 +645,7 @@ reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) { return addr; } -void DataStack::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) { +void DataStack::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { fprintf(stderr, "Emitting %d stack entries\n", _capacity); for (int i = 0; i < _capacity; i++) (*note)(param, _entries[i]); @@ -653,13 +658,13 @@ void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { freeEntry(sub_addr.offset); } -void ListTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) { +void ListTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { if (!isValidEntry(addr.offset)) { warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); return; } - List *list = &(_table[addr.offset]); + const List *list = &(_table[addr.offset]); note(param, list->first); note(param, list->last); @@ -673,12 +678,12 @@ void NodeTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { freeEntry(sub_addr.offset); } -void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) { +void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { if (!isValidEntry(addr.offset)) { warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); return; } - Node *node = &(_table[addr.offset]); + const Node *node = &(_table[addr.offset]); // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us // to walk around from any given node @@ -694,19 +699,19 @@ 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); + byte *data = 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)); + _baseVars = (const uint16 *)(_baseObj + _variables.size() * 2); + _baseMethod = (const 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)); + _baseVars = (const uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 4)); + _baseMethod = (const uint16 *)(buf + READ_SCI11ENDIAN_UINT16(data + 6)); _methodCount = READ_SCI11ENDIAN_UINT16(_baseMethod); } @@ -714,12 +719,12 @@ void Object::init(byte *buf, reg_t obj_pos) { _variables[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(data + (i * 2))); } -Object *Object::getClass(SegManager *segMan) { +const Object *Object::getClass(SegManager *segMan) const { return isClass() ? this : segMan->getObject(getSuperClassSelector()); } -int Object::locateVarSelector(SegManager *segMan, Selector slc) { - byte *buf; +int Object::locateVarSelector(SegManager *segMan, Selector slc) const { + const byte *buf; uint varnum; if (getSciVersion() < SCI_VERSION_1_1) { @@ -727,7 +732,7 @@ int Object::locateVarSelector(SegManager *segMan, Selector slc) { int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET; buf = _baseObj + selector_name_offset; } else { - Object *obj = getClass(segMan); + const Object *obj = getClass(segMan); varnum = obj->getVariable(1).toUint16(); buf = (byte *)obj->_baseVars; } @@ -761,7 +766,7 @@ bool Object::relocate(SegmentId segment, int location, size_t scriptSize) { return true; } -int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) { +int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) const { int selectors = getVarCount(); if (propertyOffset < 0 || (propertyOffset >> 1) >= selectors) { @@ -771,14 +776,14 @@ int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) { } if (getSciVersion() < SCI_VERSION_1_1) { - byte *selectoroffset = ((byte *)(_baseObj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2; + const byte *selectoroffset = ((const byte *)(_baseObj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2; return READ_SCI11ENDIAN_UINT16(selectoroffset + propertyOffset); } else { - Object *obj = this; + const Object *obj = this; if (!(getInfoSelector().offset & SCRIPT_INFO_CLASS)) obj = segMan->getObject(getSuperClassSelector()); - return READ_SCI11ENDIAN_UINT16((byte *)obj->_baseVars + propertyOffset); + return READ_SCI11ENDIAN_UINT16((const byte *)obj->_baseVars + propertyOffset); } } @@ -801,7 +806,7 @@ void Object::initSuperClass(SegManager *segMan, reg_t addr) { } bool Object::initBaseObject(SegManager *segMan, reg_t addr) { - Object *baseObj = segMan->getObject(getSpeciesSelector()); + const Object *baseObj = segMan->getObject(getSpeciesSelector()); if (baseObj) { setVarCount(baseObj->getVarCount()); @@ -821,7 +826,7 @@ reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) { return addr; } -void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { +void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const { (*note)(param, make_reg(segId, 0)); } @@ -840,13 +845,13 @@ void ArrayTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { freeEntry(sub_addr.offset); } -void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) { +void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { if (!isValidEntry(addr.offset)) { warning("Invalid array referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); return; } - SciArray *array = &(_table[addr.offset]); + const SciArray *array = &(_table[addr.offset]); for (uint32 i = 0; i < array->getSize(); i++) { reg_t value = array->getValue(i); -- cgit v1.2.3 From db475d1501452490ab4e95ecbd181380b0bec414 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 26 May 2010 18:11:17 +0000 Subject: SCI: More const related changes; remove unnecessary casts which hide const issues svn-id: r49248 --- engines/sci/engine/segment.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index c43c195e6b..02d3a8987b 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -362,8 +362,8 @@ void Script::setLockers(int lockers) { void Script::setExportTableOffset(int offset) { if (offset) { - _exportTable = (const uint16 *)(_buf + offset + 2); - _numExports = READ_SCI11ENDIAN_UINT16((const byte *)(_exportTable - 1)); + _exportTable = (uint16 *)(_buf + offset + 2); + _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); } else { _exportTable = NULL; _numExports = 0; @@ -380,7 +380,7 @@ uint16 Script::validateExportFunc(int pubfunct) { if (exportsAreWide) pubfunct *= 2; - uint16 offset = READ_SCI11ENDIAN_UINT16((const byte *)(_exportTable + pubfunct)); + uint16 offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); VERIFY(offset < _bufSize, "invalid export function pointer"); return offset; @@ -538,7 +538,7 @@ SegmentRef SystemStrings::dereference(reg_t pointer) { //-------------------- script -------------------- -reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) { +reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) const { addr.offset = 0; return addr; } @@ -622,7 +622,7 @@ void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) { //-------------------- locals -------------------- -reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) { +reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) const { // Reference the owning script SegmentId owner_seg = segMan->getScriptSegment(script_id); @@ -640,7 +640,7 @@ void LocalVariables::listAllOutgoingReferences(reg_t addr, void *param, NoteCall //-------------------- stack -------------------- -reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) { +reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) const { addr.offset = 0; return addr; } @@ -821,7 +821,7 @@ bool Object::initBaseObject(SegManager *segMan, reg_t addr) { //-------------------- dynamic memory -------------------- -reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) { +reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) const { addr.offset = 0; return addr; } @@ -860,7 +860,7 @@ void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback } } -Common::String SciString::toString() { +Common::String SciString::toString() const { if (_type != 3) error("SciString::toString(): Array is not a string"); @@ -871,7 +871,7 @@ Common::String SciString::toString() { return string; } -void SciString::fromString(Common::String string) { +void SciString::fromString(const Common::String &string) { if (_type != 3) error("SciString::fromString(): Array is not a string"); -- cgit v1.2.3 From 42d6ed880b92e19c469c70da92397bd860abb483 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 29 May 2010 21:42:42 +0000 Subject: SCI: Make Script::_exportTable const (yay :-) svn-id: r49315 --- engines/sci/engine/segment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 02d3a8987b..17d0b67cf1 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -362,7 +362,7 @@ void Script::setLockers(int lockers) { void Script::setExportTableOffset(int offset) { if (offset) { - _exportTable = (uint16 *)(_buf + offset + 2); + _exportTable = (const uint16 *)(_buf + offset + 2); _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); } else { _exportTable = NULL; -- cgit v1.2.3 From 4ecacdad164d95154ac8a645058c2de0e2be73a9 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 29 May 2010 23:09:00 +0000 Subject: SCI: Merge Script::relocateBlock and Object::relocate The shared code now resides in a new static function named relocateBlock, which is invoked by the two methods. svn-id: r49316 --- engines/sci/engine/segment.cpp | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 17d0b67cf1..7e7da81125 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -225,33 +225,34 @@ void Script::scriptObjRemove(reg_t obj_pos) { _objects.erase(obj_pos.toUint16()); } -int Script::relocateBlock(Common::Array &block, int block_location, SegmentId segment, int location) { +// This helper function is used by Script::relocateLocal and Object::relocate +static bool relocateBlock(Common::Array &block, int block_location, SegmentId segment, int location, size_t scriptSize) { int rel = location - block_location; if (rel < 0) - return 0; + return false; uint idx = rel >> 1; if (idx >= block.size()) - return 0; + return false; if (rel & 1) { warning("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); - return 0; + return false; } block[idx].segment = segment; // Perform relocation if (getSciVersion() >= SCI_VERSION_1_1) - block[idx].offset += _scriptSize; + block[idx].offset += scriptSize; - return 1; + return true; } -int Script::relocateLocal(SegmentId segment, int location) { +bool Script::relocateLocal(SegmentId segment, int location) { if (_localsBlock) - return relocateBlock(_localsBlock->_locals, _localsOffset, segment, location); + return relocateBlock(_localsBlock->_locals, _localsOffset, segment, location, _scriptSize); else - return 0; // No hands, no cookies + return false; } void Script::scriptAddCodeBlock(reg_t location) { @@ -745,25 +746,7 @@ int Object::locateVarSelector(SegManager *segMan, Selector slc) const { } 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; + return relocateBlock(_variables, getPos().offset, segment, location, scriptSize); } int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) const { -- cgit v1.2.3 From dbe561c59b61f40459ed2b4602457308e0426269 Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Sun, 30 May 2010 10:27:39 +0000 Subject: Clarify reasoning behind hack in Script::scriptRelocate() svn-id: r49320 --- engines/sci/engine/segment.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 7e7da81125..8267de76bd 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -270,8 +270,14 @@ void Script::scriptRelocate(reg_t block) { for (int i = 0; i <= count; i++) { int pos = READ_SCI11ENDIAN_UINT16(_buf + block.offset + 2 + (i * 2)); + // This occurs in SCI01/SCI1 games where every other export + // value is zero. I have no idea what it's supposed to mean. + // + // Yes, there is code in the original to handle this situation, + // but we need an example of it happening in order to determine + // what to do. if (!pos) - continue; // FIXME: A hack pending investigation + continue; // FIXME: Just ignore it for now. if (!relocateLocal(block.segment, pos)) { bool done = false; -- cgit v1.2.3 From 5cdb13b3e8a160e7eae14c03644ad3be5a38b415 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 30 May 2010 16:38:08 +0000 Subject: Made load_script() a member of the Script class svn-id: r49328 --- engines/sci/engine/segment.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 8267de76bd..30cfe2d046 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -147,6 +147,27 @@ bool Script::init(int script_nr, ResourceManager *resMan) { return true; } +void Script::load(ResourceManager *resMan) { + Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0); + assert(script != 0); + + _buf = (byte *)malloc(_bufSize); + assert(_buf); + + assert(_bufSize >= script->size); + memcpy(_buf, script->data, script->size); + + if (getSciVersion() >= SCI_VERSION_1_1) { + Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0); + assert(heap != 0); + + _heapStart = _buf + _scriptSize; + + assert(_bufSize - _scriptSize <= heap->size); + memcpy(_heapStart, heap->data, heap->size); + } +} + void Script::setScriptSize(int script_nr, ResourceManager *resMan) { Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); -- cgit v1.2.3 From 29c2f30558e9c40d5c1a76ab600611b21ee72851 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 30 May 2010 17:02:21 +0000 Subject: Unified the script loading code, and marked an issue with the SCI11 heap addresses svn-id: r49329 --- engines/sci/engine/segment.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 30cfe2d046..8a9b953289 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -120,15 +120,6 @@ void Script::freeScript() { bool Script::init(int script_nr, ResourceManager *resMan) { setScriptSize(script_nr, resMan); - _buf = (byte *)malloc(_bufSize); - - if (!_buf) { - freeScript(); - warning("Not enough memory space for script size"); - _bufSize = 0; - return false; - } - _localsOffset = 0; _localsBlock = NULL; @@ -138,11 +129,8 @@ bool Script::init(int script_nr, ResourceManager *resMan) { _markedAsDeleted = false; _nr = script_nr; - - if (getSciVersion() >= SCI_VERSION_1_1) - _heapStart = _buf + _scriptSize; - else - _heapStart = _buf; + _buf = 0; + _heapStart = 0; return true; } -- cgit v1.2.3 From 016862ac3a4928529d9eaedf6edf3e916c89155c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 30 May 2010 18:45:07 +0000 Subject: Moved setScriptSize() inside Script::init(), and removed a FIXME - the SCI1.1 word-align is done inside Script::init() svn-id: r49330 --- engines/sci/engine/segment.cpp | 60 +++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 39 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 8a9b953289..a8c4eb73f6 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -117,8 +117,8 @@ void Script::freeScript() { _codeBlocks.clear(); } -bool Script::init(int script_nr, ResourceManager *resMan) { - setScriptSize(script_nr, resMan); +void Script::init(int script_nr, ResourceManager *resMan) { + Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); _localsOffset = 0; _localsBlock = NULL; @@ -132,7 +132,25 @@ bool Script::init(int script_nr, ResourceManager *resMan) { _buf = 0; _heapStart = 0; - return true; + _scriptSize = script->size; + _bufSize = script->size; + _heapSize = 0; + + if (getSciVersion() == SCI_VERSION_0_EARLY) { + _bufSize += READ_LE_UINT16(script->data) * 2; + } else if (getSciVersion() >= SCI_VERSION_1_1) { + Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); + _bufSize += heap->size; + _heapSize = heap->size; + + // Ensure that the start of the heap resource can be word-aligned. + if (script->size & 2) { + _bufSize++; + _scriptSize++; + } + + assert(_bufSize <= 65535); + } } void Script::load(ResourceManager *resMan) { @@ -156,42 +174,6 @@ void Script::load(ResourceManager *resMan) { } } -void Script::setScriptSize(int script_nr, ResourceManager *resMan) { - Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); - Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); - bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - - _scriptSize = script->size; - _heapSize = 0; // Set later - - if (!script || (getSciVersion() >= SCI_VERSION_1_1 && !heap)) { - error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap"); - } - if (oldScriptHeader) { - _bufSize = script->size + READ_LE_UINT16(script->data) * 2; - //locals_size = READ_LE_UINT16(script->data) * 2; - } else if (getSciVersion() < SCI_VERSION_1_1) { - _bufSize = script->size; - } else { - _bufSize = script->size + heap->size; - _heapSize = heap->size; - - // Ensure that the start of the heap resource can be word-aligned. - if (script->size & 2) { - _bufSize++; - _scriptSize++; - } - - if (_bufSize > 65535) { - error("Script and heap sizes combined exceed 64K." - "This means a fundamental design bug was made in SCI\n" - "regarding SCI1.1 games.\nPlease report this so it can be" - "fixed in the next major version"); - return; - } - } -} - Object *Script::allocateObject(uint16 offset) { return &_objects[offset]; } -- cgit v1.2.3 From dc4d61f7181edf332d426bab9d16e0055e3d0f21 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 30 May 2010 20:06:50 +0000 Subject: - Merged the SCI0 scriptRelocate() and SCI11 heapRelocate() functions inside relocate(). scriptRelocate checked one more relocation entry, which seems wrong, so we're now checking for the correct number of relocations in all SCI versions - Re-added the error when script + heap exceed 64KB (better than an assert) - this should theoretically never happen, and it never has for the games tested - Removed the relocated sanity check - again, it shouldn't occur (else something else is wrong) svn-id: r49332 --- engines/sci/engine/segment.cpp | 85 +++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 50 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index a8c4eb73f6..bdd9fbc966 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -100,7 +100,6 @@ Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { _localsSegment = 0; _localsBlock = NULL; - _relocated = false; _markedAsDeleted = 0; } @@ -125,7 +124,6 @@ void Script::init(int script_nr, ResourceManager *resMan) { _codeBlocks.clear(); - _relocated = false; _markedAsDeleted = false; _nr = script_nr; @@ -139,6 +137,14 @@ void Script::init(int script_nr, ResourceManager *resMan) { if (getSciVersion() == SCI_VERSION_0_EARLY) { _bufSize += READ_LE_UINT16(script->data) * 2; } else if (getSciVersion() >= SCI_VERSION_1_1) { + /** + * In SCI11, the heap was in a separate space from the script. + * We append it to the end of the script, and adjust addressing accordingly. + * However, since we address the heap with a 16-bit pointer, the combined + * size of the stack and the heap must be 64KB. So far this has worked + * for SCI11, SCI2 and SCI21 games. SCI3 games use a different script format, + * and theoretically they can exceed the 64KB boundary using relocation. + */ Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); _bufSize += heap->size; _heapSize = heap->size; @@ -149,7 +155,11 @@ void Script::init(int script_nr, ResourceManager *resMan) { _scriptSize++; } - assert(_bufSize <= 65535); + // As mentioned above, the script and the heap together should not exceed 64KB + if (_bufSize > 65535) + error("Script and heap sizes combined exceed 64K. This means a fundamental " + "design bug was made regarding SCI1.1 and newer games.\nPlease " + "report this error to the ScummVM team"); } } @@ -253,14 +263,24 @@ void Script::scriptAddCodeBlock(reg_t location) { _codeBlocks.push_back(cb); } -void Script::scriptRelocate(reg_t block) { - VERIFY(block.offset < (uint16)_bufSize && READ_SCI11ENDIAN_UINT16(_buf + block.offset) * 2 + block.offset < (uint16)_bufSize, +void Script::relocate(reg_t block) { + byte *heap = _buf; + uint16 heapSize = (uint16)_bufSize; + uint16 heapOffset = 0; + + if (getSciVersion() >= SCI_VERSION_1_1) { + heap = _heapStart; + heapSize = (uint16)_heapSize; + heapOffset = _scriptSize; + } + + VERIFY(block.offset < (uint16)heapSize && READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset < (uint16)heapSize, "Relocation block outside of script\n"); - int count = READ_SCI11ENDIAN_UINT16(_buf + block.offset); + int count = READ_SCI11ENDIAN_UINT16(heap + block.offset); - for (int i = 0; i <= count; i++) { - int pos = READ_SCI11ENDIAN_UINT16(_buf + block.offset + 2 + (i * 2)); + for (int i = 0; i < count; i++) { + int pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (i * 2)) + heapOffset; // This occurs in SCI01/SCI1 games where every other export // value is zero. I have no idea what it's supposed to mean. // @@ -281,10 +301,13 @@ void Script::scriptRelocate(reg_t block) { done = true; } - for (k = 0; !done && k < _codeBlocks.size(); k++) { - if (pos >= _codeBlocks[k].pos.offset && - pos < _codeBlocks[k].pos.offset + _codeBlocks[k].size) - done = true; + // Sanity check for SCI0-SCI1 + if (getSciVersion() < SCI_VERSION_1_1) { + for (k = 0; !done && k < _codeBlocks.size(); k++) { + if (pos >= _codeBlocks[k].pos.offset && + pos < _codeBlocks[k].pos.offset + _codeBlocks[k].size) + done = true; + } } if (!done) { @@ -303,44 +326,6 @@ void Script::scriptRelocate(reg_t block) { } } -void Script::heapRelocate(reg_t block) { - VERIFY(block.offset < (uint16)_heapSize && READ_SCI11ENDIAN_UINT16(_heapStart + block.offset) * 2 + block.offset < (uint16)_bufSize, - "Relocation block outside of script\n"); - - if (_relocated) - return; - _relocated = true; - int count = READ_SCI11ENDIAN_UINT16(_heapStart + block.offset); - - for (int i = 0; i < count; i++) { - int pos = READ_SCI11ENDIAN_UINT16(_heapStart + block.offset + 2 + (i * 2)) + _scriptSize; - - if (!relocateLocal(block.segment, pos)) { - bool done = false; - uint k; - - ObjMap::iterator it; - const ObjMap::iterator end = _objects.end(); - for (it = _objects.begin(); !done && it != end; ++it) { - if (it->_value.relocate(block.segment, pos, _scriptSize)) - done = true; - } - - if (!done) { - printf("While processing relocation block %04x:%04x:\n", PRINT_REG(block)); - printf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count); - if (_localsBlock) - printf("- locals: %d at %04x\n", _localsBlock->_locals.size(), _localsOffset); - else - printf("- No locals\n"); - for (it = _objects.begin(), k = 0; it != end; ++it, ++k) - printf("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount()); - error("Breakpoint in %s, line %d", __FILE__, __LINE__); - } - } - } -} - void Script::incrementLockers() { _lockers++; } -- cgit v1.2.3 From a0ee93ece52213cd989a50902281d917fe392ea4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 30 May 2010 21:49:07 +0000 Subject: SCI: Script exports and synonyms are now initialized when a script is loaded. Removed a sanity check inside script_instantiate_sci0 for a bug which no longer exists svn-id: r49336 --- engines/sci/engine/segment.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index bdd9fbc966..3653ff4ae9 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -27,6 +27,7 @@ #include "sci/sci.h" #include "sci/engine/features.h" +#include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS #include "sci/engine/segment.h" #include "sci/engine/seg_manager.h" #include "sci/engine/state.h" @@ -182,6 +183,28 @@ void Script::load(ResourceManager *resMan) { assert(_bufSize - _scriptSize <= heap->size); memcpy(_heapStart, heap->data, heap->size); } + + _codeBlocks.clear(); + + _exportTable = 0; + _numExports = 0; + _synonyms = 0; + _numSynonyms = 0; + + if (getSciVersion() >= SCI_VERSION_1_1) { + if (READ_LE_UINT16(_buf + 6) > 0) { + _exportTable = (const uint16 *)(_buf + 6 + 2); + _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); + } + } else { + _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS); + if (_exportTable) { + _exportTable += 3; + _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); + } + _synonyms = findBlock(SCI_OBJ_SYNONYMS); + _numSynonyms = _synonyms ? READ_SCI11ENDIAN_UINT16(_synonyms - 2) / 4 : 0; + } } Object *Script::allocateObject(uint16 offset) { @@ -343,16 +366,6 @@ void Script::setLockers(int lockers) { _lockers = lockers; } -void Script::setExportTableOffset(int offset) { - if (offset) { - _exportTable = (const uint16 *)(_buf + offset + 2); - _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); - } else { - _exportTable = NULL; - _numExports = 0; - } -} - uint16 Script::validateExportFunc(int pubfunct) { bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); @@ -369,18 +382,10 @@ uint16 Script::validateExportFunc(int pubfunct) { return offset; } -void Script::setSynonymsOffset(int offset) { - _synonyms = _buf + offset; -} - const byte *Script::getSynonyms() const { return _synonyms; } -void Script::setSynonymsNr(int n) { - _numSynonyms = n; -} - int Script::getSynonymsNr() const { return _numSynonyms; } -- cgit v1.2.3 From 4e25867a671a8847b167decba1ed1e95cf699e66 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 30 May 2010 23:00:32 +0000 Subject: SCI: Merge setLockers(1) call into Script::init svn-id: r49337 --- engines/sci/engine/segment.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 3653ff4ae9..3bec74398c 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -135,6 +135,8 @@ void Script::init(int script_nr, ResourceManager *resMan) { _bufSize = script->size; _heapSize = 0; + _lockers = 1; + if (getSciVersion() == SCI_VERSION_0_EARLY) { _bufSize += READ_LE_UINT16(script->data) * 2; } else if (getSciVersion() >= SCI_VERSION_1_1) { -- cgit v1.2.3 From 50cd1d1da4a934cfcdcf7cb0b05bed6f7d9735c2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 30 May 2010 23:31:33 +0000 Subject: Limited access to the script export table and synonyms block svn-id: r49338 --- engines/sci/engine/segment.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 3bec74398c..e1e7fd4ae6 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -384,14 +384,6 @@ uint16 Script::validateExportFunc(int pubfunct) { return offset; } -const byte *Script::getSynonyms() const { - return _synonyms; -} - -int Script::getSynonymsNr() const { - return _numSynonyms; -} - byte *Script::findBlock(int type) { byte *buf = _buf; bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); -- cgit v1.2.3 From 3f4302214c334a590b8428fe7ae32c76e64b6ed5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 31 May 2010 11:25:59 +0000 Subject: The save/load object init code is now unified with the regular object init code svn-id: r49346 --- engines/sci/engine/segment.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index e1e7fd4ae6..07fe6f0a92 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -227,10 +227,10 @@ const Object *Script::getObject(uint16 offset) const { return 0; } -Object *Script::scriptObjInit(reg_t obj_pos) { +Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { Object *obj; - if (getSciVersion() < SCI_VERSION_1_1) + if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit) obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n"); @@ -239,7 +239,7 @@ Object *Script::scriptObjInit(reg_t obj_pos) { VERIFY(obj_pos.offset + SCRIPT_FUNCTAREAPTR_OFFSET < (int)_bufSize, "Function area pointer stored beyond end of script\n"); - obj->init(_buf, obj_pos); + obj->init(_buf, obj_pos, fullObjectInit); return obj; } @@ -680,7 +680,7 @@ void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback //-------------------- object ---------------------------- -void Object::init(byte *buf, reg_t obj_pos) { +void Object::init(byte *buf, reg_t obj_pos, bool initVariables) { byte *data = buf + obj_pos.offset; _baseObj = data; _pos = obj_pos; @@ -697,8 +697,10 @@ void Object::init(byte *buf, reg_t obj_pos) { _methodCount = READ_SCI11ENDIAN_UINT16(_baseMethod); } - for (uint i = 0; i < _variables.size(); i++) - _variables[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(data + (i * 2))); + if (initVariables) { + for (uint i = 0; i < _variables.size(); i++) + _variables[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(data + (i * 2))); + } } const Object *Object::getClass(SegManager *segMan) const { @@ -769,14 +771,15 @@ void Object::initSuperClass(SegManager *segMan, reg_t addr) { setSuperClassSelector(segMan->getClassAddress(superClassOffset, SCRIPT_GET_LOCK, addr)); } -bool Object::initBaseObject(SegManager *segMan, reg_t addr) { +bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClass) { const Object *baseObj = segMan->getObject(getSpeciesSelector()); if (baseObj) { - setVarCount(baseObj->getVarCount()); + _variables.resize(baseObj->getVarCount()); // Copy base from species class, as we need its selector IDs _baseObj = baseObj->_baseObj; - initSuperClass(segMan, addr); + if (doInitSuperClass) + initSuperClass(segMan, addr); return true; } -- cgit v1.2.3 From de2e935b2c6ca2091e37068772931da1ec51ceb3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 31 May 2010 18:31:37 +0000 Subject: Wrote the initialization code for the exports and synonyms table to make more sense and fixed a bug with the initialization of the synonyms pointer, introduced with rev #49336 svn-id: r49360 --- engines/sci/engine/segment.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 07fe6f0a92..10d73d7325 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -194,18 +194,21 @@ void Script::load(ResourceManager *resMan) { _numSynonyms = 0; if (getSciVersion() >= SCI_VERSION_1_1) { - if (READ_LE_UINT16(_buf + 6) > 0) { - _exportTable = (const uint16 *)(_buf + 6 + 2); + if (READ_LE_UINT16(_buf + 1 + 5) > 0) { + _exportTable = (const uint16 *)(_buf + 1 + 5 + 2); _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); } } else { _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS); if (_exportTable) { - _exportTable += 3; - _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); + _numExports = READ_SCI11ENDIAN_UINT16(_exportTable + 1); + _exportTable += 3; // skip header plus 2 bytes (_exportTable is a uint16 pointer) } _synonyms = findBlock(SCI_OBJ_SYNONYMS); - _numSynonyms = _synonyms ? READ_SCI11ENDIAN_UINT16(_synonyms - 2) / 4 : 0; + if (_synonyms) { + _numSynonyms = READ_SCI11ENDIAN_UINT16(_synonyms + 2) / 4; + _synonyms += 4; // skip header + } } } -- cgit v1.2.3 From c4bdca72d7fcd837e51a449ff68a1d93977a0d18 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 2 Jun 2010 15:31:20 +0000 Subject: Fixed regression from commit #49332 (merging of the SCI0 and SCI11 relocate functions, where the SCI0 equivalent had a +1 count): it seems that we should skip over zero exports, however the total number of valid exports remains the same. Fixes KQ5 and QFG2. This also fixes the relocation calculation of script 71 in SQ3, so remove the comment that the script has broken relocation entries svn-id: r49394 --- engines/sci/engine/segment.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 10d73d7325..988ee67741 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -101,7 +101,7 @@ Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { _localsSegment = 0; _localsBlock = NULL; - _markedAsDeleted = 0; + _markedAsDeleted = false; } Script::~Script() { @@ -306,17 +306,20 @@ void Script::relocate(reg_t block) { "Relocation block outside of script\n"); int count = READ_SCI11ENDIAN_UINT16(heap + block.offset); + int exportIndex = 0; for (int i = 0; i < count; i++) { - int pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (i * 2)) + heapOffset; - // This occurs in SCI01/SCI1 games where every other export - // value is zero. I have no idea what it's supposed to mean. - // - // Yes, there is code in the original to handle this situation, - // but we need an example of it happening in order to determine - // what to do. - if (!pos) - continue; // FIXME: Just ignore it for now. + int pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; + // This occurs in SCI01/SCI1 games where every usually one export + // value is zero. It seems that in this situation, we should skip + // the export and move to the next one, though the total count + // of valid exports remains the same + if (!pos) { + exportIndex++; + pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; + if (!pos) + error("Script::relocate(): Consecutive zero exports found"); + } if (!relocateLocal(block.segment, pos)) { bool done = false; @@ -339,18 +342,19 @@ void Script::relocate(reg_t block) { } if (!done) { - printf("While processing relocation block %04x:%04x:\n", PRINT_REG(block)); - printf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count); + debug("While processing relocation block %04x:%04x:\n", PRINT_REG(block)); + debug("Relocation failed for index %04x (%d/%d)\n", pos, exportIndex + 1, count); if (_localsBlock) - printf("- locals: %d at %04x\n", _localsBlock->_locals.size(), _localsOffset); + debug("- locals: %d at %04x\n", _localsBlock->_locals.size(), _localsOffset); else - printf("- No locals\n"); + debug("- No locals\n"); for (it = _objects.begin(), k = 0; it != end; ++it, ++k) - printf("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount()); - // SQ3 script 71 has broken relocation entries. - printf("Trying to continue anyway...\n"); + debug("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount()); + debug("Trying to continue anyway...\n"); } } + + exportIndex++; } } -- cgit v1.2.3 From 86b452d36cb781c24e1b167dd6cef768b7c6286b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 3 Jun 2010 10:16:21 +0000 Subject: Moved several object-related defines inside vm.h into segment.h, where the Object class resides. Also, removed several unused defines svn-id: r49406 --- engines/sci/engine/segment.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/sci/engine/segment.cpp') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 988ee67741..0e0a759d4b 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -240,7 +240,7 @@ Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { obj = allocateObject(obj_pos.offset); - VERIFY(obj_pos.offset + SCRIPT_FUNCTAREAPTR_OFFSET < (int)_bufSize, "Function area pointer stored beyond end of script\n"); + VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n"); obj->init(_buf, obj_pos, fullObjectInit); @@ -693,9 +693,9 @@ void Object::init(byte *buf, reg_t obj_pos, bool initVariables) { _pos = obj_pos; if (getSciVersion() < SCI_VERSION_1_1) { - _variables.resize(READ_LE_UINT16(data + SCRIPT_SELECTORCTR_OFFSET)); + _variables.resize(READ_LE_UINT16(data + kOffsetSelectorCounter)); _baseVars = (const uint16 *)(_baseObj + _variables.size() * 2); - _baseMethod = (const uint16 *)(data + READ_LE_UINT16(data + SCRIPT_FUNCTAREAPTR_OFFSET)); + _baseMethod = (const uint16 *)(data + READ_LE_UINT16(data + kOffsetFunctionArea)); _methodCount = READ_LE_UINT16(_baseMethod - 1); } else { _variables.resize(READ_SCI11ENDIAN_UINT16(data + 2)); @@ -720,7 +720,7 @@ int Object::locateVarSelector(SegManager *segMan, Selector slc) const { if (getSciVersion() < SCI_VERSION_1_1) { varnum = getVarCount(); - int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET; + int selector_name_offset = varnum * 2 + kOffsetSelectorSegment; buf = _baseObj + selector_name_offset; } else { const Object *obj = getClass(segMan); @@ -749,11 +749,11 @@ int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) const { } if (getSciVersion() < SCI_VERSION_1_1) { - const byte *selectoroffset = ((const byte *)(_baseObj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2; + const byte *selectoroffset = ((const byte *)(_baseObj)) + kOffsetSelectorSegment + selectors * 2; return READ_SCI11ENDIAN_UINT16(selectoroffset + propertyOffset); } else { const Object *obj = this; - if (!(getInfoSelector().offset & SCRIPT_INFO_CLASS)) + if (!isClass()) obj = segMan->getObject(getSuperClassSelector()); return READ_SCI11ENDIAN_UINT16((const byte *)obj->_baseVars + propertyOffset); -- cgit v1.2.3