aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/vm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/vm.cpp')
-rw-r--r--engines/sci/engine/vm.cpp349
1 files changed, 0 insertions, 349 deletions
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 001f154974..859ebac0c5 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -1603,355 +1603,6 @@ void run_vm(EngineState *s, int restoring) {
}
}
-#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segMan->getClassAddress(id, SCRIPT_GET_LOCK, reg))
-
-int script_instantiate_common(ResourceManager *resMan, SegManager *segMan, int script_nr, Resource **script, Resource **heap, int *was_new) {
- *was_new = 1;
-
- *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
- if (getSciVersion() >= SCI_VERSION_1_1)
- *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
-
- 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;
- }
-
- 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;
- }
- }
-
- scr->init(script_nr, resMan);
-
- reg_t reg;
- reg.segment = seg_id;
- reg.offset = 0;
-
- // 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;
-}
-
-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;
-
- Script *scr = segMan->getScript(seg_id);
-
- if (oldScriptHeader) {
- //
- int locals_nr = READ_LE_UINT16(script->data);
-
- // 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.
-
- scr->mcpyInOut(0, script->data, script->size);
- magic_pos_adder = 2; // Step over the funny prefix
-
- if (locals_nr)
- segMan->scriptInitialiseLocalsZero(seg_id, locals_nr);
-
- } else {
- scr->mcpyInOut(0, script->data, script->size);
- magic_pos_adder = 0;
- }
-
- // Now do a first pass through the script objects to find the
- // export table and local variable block
-
- reg_t reg;
- reg.segment = seg_id;
- reg.offset = magic_pos_adder;
-
- objlength = 0;
-
- 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);
-
- // 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;
- }
-
- data_base = reg;
- data_base.offset += 4;
-
- addr = data_base;
-
- 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;
-
- 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;
- }
- }
-
- segMan->_classtable[species].reg = addr;
- segMan->_classtable[species].reg.offset = classpos;
- // Set technical class position-- into the block allocated for it
- }
- break;
-
- default:
- break;
- }
- } while (objtype != 0);
-
- // And now a second pass to adjust objects and class pointers, and the general pointers
-
- objlength = 0;
- reg.offset = magic_pos_adder; // Reset counter
-
- do {
- 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);
-
- addr = reg;
- addr.offset += 4; // Step over header
-
- 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);
-
- // Instantiate the superclass, if neccessary
- obj->setSpeciesSelector(INST_LOOKUP_CLASS(obj->getSpeciesSelector().offset));
-
- Object *baseObj = segMan->getObject(obj->getSpeciesSelector());
-
- if (baseObj) {
- obj->setVarCount(baseObj->getVarCount());
- // Copy base from species class, as we need its selector IDs
- obj->_baseObj = baseObj->_baseObj;
-
- obj->setSuperClassSelector(INST_LOOKUP_CLASS(obj->getSuperClassSelector().offset));
- } else {
- warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
-
- scr->scriptObjRemove(addr);
- }
- } // if object or class
- break;
- case SCI_OBJ_POINTERS: // A relocation table
- relocation = addr.offset;
- break;
-
- default:
- break;
- }
-
- } while (objtype != 0 && reg.offset < script->size - 2);
-
- if (relocation >= 0)
- scr->scriptRelocate(make_reg(seg_id, relocation));
-
- return reg.segment; // instantiation successful
-}
-
-int script_instantiate_sci11(ResourceManager *resMan, SegManager *segMan, int script_nr) {
- Resource *script, *heap;
- int _heapStart;
- reg_t reg;
- int was_new;
-
- const int seg_id = script_instantiate_common(resMan, segMan, script_nr, &script, &heap, &was_new);
-
- if (was_new)
- return seg_id;
-
- Script *scr = segMan->getScript(seg_id);
-
- _heapStart = script->size;
- if (script->size & 2)
- _heapStart ++;
-
- scr->mcpyInOut(0, script->data, script->size);
- scr->mcpyInOut(_heapStart, heap->data, heap->size);
-
- if (READ_LE_UINT16(script->data + 6) > 0)
- scr->setExportTableOffset(6);
-
- 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);
-
- 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 ??
-
- reg.offset += 4; // Step over header
-
- if ((objtype == SCI_OBJ_OBJECT) || (objtype == SCI_OBJ_CLASS)) { // object or class?
- int superclass;
-
- reg.offset -= SCRIPT_OBJECT_MAGIC_OFFSET;
-
- superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass...
-
- 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;
- }
-
- 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;
-}
-
static void _init_stack_base_with_selector(EngineState *s, Selector selector) {
s->stack_base[0] = make_reg(0, (uint16)selector);
s->stack_base[1] = NULL_REG;