Changed the way object selectors are accessed, by removing the relevant defines and adding appropriate methods to the Object structure

svn-id: r44138
This commit is contained in:
Filippos Karapetis 2009-09-17 08:51:38 +00:00
parent 0a037ccc45
commit f890a69428
9 changed files with 97 additions and 69 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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<reg_t> _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 */

View File

@ -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();

View File

@ -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;

View File

@ -266,11 +266,11 @@ const char *SegManager::getObjectName(reg_t pos) {
if (!obj)
return "<no such object>";
reg_t nameReg = obj->_variables[SCRIPT_NAME_SELECTOR];
reg_t nameReg = obj->getNameSelector(version);
if (nameReg.isNull())
return "<no name>";
const char *name = derefString(obj->_variables[SCRIPT_NAME_SELECTOR]);
const char *name = derefString(nameReg);
if (!name)
return "<invalid name>";
@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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 */