aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/script.cpp
diff options
context:
space:
mode:
authorFilippos Karapetis2010-06-14 19:37:19 +0000
committerFilippos Karapetis2010-06-14 19:37:19 +0000
commit86878450ee26cbf2b4f79e5e54787fe5cce2a10e (patch)
tree06f3917c9a644aded5fa7d846503e1f9886e576a /engines/sci/engine/script.cpp
parent303c7b0a8dd0fb120f1fa1ec0abb03b27912e8a5 (diff)
downloadscummvm-rg350-86878450ee26cbf2b4f79e5e54787fe5cce2a10e.tar.gz
scummvm-rg350-86878450ee26cbf2b4f79e5e54787fe5cce2a10e.tar.bz2
scummvm-rg350-86878450ee26cbf2b4f79e5e54787fe5cce2a10e.zip
Cleanup of the SCI0 object initialization code
svn-id: r49666
Diffstat (limited to 'engines/sci/engine/script.cpp')
-rw-r--r--engines/sci/engine/script.cpp148
1 files changed, 63 insertions, 85 deletions
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 6dfd39a496..c1810df679 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -192,8 +192,7 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) {
return;
}
- _classTable[species].reg.segment = seg;
- _classTable[species].reg.offset = classpos;
+ setClassOffset(species, make_reg(seg, classpos));
}
seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2;
}
@@ -231,85 +230,69 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) {
void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) {
int objType;
- uint32 objLength = 0;
+ reg_t addr;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
- uint16 curOffset = oldScriptHeader ? 2 : 0;
- // Now do a first pass through the script objects to find all the object classes
-
- do {
- objType = scr->getHeap(curOffset);
- if (!objType)
- break;
-
- objLength = scr->getHeap(curOffset + 2);
- curOffset += 4; // skip header
-
- switch (objType) {
- case SCI_OBJ_CLASS: {
- int classpos = curOffset - SCRIPT_OBJECT_MAGIC_OFFSET;
- int species = scr->getHeap(curOffset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET);
- if (species < 0 || species >= (int)segMan->classTableSize()) {
- if (species == (int)segMan->classTableSize()) {
- // Happens in the LSL2 demo
- warning("Applying workaround for an off-by-one invalid species access");
- segMan->resizeClassTable(segMan->classTableSize() + 1);
- } else {
- error("Invalid species %d(0x%x) not in interval "
- "[0,%d) while instantiating script at segment %d\n",
- species, species, segMan->classTableSize(),
- segmentId);
- return;
+ // The script is initialized in 2 passes.
+ // Pass 1: creates a lookup table of all used classes
+ // Pass 2: loads classes and objects
+
+ for (uint16 pass = 0; pass <= 1; pass++) {
+ uint16 objLength = 0;
+ uint16 curOffset = oldScriptHeader ? 2 : 0;
+
+ do {
+ objType = scr->getHeap(curOffset);
+ if (!objType)
+ break;
+
+ objLength = scr->getHeap(curOffset + 2);
+ curOffset += 4; // skip header
+ addr = make_reg(segmentId, curOffset);;
+
+ switch (objType) {
+ case SCI_OBJ_CODE:
+ if (pass == 0)
+ scr->scriptAddCodeBlock(addr);
+ break;
+ case SCI_OBJ_OBJECT:
+ case SCI_OBJ_CLASS:
+ if (pass == 0 && objType == SCI_OBJ_CLASS) {
+ int classpos = curOffset + 8; // SCRIPT_OBJECT_MAGIC_OFFSET
+ int species = scr->getHeap(classpos);
+
+ if (species == (int)segMan->classTableSize()) {
+ // Happens in the LSL2 demo
+ warning("Applying workaround for an off-by-one invalid species access");
+ segMan->resizeClassTable(segMan->classTableSize() + 1);
+ } else if (species < 0 || species > (int)segMan->classTableSize()) {
+ error("Invalid species %d(0x%x) not in interval "
+ "[0,%d) while instantiating script at segment %d\n",
+ species, species, segMan->classTableSize(),
+ segmentId);
+ return;
+ }
+
+ segMan->setClassOffset(species, make_reg(segmentId, classpos));
+ } else if (pass == 1) {
+ Object *obj = scr->scriptObjInit(addr);
+ obj->initSpecies(segMan, addr);
+
+ if (!obj->initBaseObject(segMan, addr)) {
+ warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
+ scr->scriptObjRemove(addr);
+ }
}
- }
-
- segMan->setClassOffset(species, make_reg(segmentId, classpos));
- // Set technical class position-- into the block allocated for it
- }
- break;
-
- default:
- break;
- }
-
- curOffset += objLength - 4;
- } while (objType != 0 && curOffset < scr->getScriptSize() - 2);
-
- // And now a second pass to adjust objects and class pointers, and the general pointers
- objLength = 0;
- curOffset = oldScriptHeader ? 2 : 0;
-
- do {
- objType = scr->getHeap(curOffset);
- if (!objType)
- break;
-
- objLength = scr->getHeap(curOffset + 2);
- curOffset += 4; // skip header
+ break;
- reg_t addr = make_reg(segmentId, curOffset);
-
- switch (objType) {
- case SCI_OBJ_CODE:
- scr->scriptAddCodeBlock(addr);
- break;
- case SCI_OBJ_OBJECT:
- case SCI_OBJ_CLASS: { // object or class?
- Object *obj = scr->scriptObjInit(addr);
- obj->initSpecies(segMan, addr);
-
- if (!obj->initBaseObject(segMan, addr)) {
- warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
- scr->scriptObjRemove(addr);
+ default:
+ break;
}
- } // if object or class
- break;
- default:
- break;
- }
- curOffset += objLength - 4;
- } while (objType != 0 && curOffset < scr->getScriptSize() - 2);
+ curOffset += objLength - 4;
+ } while (objType != 0 && curOffset < scr->getScriptSize() - 2);
+ } // for
+
}
int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNum) {
@@ -411,16 +394,11 @@ void script_uninstantiate(SegManager *segMan, int script_nr) {
script_uninstantiate_sci0(segMan, script_nr, segment);
// FIXME: Add proper script uninstantiation for SCI 1.1
- if (scr->getLockers())
- return; // if xxx.lockers > 0
-
- // Otherwise unload it completely
- // Explanation: I'm starting to believe that this work is done by SCI itself.
- scr->markDeleted();
-
- debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr);
-
- return;
+ if (!scr->getLockers()) {
+ // The actual script deletion seems to be done by SCI scripts themselves
+ scr->markDeleted();
+ debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr);
+ }
}