aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/script.cpp
diff options
context:
space:
mode:
authorMax Horn2010-02-02 22:50:32 +0000
committerMax Horn2010-02-02 22:50:32 +0000
commit6c322506dd15b164028f8c560e55323f1b834711 (patch)
tree2e233495329c36bb5df7c38215f0a6d89ac07a67 /engines/sci/engine/script.cpp
parent5d80990380a8438dc474cdd5778807b7a72e2501 (diff)
downloadscummvm-rg350-6c322506dd15b164028f8c560e55323f1b834711.tar.gz
scummvm-rg350-6c322506dd15b164028f8c560e55323f1b834711.tar.bz2
scummvm-rg350-6c322506dd15b164028f8c560e55323f1b834711.zip
SCI: Move some code around (no code changes)
svn-id: r47823
Diffstat (limited to 'engines/sci/engine/script.cpp')
-rw-r--r--engines/sci/engine/script.cpp602
1 files changed, 289 insertions, 313 deletions
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 1c898da4e5..604aff557c 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -91,6 +91,8 @@ opcode_format g_opcode_formats[128][4] = {
};
#undef END
+// TODO: script_adjust_opcode_formats should probably be part of the
+// constructor (?) of a VirtualMachine or a ScriptManager class.
void script_adjust_opcode_formats(EngineState *s) {
// TODO: Check that this is correct
if (s->detectLofsType() != SCI_VERSION_0_EARLY) {
@@ -112,380 +114,354 @@ void script_adjust_opcode_formats(EngineState *s) {
#endif
}
-#if 1
+#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segMan->getClassAddress(id, SCRIPT_GET_LOCK, reg))
-#define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_)
-#define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_)
+int script_instantiate_common(ResourceManager *resMan, SegManager *segMan, int script_nr, Resource **script, Resource **heap, int *was_new) {
+ *was_new = 1;
-#else
+ *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
+ if (getSciVersion() >= SCI_VERSION_1_1)
+ *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
-// The defines below can be used to construct static selector tables for games which don't have
-// a vocab.997 resource, by dumping the selector table from other similar versions or games
-#define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_); \
- printf("\t{ \"%s\", %d },\n", #_slc_, _selectorCache._slc_)
+ if (!*script || (getSciVersion() >= SCI_VERSION_1_1 && !heap)) {
+ warning("Script 0x%x requested but not found", script_nr);
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ if (*heap)
+ warning("Inconsistency: heap resource WAS found");
+ else if (*script)
+ warning("Inconsistency: script resource WAS found");
+ }
+ return 0;
+ }
-#define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_); \
- printf("\t{ \"%s\", %d },\n", _slcstr_, _selectorCache._slc_)
+ SegmentId seg_id = segMan->getScriptSegment(script_nr);
+ Script *scr = segMan->getScriptIfLoaded(seg_id);
+ if (scr) {
+ if (!scr->isMarkedAsDeleted()) {
+ scr->incrementLockers();
+ return seg_id;
+ } else {
+ scr->freeScript();
+ }
+ } else {
+ scr = segMan->allocateScript(script_nr, &seg_id);
+ if (!scr) { // ALL YOUR SCRIPT BASE ARE BELONG TO US
+ error("Not enough heap space for script size 0x%x of script 0x%x (Should this happen?)", (*script)->size, script_nr);
+ return 0;
+ }
+ }
-#endif
+ scr->init(script_nr, resMan);
-void Kernel::mapSelectors() {
- // species
- // superClass
- // -info-
- FIND_SELECTOR(y);
- FIND_SELECTOR(x);
- FIND_SELECTOR(view);
- FIND_SELECTOR(loop);
- FIND_SELECTOR(cel);
- FIND_SELECTOR(underBits);
- FIND_SELECTOR(nsTop);
- FIND_SELECTOR(nsLeft);
- FIND_SELECTOR(nsBottom);
- FIND_SELECTOR(lsTop);
- FIND_SELECTOR(lsLeft);
- FIND_SELECTOR(lsBottom);
- FIND_SELECTOR(lsRight);
- FIND_SELECTOR(nsRight);
- FIND_SELECTOR(signal);
- FIND_SELECTOR(illegalBits);
- FIND_SELECTOR(brTop);
- FIND_SELECTOR(brLeft);
- FIND_SELECTOR(brBottom);
- FIND_SELECTOR(brRight);
- // name
- // key
- // time
- FIND_SELECTOR(text);
- FIND_SELECTOR(elements);
- // color
- // back
- FIND_SELECTOR(mode);
- // style
- FIND_SELECTOR(state);
- FIND_SELECTOR(font);
- FIND_SELECTOR(type);
- // window
- FIND_SELECTOR(cursor);
- FIND_SELECTOR(max);
- // mark
- // who
- FIND_SELECTOR(message);
- // edit
- FIND_SELECTOR(play);
- FIND_SELECTOR(number);
- FIND_SELECTOR(handle); // nodePtr
- FIND_SELECTOR(client);
- FIND_SELECTOR(dx);
- FIND_SELECTOR(dy);
- FIND_SELECTOR2(b_movCnt, "b-moveCnt");
- FIND_SELECTOR2(b_i1, "b-i1");
- FIND_SELECTOR2(b_i2, "b-i2");
- FIND_SELECTOR2(b_di, "b-di");
- FIND_SELECTOR2(b_xAxis, "b-xAxis");
- FIND_SELECTOR2(b_incr, "b-incr");
- FIND_SELECTOR(xStep);
- FIND_SELECTOR(yStep);
- FIND_SELECTOR(moveSpeed);
- FIND_SELECTOR(canBeHere); // cantBeHere
- FIND_SELECTOR(heading);
- FIND_SELECTOR(mover);
- FIND_SELECTOR(doit);
- FIND_SELECTOR(isBlocked);
- FIND_SELECTOR(looper);
- FIND_SELECTOR(priority);
- FIND_SELECTOR(modifiers);
- FIND_SELECTOR(replay);
- // setPri
- // at
- // next
- // done
- // width
- FIND_SELECTOR(wordFail);
- FIND_SELECTOR(syntaxFail);
- // semanticFail
- // pragmaFail
- // said
- FIND_SELECTOR(claimed);
- // value
- // save
- // restore
- // title
- // button
- // icon
- // draw
- FIND_SELECTOR2(delete_, "delete");
- FIND_SELECTOR(z);
- // -----------------------------
- FIND_SELECTOR(size);
- FIND_SELECTOR(moveDone);
- FIND_SELECTOR(vol);
- FIND_SELECTOR(pri);
- FIND_SELECTOR(min);
- FIND_SELECTOR(sec);
- FIND_SELECTOR(frame);
- FIND_SELECTOR(dataInc);
- FIND_SELECTOR(palette);
- FIND_SELECTOR(cantBeHere);
- FIND_SELECTOR(nodePtr);
- FIND_SELECTOR(flags);
- FIND_SELECTOR(points);
- FIND_SELECTOR(syncCue);
- FIND_SELECTOR(syncTime);
- FIND_SELECTOR(printLang);
- FIND_SELECTOR(subtitleLang);
- FIND_SELECTOR(parseLang);
- FIND_SELECTOR(overlay);
- FIND_SELECTOR(setCursor);
- FIND_SELECTOR(topString);
- FIND_SELECTOR(scaleSignal);
- FIND_SELECTOR(scaleX);
- FIND_SELECTOR(scaleY);
+ reg_t reg;
+ reg.segment = seg_id;
+ reg.offset = 0;
-#ifdef ENABLE_SCI32
- FIND_SELECTOR(data);
- FIND_SELECTOR(picture);
- FIND_SELECTOR(plane);
- FIND_SELECTOR(top);
- FIND_SELECTOR(left);
-#endif
+ // Set heap position (beyond the size word)
+ scr->setLockers(1);
+ scr->setExportTableOffset(0);
+ scr->setSynonymsOffset(0);
+ scr->setSynonymsNr(0);
+
+ *was_new = 0;
+
+ return seg_id;
}
-void Kernel::dumpScriptObject(char *data, int seeker, int objsize) {
- int selectors, overloads, selectorsize;
- int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker);
- int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker);
- int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker);
- int i = 0;
+int script_instantiate_sci0(ResourceManager *resMan, SegManager *segMan, int script_nr) {
+ int objtype;
+ unsigned int objlength;
+ int relocation = -1;
+ int magic_pos_adder; // Usually 0; 2 for older SCI versions
+ Resource *script;
+ int was_new;
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+
+ const int seg_id = script_instantiate_common(resMan, segMan, script_nr, &script, NULL, &was_new);
+
+ if (was_new)
+ return seg_id;
- printf("Object\n");
+ Script *scr = segMan->getScript(seg_id);
- Common::hexdump((unsigned char *) data + seeker, objsize - 4, 16, seeker);
- //-4 because the size includes the two-word header
+ if (oldScriptHeader) {
+ //
+ int locals_nr = READ_LE_UINT16(script->data);
- printf("Name: %s\n", namepos ? ((char *)(data + namepos)) : "<unknown>");
- printf("Superclass: %x\n", superclass);
- printf("Species: %x\n", species);
- printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *) data + 12 + seeker) & 0xffff);
+ // Old script block
+ // There won't be a localvar block in this case
+ // Instead, the script starts with a 16 bit int specifying the
+ // number of locals we need; these are then allocated and zeroed.
- printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *) data + seeker + 4));
- printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *) data + seeker + 6)));
+ scr->mcpyInOut(0, script->data, script->size);
+ magic_pos_adder = 2; // Step over the funny prefix
- seeker += 8;
+ if (locals_nr)
+ segMan->scriptInitialiseLocalsZero(seg_id, locals_nr);
- while (selectors--) {
- printf(" [#%03x] = 0x%x\n", i++, (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff);
- seeker += 2;
+ } else {
+ scr->mcpyInOut(0, script->data, script->size);
+ magic_pos_adder = 0;
}
- printf("Overridden functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker));
+ // Now do a first pass through the script objects to find the
+ // export table and local variable block
- seeker += 2;
+ reg_t reg;
+ reg.segment = seg_id;
+ reg.offset = magic_pos_adder;
- if (overloads < 100)
- while (overloads--) {
- int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker));
+ objlength = 0;
- printf(" [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>");
- printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors*2 + 2) & 0xffff);
+ do {
+ reg_t data_base;
+ reg_t addr;
+ reg.offset += objlength; // Step over the last checked object
+ objtype = scr->getHeap(reg.offset);
+ if (!objtype)
+ break;
+
+ objlength = scr->getHeap(reg.offset + 2);
- seeker += 2;
+ // This happens in some demos (e.g. the EcoQuest 1 demo). Not sure what is the
+ // actual cause of it, but the scripts of these demos can't be loaded properly
+ // and we're stuck forever in this loop, as objlength never changes
+ if (!objlength) {
+ warning("script_instantiate_sci0: objlength is 0, unable to parse script");
+ return 0;
}
-}
-void Kernel::dumpScriptClass(char *data, int seeker, int objsize) {
- int selectors, overloads, selectorsize;
- int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker);
- int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker);
- int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker);
+ data_base = reg;
+ data_base.offset += 4;
- printf("Class\n");
+ addr = data_base;
- Common::hexdump((unsigned char *) data + seeker, objsize - 4, 16, seeker);
+ switch (objtype) {
+ case SCI_OBJ_EXPORTS: {
+ scr->setExportTableOffset(data_base.offset);
+ }
+ break;
+
+ case SCI_OBJ_SYNONYMS:
+ scr->setSynonymsOffset(addr.offset); // +4 is to step over the header
+ scr->setSynonymsNr((objlength) / 4);
+ break;
+
+ case SCI_OBJ_LOCALVARS:
+ segMan->scriptInitialiseLocals(data_base);
+ break;
- printf("Name: %s\n", namepos ? ((char *)data + namepos) : "<unknown>");
- printf("Superclass: %x\n", superclass);
- printf("Species: %x\n", species);
- printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *)data + 12 + seeker) & 0xffff);
+ case SCI_OBJ_CLASS: {
+ int classpos = addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET;
+ int species;
+ species = scr->getHeap(addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET);
+ if (species < 0 || species >= (int)segMan->_classtable.size()) {
+ if (species == (int)segMan->_classtable.size()) {
+ // Happens in the LSL2 demo
+ warning("Applying workaround for an off-by-one invalid species access");
+ segMan->_classtable.resize(segMan->_classtable.size() + 1);
+ } else {
+ warning("Invalid species %d(0x%x) not in interval "
+ "[0,%d) while instantiating script %d\n",
+ species, species, segMan->_classtable.size(),
+ script_nr);
+ return 0;
+ }
+ }
- printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + 4));
- printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *)data + seeker + 6)));
+ segMan->_classtable[species].reg = addr;
+ segMan->_classtable[species].reg.offset = classpos;
+ // Set technical class position-- into the block allocated for it
+ }
+ break;
- seeker += 8;
- selectorsize <<= 1;
+ default:
+ break;
+ }
+ } while (objtype != 0);
- while (selectors--) {
- int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker) + selectorsize);
+ // And now a second pass to adjust objects and class pointers, and the general pointers
- printf(" [%03x] %s = 0x%x\n", 0xffff & selector, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>",
- (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff);
+ objlength = 0;
+ reg.offset = magic_pos_adder; // Reset counter
- seeker += 2;
- }
+ do {
+ reg_t addr;
+ reg.offset += objlength; // Step over the last checked object
+ objtype = scr->getHeap(reg.offset);
+ if (!objtype)
+ break;
- seeker += selectorsize;
+ objlength = scr->getHeap(reg.offset + 2);
- printf("Overloaded functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker));
+ addr = reg;
+ addr.offset += 4; // Step over header
- seeker += 2;
+ 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);
- while (overloads--) {
- int selector = (int16)READ_LE_UINT16((unsigned char *)data + (seeker));
- fprintf(stderr, "selector=%d; selectorNames.size() =%d\n", selector, _selectorNames.size());
- printf(" [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ?
- _selectorNames[selector].c_str() : "<?>");
- printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors * 2 + 2) & 0xffff);
+ // Instantiate the superclass, if neccessary
+ obj->setSpeciesSelector(INST_LOOKUP_CLASS(obj->getSpeciesSelector().offset));
- seeker += 2;
- }
-}
+ Object *baseObj = segMan->getObject(obj->getSpeciesSelector());
-void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
- int objectctr[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- unsigned int _seeker = 0;
- Resource *script = _resMan->findResource(ResourceId(kResourceTypeScript, scriptNumber), 0);
+ if (baseObj) {
+ obj->setVarCount(baseObj->getVarCount());
+ // Copy base from species class, as we need its selector IDs
+ obj->_baseObj = baseObj->_baseObj;
- if (!script) {
- warning("dissectScript(): Script not found!\n");
- return;
- }
+ obj->setSuperClassSelector(INST_LOOKUP_CLASS(obj->getSuperClassSelector().offset));
+ } else {
+ warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
- while (_seeker < script->size) {
- int objtype = (int16)READ_LE_UINT16(script->data + _seeker);
- int objsize;
- unsigned int seeker = _seeker + 4;
+ scr->scriptObjRemove(addr);
+ }
+ } // if object or class
+ break;
+ case SCI_OBJ_POINTERS: // A relocation table
+ relocation = addr.offset;
+ break;
- if (!objtype) {
- printf("End of script object (#0) encountered.\n");
- printf("Classes: %i, Objects: %i, Export: %i,\n Var: %i (all base 10)",
- objectctr[6], objectctr[1], objectctr[7], objectctr[10]);
- return;
+ default:
+ break;
}
- printf("\n");
+ } while (objtype != 0 && reg.offset < script->size - 2);
+
+ if (relocation >= 0)
+ scr->scriptRelocate(make_reg(seg_id, relocation));
- objsize = (int16)READ_LE_UINT16(script->data + _seeker + 2);
+ return reg.segment; // instantiation successful
+}
- printf("Obj type #%x, size 0x%x: ", objtype, objsize);
+int script_instantiate_sci11(ResourceManager *resMan, SegManager *segMan, int script_nr) {
+ Resource *script, *heap;
+ int _heapStart;
+ reg_t reg;
+ int was_new;
- _seeker += objsize;
+ const int seg_id = script_instantiate_common(resMan, segMan, script_nr, &script, &heap, &was_new);
- objectctr[objtype]++;
+ if (was_new)
+ return seg_id;
- switch (objtype) {
- case SCI_OBJ_OBJECT:
- dumpScriptObject((char *)script->data, seeker, objsize);
- break;
+ Script *scr = segMan->getScript(seg_id);
- case SCI_OBJ_CODE: {
- printf("Code\n");
- Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ _heapStart = script->size;
+ if (script->size & 2)
+ _heapStart ++;
- case 3: {
- printf("<unknown>\n");
- Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ scr->mcpyInOut(0, script->data, script->size);
+ scr->mcpyInOut(_heapStart, heap->data, heap->size);
- case SCI_OBJ_SAID: {
- printf("Said\n");
- Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
-
- printf("%04x: ", seeker);
- while (seeker < _seeker) {
- unsigned char nextitem = script->data [seeker++];
- if (nextitem == 0xFF)
- printf("\n%04x: ", seeker);
- else if (nextitem >= 0xF0) {
- switch (nextitem) {
- case 0xf0:
- printf(", ");
- break;
- case 0xf1:
- printf("& ");
- break;
- case 0xf2:
- printf("/ ");
- break;
- case 0xf3:
- printf("( ");
- break;
- case 0xf4:
- printf(") ");
- break;
- case 0xf5:
- printf("[ ");
- break;
- case 0xf6:
- printf("] ");
- break;
- case 0xf7:
- printf("# ");
- break;
- case 0xf8:
- printf("< ");
- break;
- case 0xf9:
- printf("> ");
- break;
- }
- } else {
- nextitem = nextitem << 8 | script->data [seeker++];
- printf("%s[%03x] ", vocab->getAnyWordFromGroup(nextitem), nextitem);
- }
- }
- printf("\n");
- }
- break;
+ if (READ_LE_UINT16(script->data + 6) > 0)
+ scr->setExportTableOffset(6);
- case SCI_OBJ_STRINGS: {
- printf("Strings\n");
- while (script->data [seeker]) {
- printf("%04x: %s\n", seeker, script->data + seeker);
- seeker += strlen((char *)script->data + seeker) + 1;
- }
- seeker++; // the ending zero byte
- };
- break;
+ reg.segment = seg_id;
+ reg.offset = _heapStart + 4;
+ segMan->scriptInitialiseLocals(reg);
+
+ segMan->scriptRelocateExportsSci11(seg_id);
+ segMan->scriptInitialiseObjectsSci11(seg_id);
+
+ reg.offset = READ_LE_UINT16(heap->data);
+ scr->heapRelocate(reg);
- case SCI_OBJ_CLASS:
- dumpScriptClass((char *)script->data, seeker, objsize);
+ return seg_id;
+}
+
+int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr) {
+ if (getSciVersion() >= SCI_VERSION_1_1)
+ return script_instantiate_sci11(resMan, segMan, script_nr);
+ else
+ return script_instantiate_sci0(resMan, segMan, script_nr);
+}
+
+void script_uninstantiate_sci0(SegManager *segMan, int script_nr, SegmentId seg) {
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+ reg_t reg = make_reg(seg, oldScriptHeader ? 2 : 0);
+ int objtype, objlength;
+ Script *scr = segMan->getScript(seg);
+
+ // Make a pass over the object in order uninstantiate all superclasses
+ objlength = 0;
+
+ do {
+ reg.offset += objlength; // Step over the last checked object
+
+ objtype = scr->getHeap(reg.offset);
+ if (!objtype)
break;
+ objlength = scr->getHeap(reg.offset + 2); // use SEG_UGET_HEAP ??
- case SCI_OBJ_EXPORTS: {
- printf("Exports\n");
- Common::hexdump((unsigned char *)script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ reg.offset += 4; // Step over header
- case SCI_OBJ_POINTERS: {
- printf("Pointers\n");
- Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ if ((objtype == SCI_OBJ_OBJECT) || (objtype == SCI_OBJ_CLASS)) { // object or class?
+ int superclass;
- case 9: {
- printf("<unknown>\n");
- Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ reg.offset -= SCRIPT_OBJECT_MAGIC_OFFSET;
- case SCI_OBJ_LOCALVARS: {
- printf("Local vars\n");
- Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
- };
- break;
+ superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass...
- default:
- printf("Unsupported!\n");
- return;
- }
+ if (superclass >= 0) {
+ int superclass_script = segMan->_classtable[superclass].script;
+
+ if (superclass_script == script_nr) {
+ if (scr->getLockers())
+ scr->decrementLockers(); // Decrease lockers if this is us ourselves
+ } else
+ script_uninstantiate(segMan, superclass_script);
+ // Recurse to assure that the superclass lockers number gets decreased
+ }
+
+ reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET;
+ } // if object or class
+
+ reg.offset -= 4; // Step back on header
+
+ } while (objtype != 0);
+}
+void script_uninstantiate(SegManager *segMan, int script_nr) {
+ SegmentId segment = segMan->getScriptSegment(script_nr);
+ Script *scr = segMan->getScriptIfLoaded(segment);
+
+ if (!scr) { // Is it already loaded?
+ //warning("unloading script 0x%x requested although not loaded", script_nr);
+ // This is perfectly valid SCI behaviour
+ return;
}
- printf("Script ends without terminator\n");
+ scr->decrementLockers(); // One less locker
+
+ if (scr->getLockers() > 0)
+ return;
+
+ // Free all classtable references to this script
+ for (uint i = 0; i < segMan->_classtable.size(); i++)
+ if (segMan->_classtable[i].reg.segment == segment)
+ segMan->_classtable[i].reg = NULL_REG;
+
+ if (getSciVersion() < SCI_VERSION_1_1)
+ 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;
}
+
} // End of namespace Sci