diff options
author | Willem Jan Palenstijn | 2013-10-27 01:17:28 +0200 |
---|---|---|
committer | Willem Jan Palenstijn | 2013-12-14 14:19:33 +0100 |
commit | 78e7f5b51c04a7751c9c6462a542257f817261d3 (patch) | |
tree | 1b952b4568c2a6f2d78320e8b39c7e8c2889e5c7 | |
parent | a917e9d6fe96cbf4ffb3521fdedf6f9ad5e6fe30 (diff) | |
download | scummvm-rg350-78e7f5b51c04a7751c9c6462a542257f817261d3.tar.gz scummvm-rg350-78e7f5b51c04a7751c9c6462a542257f817261d3.tar.bz2 scummvm-rg350-78e7f5b51c04a7751c9c6462a542257f817261d3.zip |
SCI: Make second pass when loading objects
This is because objects may be loaded before their base objects,
which causes initBaseObject to fail for SCI0.
Script::initializeObjectsSci0 already did this, but
SegManager::saveLoadWithSerializer did not when calling
initBaseObject after loading a savegame.
-rw-r--r-- | engines/sci/engine/object.cpp | 1 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 37 |
2 files changed, 22 insertions, 16 deletions
diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp index b28026b71f..6f219b388e 100644 --- a/engines/sci/engine/object.cpp +++ b/engines/sci/engine/object.cpp @@ -175,6 +175,7 @@ bool Object::initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClas _variables.resize(baseObj->getVarCount()); // Copy base from species class, as we need its selector IDs _baseObj = baseObj->_baseObj; + assert(_baseObj); if (doInitSuperClass) initSuperClass(segMan, addr); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 16b88b5672..ce9a672572 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -219,25 +219,30 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { syncArray<Class>(s, _classTable); - // Now that all scripts are loaded, init their objects - for (uint i = 0; i < _heap.size(); i++) { - if (!_heap[i] || _heap[i]->getType() != SEG_TYPE_SCRIPT) - continue; + // Now that all scripts are loaded, init their objects. + // Just like in Script::initializeObjectsSci0, we do two passes + // in case an object is loaded before its base. + int passes = getSciVersion() < SCI_VERSION_1_1 ? 2 : 1; + for (int pass = 1; pass <= passes; ++pass) { + for (uint i = 0; i < _heap.size(); i++) { + if (!_heap[i] || _heap[i]->getType() != SEG_TYPE_SCRIPT) + continue; - Script *scr = (Script *)_heap[i]; - scr->syncLocalsBlock(this); + Script *scr = (Script *)_heap[i]; + scr->syncLocalsBlock(this); - ObjMap objects = scr->getObjectMap(); - for (ObjMap::iterator it = objects.begin(); it != objects.end(); ++it) { - reg_t addr = it->_value.getPos(); - Object *obj = scr->scriptObjInit(addr, false); + ObjMap objects = scr->getObjectMap(); + for (ObjMap::iterator it = objects.begin(); it != objects.end(); ++it) { + reg_t addr = it->_value.getPos(); + Object *obj = scr->scriptObjInit(addr, false); - if (getSciVersion() < SCI_VERSION_1_1) { - if (!obj->initBaseObject(this, addr, false)) { - // TODO/FIXME: This should not be happening at all. It might indicate a possible issue - // with the garbage collector. It happens for example in LSL5 (German, perhaps English too). - warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - objects.erase(addr.toUint16()); + if (pass == 2) { + if (!obj->initBaseObject(this, addr, false)) { + // TODO/FIXME: This should not be happening at all. It might indicate a possible issue + // with the garbage collector. It happens for example in LSL5 (German, perhaps English too). + warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + objects.erase(addr.toUint16()); + } } } } |