diff options
Diffstat (limited to 'engines/sci/engine/vm.cpp')
-rw-r--r-- | engines/sci/engine/vm.cpp | 349 |
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; |