diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 9f75b14d99e..3f4148fcc07 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -3065,13 +3065,14 @@ int Console::printObject(reg_t pos) { DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->segMan->getObjectName(pos), obj->_variables.size(), obj->methods_nr); - if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) - var_container = s->segMan->getObject(obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); + if (!(obj->getInfoSelector(version).offset & SCRIPT_INFO_CLASS)) + var_container = s->segMan->getObject(obj->getSuperClassSelector(version)); DebugPrintf(" -- member variables:\n"); for (i = 0; (uint)i < obj->_variables.size(); i++) { printf(" "); if (i < var_container->variable_names_nr) { - DebugPrintf("[%03x] %s = ", VM_OBJECT_GET_VARSELECTOR(var_container, i), selector_name(s, VM_OBJECT_GET_VARSELECTOR(var_container, i))); + uint16 varSelector = var_container->getVarSelector(i, version); + DebugPrintf("[%03x] %s = ", varSelector, selector_name(s, varSelector)); } else DebugPrintf("p#%x = ", i); @@ -3086,8 +3087,8 @@ int Console::printObject(reg_t pos) { } DebugPrintf(" -- methods:\n"); for (i = 0; i < obj->methods_nr; i++) { - reg_t fptr = VM_OBJECT_READ_FUNCTION(obj, i); - DebugPrintf(" [%03x] %s = %04x:%04x\n", VM_OBJECT_GET_FUNCSELECTOR(obj, i), selector_name(s, VM_OBJECT_GET_FUNCSELECTOR(obj, i)), PRINT_REG(fptr)); + reg_t fptr = obj->getFunction(i, version); + DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i, version), selector_name(s, obj->getFuncSelector(i, version)), PRINT_REG(fptr)); } if (s->segMan->_heap[pos.segment]->getType() == SEG_TYPE_SCRIPT) DebugPrintf("\nOwner script:\t%d\n", s->segMan->getScript(pos.segment)->_nr); diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 318d4b9c4d5..157f285541f 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -204,10 +204,10 @@ reg_t kClone(EngineState *s, int, int argc, reg_t *argv) { SciVersion version = s->resMan->sciVersion(); // for the selector defines // Mark as clone - clone_obj->_variables[SCRIPT_INFO_SELECTOR].offset = SCRIPT_INFO_CLONE; - clone_obj->_variables[SCRIPT_SPECIES_SELECTOR] = clone_obj->pos; - if (IS_CLASS(parent_obj)) - clone_obj->_variables[SCRIPT_SUPERCLASS_SELECTOR] = parent_obj->pos; + clone_obj->setInfoSelector(make_reg(0, SCRIPT_INFO_CLONE), version); + clone_obj->setSpeciesSelector(clone_obj->pos, version); + if (parent_obj->isClass(version)) + clone_obj->setSuperClassSelector(parent_obj->pos, version); s->segMan->getScript(parent_obj->pos.segment)->incrementLockers(); s->segMan->getScript(clone_obj->pos.segment)->incrementLockers(); @@ -230,7 +230,7 @@ reg_t kDisposeClone(EngineState *s, int, int argc, reg_t *argv) { SciVersion version = s->resMan->sciVersion(); // for the selector defines - if (victim_obj->_variables[SCRIPT_INFO_SELECTOR].offset != SCRIPT_INFO_CLONE) { + if (victim_obj->getInfoSelector(version).offset != SCRIPT_INFO_CLONE) { //warning("Attempt to dispose something other than a clone at %04x", offset); // SCI silently ignores this behaviour; some games actually depend on it return s->r_acc; diff --git a/engines/sci/engine/memobj.h b/engines/sci/engine/memobj.h index e792ac80ae6..38a165a33a3 100644 --- a/engines/sci/engine/memobj.h +++ b/engines/sci/engine/memobj.h @@ -198,6 +198,7 @@ public: /** Clone has been marked as 'freed' */ #define OBJECT_FLAG_FREED (0x1 << 0) +// TODO: convert to class, perhaps? struct Object { int flags; reg_t pos; /**< Object offset within its script; for clones, this is their base */ @@ -208,6 +209,67 @@ struct Object { uint16 *base_method; /**< Pointer to the method selector area for this object */ uint16 *base_vars; /**< Pointer to the varselector area for this object */ Common::Array _variables; + + uint16 getVarSelector(uint16 i, SciVersion version) { + if (version < SCI_VERSION_1_1) + return READ_LE_UINT16(base_obj + _variables.size() * 2 + i * 2); + else + return *(base_vars + i); + } + + reg_t getSpeciesSelector(SciVersion version) { + return _variables[version < SCI_VERSION_1_1 ? 0 : 5]; + } + + void setSpeciesSelector(reg_t value, SciVersion version) { + _variables[version < SCI_VERSION_1_1 ? 0 : 5] = value; + } + + reg_t getSuperClassSelector(SciVersion version) { + return _variables[version < SCI_VERSION_1_1 ? 1 : 6]; + } + + void setSuperClassSelector(reg_t value, SciVersion version) { + _variables[version < SCI_VERSION_1_1 ? 1 : 6] = value; + } + + reg_t getInfoSelector(SciVersion version) { + return _variables[version < SCI_VERSION_1_1 ? 2 : 7]; + } + + void setInfoSelector(reg_t value, SciVersion version) { + _variables[version < SCI_VERSION_1_1 ? 2 : 7] = value; + } + + reg_t getNameSelector(SciVersion version) { + return _variables[version < SCI_VERSION_1_1 ? 3 : 8]; + } + + void setNameSelector(reg_t value, SciVersion version) { + _variables[version < SCI_VERSION_1_1 ? 3 : 8] = value; + } + + reg_t getClassScriptSelector() { + return _variables[4]; + } + + void setClassScriptSelector(reg_t value) { + _variables[4] = value; + } + + uint16 getFuncSelector(uint16 i, SciVersion version) { + uint16 offset = (version < SCI_VERSION_1_1) ? i : i * 2 + 1; + return READ_LE_UINT16((byte *) (base_method + offset)); + } + + reg_t getFunction(uint16 i, SciVersion version) { + uint16 offset = (version < SCI_VERSION_1_1) ? methods_nr + 1 + i : i * 2 + 2; + return make_reg(pos.segment, READ_LE_UINT16((byte *) (base_method + offset))); + } + + bool isClass(SciVersion version) { + return (getInfoSelector(version).offset & SCRIPT_INFO_CLASS); + } }; struct CodeBlock { @@ -215,28 +277,6 @@ struct CodeBlock { int size; }; -#define VM_OBJECT_GET_VARSELECTOR(obj, i) \ - (version < SCI_VERSION_1_1 ? \ - READ_LE_UINT16(obj->base_obj + obj->_variables.size() * 2 + i*2) : \ - *(obj->base_vars + i)) -#define VM_OBJECT_READ_PROPERTY(obj, i) (obj->_variables[i]) -#define VM_OBJECT_GET_FUNCSELECTOR(obj, i) \ - (version < SCI_VERSION_1_1 ? \ - READ_LE_UINT16((byte *) (obj->base_method + i)) : \ - READ_LE_UINT16((byte *) (obj->base_method + i*2 + 1))) -#define VM_OBJECT_READ_FUNCTION(obj, i) \ - (version < SCI_VERSION_1_1 ? \ - make_reg(obj->pos.segment, \ - READ_LE_UINT16((byte *) (obj->base_method \ - + obj->methods_nr + 1 \ - + i))) : \ - make_reg(obj->pos.segment, \ - READ_LE_UINT16((byte *) (obj->base_method \ - + i * 2 + 2)))) - - - - class Script : public SegmentObj { public: int _nr; /**< Script number */ diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 11599797e2e..0782530a7c6 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -613,11 +613,11 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { int funct_area = READ_LE_UINT16( data + SCRIPT_FUNCTAREAPTR_OFFSET ); Object *base_obj; - base_obj = s->segMan->getObject(scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR]); + base_obj = s->segMan->getObject(scr->_objects[j].getSpeciesSelector(version)); if (!base_obj) { warning("Object without a base class: Script %d, index %d (reg address %04x:%04x", - scr->_nr, j, PRINT_REG(scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR])); + scr->_nr, j, PRINT_REG(scr->_objects[j].getSpeciesSelector(version))); continue; } scr->_objects[j].variable_names_nr = base_obj->_variables.size(); diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 38879a48aea..670aee3981c 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -81,8 +81,8 @@ int propertyOffsetToId(SegManager *segMan, int prop_ofs, reg_t objp) { if (segMan->sciVersion() < SCI_VERSION_1_1) selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2; else { - if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) { - obj = segMan->getObject(obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); + if (!(obj->getInfoSelector(version).offset & SCRIPT_INFO_CLASS)) { + obj = segMan->getObject(obj->getSuperClassSelector(version)); selectoroffset = (byte *)obj->base_vars; } else selectoroffset = (byte *)obj->base_vars; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index c503d7bcd00..cb178098b2f 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -266,11 +266,11 @@ const char *SegManager::getObjectName(reg_t pos) { if (!obj) return ""; - reg_t nameReg = obj->_variables[SCRIPT_NAME_SELECTOR]; + reg_t nameReg = obj->getNameSelector(version); if (nameReg.isNull()) return ""; - const char *name = derefString(obj->_variables[SCRIPT_NAME_SELECTOR]); + const char *name = derefString(nameReg); if (!name) return ""; @@ -678,8 +678,8 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { #endif // Copy base from species class, as we need its selector IDs - obj->_variables[SCRIPT_SUPERCLASS_SELECTOR] = - getClassAddress(obj->_variables[SCRIPT_SUPERCLASS_SELECTOR].offset, SCRIPT_GET_LOCK, NULL_REG); + obj->setSuperClassSelector( + getClassAddress(obj->getSuperClassSelector(version).offset, SCRIPT_GET_LOCK, NULL_REG), version); // Set the -classScript- selector to the script number. // FIXME: As this selector is filled in at run-time, it is likely @@ -687,7 +687,7 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { // uses this selector together with -propDict- to compare classes. // For the purpose of Obj::isKindOf, using the script number appears // to be sufficient. - obj->_variables[SCRIPT_CLASSSCRIPT_SELECTOR] = make_reg(0, scr->_nr); + obj->setClassScriptSelector(make_reg(0, scr->_nr)); seeker += READ_LE_UINT16(seeker + 2) * 2; } @@ -809,7 +809,7 @@ void SegManager::reconstructClones() { continue; CloneTable::Entry &seeker = ct->_table[j]; - base_obj = getObject(seeker._variables[SCRIPT_SPECIES_SELECTOR]); + base_obj = getObject(seeker.getSpeciesSelector(version)); if (!base_obj) { warning("Clone entry without a base class: %d", j); seeker.base = NULL; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 4c60b26fa43..bf385d65518 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -335,7 +335,7 @@ SciVersion EngineState::detectSetCursorType() { SciVersion EngineState::detectLofsType() { if (_lofsType == SCI_VERSION_AUTODETECT) { - SciVersion version = segMan->sciVersion(); // FIXME: for VM_OBJECT_READ_FUNCTION + SciVersion version = segMan->sciVersion(); // This detection only works (and is only needed) pre-SCI1.1 if (version >= SCI_VERSION_1_1) { @@ -355,7 +355,7 @@ SciVersion EngineState::detectLofsType() { // Check methods of the Game class for lofs operations if (obj) { for (int m = 0; m < obj->methods_nr; m++) { - reg_t fptr = VM_OBJECT_READ_FUNCTION(obj, m); + reg_t fptr = obj->getFunction(m, version); Script *script = segMan->getScript(fptr.segment); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index c0381519cc6..617016f3e66 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1406,8 +1406,8 @@ static int _obj_locate_varselector(SegManager *segMan, Object *obj, Selector slc int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET; buf = obj->base_obj + selector_name_offset; } else { - if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) - obj = segMan->getObject(obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); + if (!(obj->getInfoSelector(version).offset & SCRIPT_INFO_CLASS)) + obj = segMan->getObject(obj->getSuperClassSelector(version)); buf = (byte *)obj->base_vars; varnum = obj->_variables[1].toUint16(); @@ -1428,7 +1428,7 @@ static int _class_locate_funcselector(Object *obj, Selector slc, SciVersion vers int i; for (i = 0; i < funcnum; i++) - if (VM_OBJECT_GET_FUNCSELECTOR(obj, i) == slc) // Found it? + if (obj->getFuncSelector(i, version) == slc) // Found it? return i; // report success return -1; // Failed @@ -1445,13 +1445,13 @@ static SelectorType _lookup_selector_function(SegManager *segMan, int seg_id, Ob if (index >= 0) { if (fptr) { - *fptr = VM_OBJECT_READ_FUNCTION(obj, index); + *fptr = obj->getFunction(index, version); } return kSelectorMethod; } else { - seg_id = obj->_variables[SCRIPT_SUPERCLASS_SELECTOR].segment; - obj = segMan->getObject(obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); + seg_id = obj->getSuperClassSelector(version).segment; + obj = segMan->getObject(obj->getSuperClassSelector(version)); } } @@ -1475,15 +1475,15 @@ SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector se PRINT_REG(obj_location)); } - if (IS_CLASS(obj)) + if (obj->isClass(version)) species = obj; else - species = segMan->getObject(obj->_variables[SCRIPT_SPECIES_SELECTOR]); + species = segMan->getObject(obj->getSpeciesSelector(version)); if (!obj) { error("lookup_selector(): Error while looking up Species class.\nOriginal address was %04x:%04x. Species address was %04x:%04x", - PRINT_REG(obj_location), PRINT_REG(obj->_variables[SCRIPT_SPECIES_SELECTOR])); + PRINT_REG(obj_location), PRINT_REG(obj->getSpeciesSelector(version))); return kSelectorNone; } @@ -1694,14 +1694,14 @@ int script_instantiate_sci0(ResourceManager *resMan, SegManager *segMan, int scr Object *base_obj; // Instantiate the superclass, if neccessary - obj->_variables[SCRIPT_SPECIES_SELECTOR] = INST_LOOKUP_CLASS(obj->_variables[SCRIPT_SPECIES_SELECTOR].offset); + obj->setSpeciesSelector(INST_LOOKUP_CLASS(obj->getSpeciesSelector(version).offset), version); - base_obj = segMan->getObject(obj->_variables[SCRIPT_SPECIES_SELECTOR]); + base_obj = segMan->getObject(obj->getSpeciesSelector(version)); obj->variable_names_nr = base_obj->_variables.size(); obj->base_obj = base_obj->base_obj; // Copy base from species class, as we need its selector IDs - obj->_variables[SCRIPT_SUPERCLASS_SELECTOR] = INST_LOOKUP_CLASS(obj->_variables[SCRIPT_SUPERCLASS_SELECTOR].offset); + obj->setSuperClassSelector(INST_LOOKUP_CLASS(obj->getSuperClassSelector(version).offset), version); } // if object or class break; case SCI_OBJ_POINTERS: // A relocation table diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 57fad31c8fb..f2d51fafb14 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -68,11 +68,9 @@ class ResourceManager; /** Offset of the name pointer */ #define SCRIPT_NAME_OFFSET (version < SCI_VERSION_1_1 ? 14 -8 : 16) -#define SCRIPT_NAME_SELECTOR (version < SCI_VERSION_1_1 ? 3 : 8) /** Object-relative offset of the -info- selector */ #define SCRIPT_INFO_OFFSET (version < SCI_VERSION_1_1 ? 12 -8 : 14) -#define SCRIPT_INFO_SELECTOR (version < SCI_VERSION_1_1 ? 2 : 7) /** Flag fo the -info- selector */ #define SCRIPT_INFO_CLONE 0x0001 @@ -91,17 +89,9 @@ class ResourceManager; #define SCRIPT_SUPERCLASS_OFFSET (version < SCI_VERSION_1_1 ? 10 -8 : 12) -/*---------------------------------*/ -/* Script selector index variables */ -/*---------------------------------*/ -#define SCRIPT_SPECIES_SELECTOR (version < SCI_VERSION_1_1 ? 0 : 5) -#define SCRIPT_SUPERCLASS_SELECTOR (version < SCI_VERSION_1_1 ? 1 : 6) -#define SCRIPT_CLASSSCRIPT_SELECTOR 4 - /** Magic adjustment value for lofsa and lofss */ #define SCRIPT_LOFS_MAGIC 3 - /** Stack pointer value: Use predecessor's value */ #define CALL_SP_CARRY NULL @@ -119,9 +109,6 @@ struct Class { #define RAW_IS_OBJECT(datablock) (READ_LE_UINT16(((byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) -#define IS_CLASS(obj) (obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS) - - /** Contains selector IDs for a few selected selectors */ struct selector_map_t { Selector init; /**< Init function */