aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorWillem Jan Palenstijn2013-10-27 01:17:28 +0200
committerWillem Jan Palenstijn2013-12-14 14:19:33 +0100
commit78e7f5b51c04a7751c9c6462a542257f817261d3 (patch)
tree1b952b4568c2a6f2d78320e8b39c7e8c2889e5c7 /engines/sci/engine
parenta917e9d6fe96cbf4ffb3521fdedf6f9ad5e6fe30 (diff)
downloadscummvm-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.
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/object.cpp1
-rw-r--r--engines/sci/engine/savegame.cpp37
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());
+ }
}
}
}