Started rewriting the Object struct into a class

svn-id: r44878
This commit is contained in:
Filippos Karapetis 2009-10-10 15:58:51 +00:00
parent 8fd29ecf9f
commit d6f5d93dbf
12 changed files with 165 additions and 204 deletions

View file

@ -1353,11 +1353,11 @@ bool Console::segmentInfo(int nr) {
for (it = scr->_objects.begin(); it != end; ++it) { for (it = scr->_objects.begin(); it != end; ++it) {
DebugPrintf(" "); DebugPrintf(" ");
// Object header // Object header
Object *obj = _vm->_gamestate->_segMan->getObject(it->_value._pos); Object *obj = _vm->_gamestate->_segMan->getObject(it->_value.getPos());
if (obj) if (obj)
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(it->_value._pos), DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(it->_value.getPos()),
_vm->_gamestate->_segMan->getObjectName(it->_value._pos), _vm->_gamestate->_segMan->getObjectName(it->_value.getPos()),
obj->_variables.size(), obj->methods_nr); obj->getVarCount(), obj->getMethodCount());
} }
} }
break; break;
@ -1400,11 +1400,11 @@ bool Console::segmentInfo(int nr) {
objpos.segment = nr; objpos.segment = nr;
DebugPrintf(" [%04x] %s; copy of ", i, _vm->_gamestate->_segMan->getObjectName(objpos)); DebugPrintf(" [%04x] %s; copy of ", i, _vm->_gamestate->_segMan->getObjectName(objpos));
// Object header // Object header
Object *obj = _vm->_gamestate->_segMan->getObject(ct->_table[i]._pos); Object *obj = _vm->_gamestate->_segMan->getObject(ct->_table[i].getPos());
if (obj) if (obj)
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i]._pos), DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].getPos()),
_vm->_gamestate->_segMan->getObjectName(ct->_table[i]._pos), _vm->_gamestate->_segMan->getObjectName(ct->_table[i].getPos()),
obj->_variables.size(), obj->methods_nr); obj->getVarCount(), obj->getMethodCount());
} }
} }
break; break;
@ -2935,7 +2935,7 @@ int Console::printObject(reg_t pos) {
EngineState *s = _vm->_gamestate; // for the several defines in this function EngineState *s = _vm->_gamestate; // for the several defines in this function
Object *obj = s->_segMan->getObject(pos); Object *obj = s->_segMan->getObject(pos);
Object *var_container = obj; Object *var_container = obj;
int i; uint i;
if (!obj) { if (!obj) {
DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos)); DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos));
@ -2944,20 +2944,20 @@ int Console::printObject(reg_t pos) {
// Object header // Object header
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->_segMan->getObjectName(pos), DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->_segMan->getObjectName(pos),
obj->_variables.size(), obj->methods_nr); obj->getVarCount(), obj->getMethodCount());
if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS)) if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS))
var_container = s->_segMan->getObject(obj->getSuperClassSelector()); var_container = s->_segMan->getObject(obj->getSuperClassSelector());
DebugPrintf(" -- member variables:\n"); DebugPrintf(" -- member variables:\n");
for (i = 0; (uint)i < obj->_variables.size(); i++) { for (i = 0; (uint)i < obj->getVarCount(); i++) {
printf(" "); printf(" ");
if (i < var_container->variable_names_nr) { if (i < var_container->getVarCount()) {
uint16 varSelector = var_container->getVarSelector(i); uint16 varSelector = var_container->getVarSelector(i);
DebugPrintf("[%03x] %s = ", varSelector, selector_name(s, varSelector)); DebugPrintf("[%03x] %s = ", varSelector, selector_name(s, varSelector));
} else } else
DebugPrintf("p#%x = ", i); DebugPrintf("p#%x = ", i);
reg_t val = obj->_variables[i]; reg_t val = obj->getVariable(i);
DebugPrintf("%04x:%04x", PRINT_REG(val)); DebugPrintf("%04x:%04x", PRINT_REG(val));
Object *ref = s->_segMan->getObject(val); Object *ref = s->_segMan->getObject(val);
@ -2967,7 +2967,7 @@ int Console::printObject(reg_t pos) {
DebugPrintf("\n"); DebugPrintf("\n");
} }
DebugPrintf(" -- methods:\n"); DebugPrintf(" -- methods:\n");
for (i = 0; i < obj->methods_nr; i++) { for (i = 0; i < obj->getMethodCount(); i++) {
reg_t fptr = obj->getFunction(i); reg_t fptr = obj->getFunction(i);
DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), selector_name(s, obj->getFuncSelector(i)), PRINT_REG(fptr)); DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), selector_name(s, obj->getFuncSelector(i)), PRINT_REG(fptr));
} }

View file

@ -122,7 +122,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
ObjMap::iterator it; ObjMap::iterator it;
const ObjMap::iterator end = script->_objects.end(); const ObjMap::iterator end = script->_objects.end();
for (it = script->_objects.begin(); it != end; ++it) { for (it = script->_objects.begin(); it != end; ++it) {
wm.push(it->_value._pos); wm.push(it->_value.getPos());
} }
} }
} }

View file

@ -123,15 +123,14 @@ reg_t kClone(EngineState *s, int argc, reg_t *argv) {
} }
*clone_obj = *parent_obj; *clone_obj = *parent_obj;
clone_obj->_flags = 0;
// Mark as clone // Mark as clone
clone_obj->setInfoSelector(make_reg(0, SCRIPT_INFO_CLONE)); clone_obj->setInfoSelector(make_reg(0, SCRIPT_INFO_CLONE));
clone_obj->setSpeciesSelector(clone_obj->_pos); clone_obj->setSpeciesSelector(clone_obj->getPos());
if (parent_obj->isClass()) if (parent_obj->isClass())
clone_obj->setSuperClassSelector(parent_obj->_pos); clone_obj->setSuperClassSelector(parent_obj->getPos());
s->_segMan->getScript(parent_obj->_pos.segment)->incrementLockers(); s->_segMan->getScript(parent_obj->getPos().segment)->incrementLockers();
s->_segMan->getScript(clone_obj->_pos.segment)->incrementLockers(); s->_segMan->getScript(clone_obj->getPos().segment)->incrementLockers();
return clone_addr; return clone_addr;
} }
@ -167,8 +166,8 @@ reg_t kDisposeClone(EngineState *s, int argc, reg_t *argv) {
} }
#endif #endif
victim_obj->_flags |= OBJECT_FLAG_FREED; victim_obj->markAsFreed();
_k_view_list_mark_free(s, victim_addr); // Free on view list, if neccessary _k_view_list_mark_free(s, victim_addr); // Free on view list, if neccessary
return s->r_acc; return s->r_acc;

View file

@ -312,14 +312,21 @@ void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) {
syncArray<reg_t>(s, _locals); syncArray<reg_t>(s, _locals);
} }
template <>
void syncWithSerializer(Common::Serializer &s, Object &obj) {
s.syncAsSint32LE(obj._flags);
sync_reg_t(s, obj._pos);
s.syncAsSint32LE(obj.variable_names_nr);
s.syncAsSint32LE(obj.methods_nr);
syncArray<reg_t>(s, obj._variables); void Object::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(_flags);
sync_reg_t(s, _pos);
int varCount;
if (s.isLoading()) {
s.syncAsSint32LE(varCount);
_variables.resize(varCount);
} else {
varCount = _variables.size();
s.syncAsSint32LE(varCount);
}
s.syncAsSint32LE(_methodCount); // that's actually a uint16
syncArray<reg_t>(s, _variables);
} }
template <> template <>
@ -411,7 +418,7 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) {
Object tmp; Object tmp;
for (uint i = 0; i < numObjs; ++i) { for (uint i = 0; i < numObjs; ++i) {
syncWithSerializer<Object>(s, tmp); syncWithSerializer<Object>(s, tmp);
_objects[tmp._pos.offset] = tmp; _objects[tmp.getPos().offset] = tmp;
} }
} else { } else {
ObjMap::iterator it; ObjMap::iterator it;
@ -605,8 +612,7 @@ void SegManager::reconstructScripts(EngineState *s) {
ObjMap::iterator it; ObjMap::iterator it;
const ObjMap::iterator end = scr->_objects.end(); const ObjMap::iterator end = scr->_objects.end();
for (it = scr->_objects.begin(); it != end; ++it) { for (it = scr->_objects.begin(); it != end; ++it) {
byte *data = scr->_buf + it->_value._pos.offset; byte *data = scr->_buf + it->_value.getPos().offset;
it->_value.base = scr->_buf;
it->_value.base_obj = data; it->_value.base_obj = data;
} }
} }
@ -622,7 +628,7 @@ void SegManager::reconstructScripts(EngineState *s) {
ObjMap::iterator it; ObjMap::iterator it;
const ObjMap::iterator end = scr->_objects.end(); const ObjMap::iterator end = scr->_objects.end();
for (it = scr->_objects.begin(); it != end; ++it) { for (it = scr->_objects.begin(); it != end; ++it) {
byte *data = scr->_buf + it->_value._pos.offset; byte *data = scr->_buf + it->_value.getPos().offset;
if (getSciVersion() >= SCI_VERSION_1_1) { if (getSciVersion() >= SCI_VERSION_1_1) {
uint16 *funct_area = (uint16 *)(scr->_buf + READ_LE_UINT16( data + 6 )); uint16 *funct_area = (uint16 *)(scr->_buf + READ_LE_UINT16( data + 6 ));
@ -641,11 +647,11 @@ void SegManager::reconstructScripts(EngineState *s) {
scr->_nr, i, PRINT_REG(it->_value.getSpeciesSelector())); scr->_nr, i, PRINT_REG(it->_value.getSpeciesSelector()));
continue; continue;
} }
it->_value.variable_names_nr = base_obj->_variables.size(); it->_value.setVarCount(base_obj->getVarCount());
it->_value.base_obj = base_obj->base_obj; it->_value.base_obj = base_obj->base_obj;
it->_value.base_method = (uint16 *)(data + funct_area); it->_value.base_method = (uint16 *)(data + funct_area);
it->_value.base_vars = (uint16 *)(data + it->_value.variable_names_nr * 2 + SCRIPT_SELECTOR_OFFSET); it->_value.base_vars = (uint16 *)(data + it->_value.getVarCount() * 2 + SCRIPT_SELECTOR_OFFSET);
} }
} }
} }

View file

@ -75,7 +75,7 @@ int propertyOffsetToId(SegManager *segMan, int prop_ofs, reg_t objp) {
return -1; return -1;
} }
selectors = obj->_variables.size(); selectors = obj->getVarCount();
if (getSciVersion() < SCI_VERSION_1_1) if (getSciVersion() < SCI_VERSION_1_1)
selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2; selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2;

View file

@ -184,9 +184,7 @@ int SegManager::deallocate(SegmentId seg, bool recursive) {
bool SegManager::isHeapObject(reg_t pos) { bool SegManager::isHeapObject(reg_t pos) {
Object *obj = getObject(pos); Object *obj = getObject(pos);
if (obj == NULL) if (obj == NULL || (obj && obj->isFreed()))
return false;
if (obj->_flags & OBJECT_FLAG_FREED)
return false; return false;
Script *scr = getScriptIfLoaded(pos.segment); Script *scr = getScriptIfLoaded(pos.segment);
return !(scr && scr->_markedAsDeleted); return !(scr && scr->_markedAsDeleted);
@ -305,7 +303,7 @@ reg_t SegManager::findObjectByName(const Common::String &name, int index) {
if (mobj->getType() == SEG_TYPE_SCRIPT) { if (mobj->getType() == SEG_TYPE_SCRIPT) {
obj = &(it->_value); obj = &(it->_value);
objpos.offset = obj->_pos.offset; objpos.offset = obj->getPos().offset;
++it; ++it;
} else if (mobj->getType() == SEG_TYPE_CLONES) { } else if (mobj->getType() == SEG_TYPE_CLONES) {
if (!ct->isValidEntry(idx)) if (!ct->isValidEntry(idx))
@ -396,7 +394,7 @@ int Script::relocateLocal(SegmentId segment, int location) {
} }
int Script::relocateObject(Object &obj, SegmentId segment, int location) { int Script::relocateObject(Object &obj, SegmentId segment, int location) {
return relocateBlock(obj._variables, obj._pos.offset, segment, location); return relocateBlock(obj._variables, obj.getPos().offset, segment, location);
} }
void Script::scriptAddCodeBlock(reg_t location) { void Script::scriptAddCodeBlock(reg_t location) {
@ -442,7 +440,7 @@ void Script::scriptRelocate(reg_t block) {
else else
printf("- No locals\n"); printf("- No locals\n");
for (it = _objects.begin(), k = 0; it != end; ++it, ++k) for (it = _objects.begin(), k = 0; it != end; ++it, ++k)
printf("- obj#%d at %04x w/ %d vars\n", k, it->_value._pos.offset, it->_value._variables.size()); printf("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount());
// SQ3 script 71 has broken relocation entries. // SQ3 script 71 has broken relocation entries.
printf("Trying to continue anyway...\n"); printf("Trying to continue anyway...\n");
} }
@ -481,7 +479,7 @@ void Script::heapRelocate(reg_t block) {
else else
printf("- No locals\n"); printf("- No locals\n");
for (it = _objects.begin(), k = 0; it != end; ++it, ++k) for (it = _objects.begin(), k = 0; it != end; ++it, ++k)
printf("- obj#%d at %04x w/ %d vars\n", k, it->_value._pos.offset, it->_value._variables.size()); printf("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount());
error("Breakpoint in %s, line %d", __FILE__, __LINE__); error("Breakpoint in %s, line %d", __FILE__, __LINE__);
} }
} }
@ -545,45 +543,7 @@ Object *Script::scriptObjInit(reg_t obj_pos) {
VERIFY(obj_pos.offset + SCRIPT_FUNCTAREAPTR_OFFSET < (int)_bufSize, "Function area pointer stored beyond end of script\n"); VERIFY(obj_pos.offset + SCRIPT_FUNCTAREAPTR_OFFSET < (int)_bufSize, "Function area pointer stored beyond end of script\n");
byte *data = (byte *)(_buf + obj_pos.offset); obj->init(_buf, obj_pos);
uint16 *funct_area = 0;
bool isClass;
if (getSciVersion() < SCI_VERSION_1_1) {
obj->variable_names_nr = READ_LE_UINT16(data + SCRIPT_SELECTORCTR_OFFSET);
obj->base_vars = 0;
funct_area = (uint16 *)(data + READ_LE_UINT16(data + SCRIPT_FUNCTAREAPTR_OFFSET));
obj->methods_nr = READ_LE_UINT16(funct_area - 1);
isClass = READ_LE_UINT16(data + 4) & SCRIPT_INFO_CLASS; // SCRIPT_INFO_OFFSET
} else {
obj->variable_names_nr = READ_LE_UINT16(data + 2);
obj->base_vars = (uint16 *)(_buf + READ_LE_UINT16(data + 4));
funct_area = (uint16 *)(_buf + READ_LE_UINT16(data + 6));
obj->methods_nr = READ_LE_UINT16(funct_area);
isClass = READ_LE_UINT16(data + 14) & SCRIPT_INFO_CLASS;
}
obj->_flags = 0;
obj->_pos = obj_pos;
obj->base_method = funct_area;
VERIFY((byte *)funct_area < _buf + _bufSize, "Function area pointer references beyond end of script");
if (getSciVersion() < SCI_VERSION_1_1) {
VERIFY((byte *)funct_area + obj->methods_nr * 2
// add again for classes, since those also store selectors
+ (isClass ? obj->methods_nr * 2 : 0) < _buf + _bufSize, "Function area extends beyond end of script");
} else {
VERIFY(((byte *)funct_area + obj->variable_names_nr) < _buf + _bufSize, "Function area extends beyond end of script");
}
obj->_variables.resize(obj->variable_names_nr);
obj->base = _buf;
obj->base_obj = data;
for (int i = 0; i < obj->variable_names_nr; i++)
obj->_variables[i] = make_reg(0, READ_LE_UINT16(data + (i * 2)));
return obj; return obj;
} }
@ -829,12 +789,10 @@ void SegManager::reconstructClones() {
base_obj = getObject(seeker.getSpeciesSelector()); base_obj = getObject(seeker.getSpeciesSelector());
if (!base_obj) { if (!base_obj) {
warning("Clone entry without a base class: %d", j); warning("Clone entry without a base class: %d", j);
seeker.base = NULL;
seeker.base_obj = NULL; seeker.base_obj = NULL;
seeker.base_vars = NULL; seeker.base_vars = NULL;
seeker.base_method = NULL; seeker.base_method = NULL;
} else { } else {
seeker.base = base_obj->base;
seeker.base_obj = base_obj->base_obj; seeker.base_obj = base_obj->base_obj;
seeker.base_vars = base_obj->base_vars; seeker.base_vars = base_obj->base_vars;
seeker.base_method = base_obj->base_method; seeker.base_method = base_obj->base_method;

View file

@ -336,8 +336,8 @@ void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback not
if (_localsSegment) if (_localsSegment)
(*note)(param, make_reg(_localsSegment, 0)); (*note)(param, make_reg(_localsSegment, 0));
for (uint i = 0; i < obj->_variables.size(); i++) for (uint i = 0; i < obj->getVarCount(); i++)
(*note)(param, obj->_variables[i]); (*note)(param, obj->getVariable(i));
} else { } else {
warning("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr)); warning("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr));
} }
@ -362,11 +362,11 @@ void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback
clone = &(_table[addr.offset]); clone = &(_table[addr.offset]);
// Emit all member variables (including references to the 'super' delegate) // Emit all member variables (including references to the 'super' delegate)
for (uint i = 0; i < clone->_variables.size(); i++) for (uint i = 0; i < clone->getVarCount(); i++)
(*note)(param, clone->_variables[i]); (*note)(param, clone->getVariable(i));
// Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals. // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals.
(*note)(param, clone->_pos); (*note)(param, clone->getPos());
//debugC(2, kDebugLevelGC, "[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos)); //debugC(2, kDebugLevelGC, "[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos));
} }

View file

@ -191,80 +191,112 @@ public:
}; };
/** Clone has been marked as 'freed' */ /** Clone has been marked as 'freed' */
#define OBJECT_FLAG_FREED (0x1 << 0) #define OBJECT_FLAG_FREED (1 << 0)
// TODO: convert to class, perhaps? class Object {
struct Object { public:
int _flags; Object() {
reg_t _pos; /**< Object offset within its script; for clones, this is their base */ _flags = 0;
int variable_names_nr; /**< Number of variable names, may be less than variables_nr */ _offset = getSciVersion() < SCI_VERSION_1_1 ? 0 : 5;
int methods_nr; }
byte *base; /**< Points to a buffer all relative references (code, strings) point to */
byte *base_obj; /**< base + object offset within base */
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) { ~Object() { }
reg_t getSpeciesSelector() { return _variables[_offset]; }
void setSpeciesSelector(reg_t value) { _variables[_offset] = value; }
reg_t getSuperClassSelector() { return _variables[_offset + 1]; }
void setSuperClassSelector(reg_t value) { _variables[_offset + 1] = value; }
reg_t getInfoSelector() { return _variables[_offset + 2]; }
void setInfoSelector(reg_t value) { _variables[_offset + 2] = value; }
reg_t getNameSelector() { return _variables[_offset + 3]; }
void setNameSelector(reg_t value) { _variables[_offset + 3] = value; }
reg_t getClassScriptSelector() { return _variables[4]; }
void setClassScriptSelector(reg_t value) { _variables[4] = value; }
Selector getVarSelector(uint16 i) {
if (getSciVersion() < SCI_VERSION_1_1) if (getSciVersion() < SCI_VERSION_1_1)
return READ_LE_UINT16(base_obj + _variables.size() * 2 + i * 2); return READ_LE_UINT16(base_obj + _variables.size() * 2 + i * 2);
else else
return *(base_vars + i); return *(base_vars + i);
} }
reg_t getSpeciesSelector() { Selector getFuncSelector(uint16 i) {
return _variables[getSciVersion() < SCI_VERSION_1_1 ? 0 : 5];
}
void setSpeciesSelector(reg_t value) {
_variables[getSciVersion() < SCI_VERSION_1_1 ? 0 : 5] = value;
}
reg_t getSuperClassSelector() {
return _variables[getSciVersion() < SCI_VERSION_1_1 ? 1 : 6];
}
void setSuperClassSelector(reg_t value) {
_variables[getSciVersion() < SCI_VERSION_1_1 ? 1 : 6] = value;
}
reg_t getInfoSelector() {
return _variables[getSciVersion() < SCI_VERSION_1_1 ? 2 : 7];
}
void setInfoSelector(reg_t value) {
_variables[getSciVersion() < SCI_VERSION_1_1 ? 2 : 7] = value;
}
reg_t getNameSelector() {
return _variables[getSciVersion() < SCI_VERSION_1_1 ? 3 : 8];
}
void setNameSelector(reg_t value) {
_variables[getSciVersion() < 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) {
uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? i : i * 2 + 1; uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? i : i * 2 + 1;
return READ_LE_UINT16((byte *) (base_method + offset)); return READ_LE_UINT16((byte *) (base_method + offset));
} }
/**
* Determines if this object is a class and explicitly defines the
* selector as a funcselector. Does NOT say anything about the object's
* superclasses, i.e. failure may be returned even if one of the
* superclasses defines the funcselector
*/
int funcSelectorPosition(Selector sel) {
for (uint i = 0; i < _methodCount; i++)
if (getFuncSelector(i) == sel)
return i;
return -1;
}
reg_t getFunction(uint16 i) { reg_t getFunction(uint16 i) {
uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? methods_nr + 1 + i : i * 2 + 2; uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? _methodCount + 1 + i : i * 2 + 2;
return make_reg(_pos.segment, READ_LE_UINT16((byte *) (base_method + offset))); return make_reg(_pos.segment, READ_LE_UINT16((byte *) (base_method + offset)));
} }
bool isClass() { bool isClass() { return (getInfoSelector().offset & SCRIPT_INFO_CLASS); }
return (getInfoSelector().offset & SCRIPT_INFO_CLASS);
void markAsFreed() { _flags |= OBJECT_FLAG_FREED; }
bool isFreed() { return _flags & OBJECT_FLAG_FREED; }
void setVarCount(uint size) { _variables.resize(size); }
uint getVarCount() { return _variables.size(); }
void init(byte *buf, reg_t obj_pos) {
byte *data = (byte *)(buf + obj_pos.offset);
base_obj = data;
_pos = obj_pos;
if (getSciVersion() < SCI_VERSION_1_1) {
setVarCount(READ_LE_UINT16(data + SCRIPT_SELECTORCTR_OFFSET));
base_vars = 0;
base_method = (uint16 *)(data + READ_LE_UINT16(data + SCRIPT_FUNCTAREAPTR_OFFSET));
_methodCount = READ_LE_UINT16(base_method - 1);
} else {
setVarCount(READ_LE_UINT16(data + 2));
base_vars = (uint16 *)(buf + READ_LE_UINT16(data + 4));
base_method = (uint16 *)(buf + READ_LE_UINT16(data + 6));
_methodCount = READ_LE_UINT16(base_method);
}
for (uint i = 0; i < _variables.size(); i++)
_variables[i] = make_reg(0, READ_LE_UINT16(data + (i * 2)));
} }
reg_t getVariable(uint var) { return _variables[var]; }
uint16 getMethodCount() { return _methodCount; }
reg_t getPos() { return _pos; }
void saveLoadWithSerializer(Common::Serializer &ser);
// TODO: make private. Used by validate_property(), ObjVarRef::getPointer and Script::relocateObject
Common::Array<reg_t> _variables;
// TODO: make private
byte *base_obj; /**< base + object offset within base */
uint16 *base_method; /**< Pointer to the method selector area for this object */
uint16 *base_vars; /**< Pointer to the varselector area for this object */
private:
uint16 _methodCount;
int _flags;
uint16 _offset;
reg_t _pos; /**< Object offset within its script; for clones, this is their base */
}; };
struct CodeBlock { struct CodeBlock {

View file

@ -104,7 +104,7 @@ static int _obj_locate_varselector(SegManager *segMan, Object *obj, Selector slc
uint varnum; uint varnum;
if (getSciVersion() < SCI_VERSION_1_1) { if (getSciVersion() < SCI_VERSION_1_1) {
varnum = obj->variable_names_nr; varnum = obj->getVarCount();
int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET; int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET;
buf = obj->base_obj + selector_name_offset; buf = obj->base_obj + selector_name_offset;
} else { } else {
@ -112,7 +112,7 @@ static int _obj_locate_varselector(SegManager *segMan, Object *obj, Selector slc
obj = segMan->getObject(obj->getSuperClassSelector()); obj = segMan->getObject(obj->getSuperClassSelector());
buf = (byte *)obj->base_vars; buf = (byte *)obj->base_vars;
varnum = obj->_variables[1].toUint16(); varnum = obj->getVariable(1).toUint16();
} }
for (uint i = 0; i < varnum; i++) for (uint i = 0; i < varnum; i++)
@ -122,46 +122,8 @@ static int _obj_locate_varselector(SegManager *segMan, Object *obj, Selector slc
return -1; // Failed return -1; // Failed
} }
static int _class_locate_funcselector(Object *obj, Selector slc) {
// Determines if obj is a class and explicitly defines slc as a funcselector
// Does NOT say anything about obj's superclasses, i.e. failure may be
// returned even if one of the superclasses defines the funcselector.
int funcnum = obj->methods_nr;
int i;
for (i = 0; i < funcnum; i++)
if (obj->getFuncSelector(i) == slc) // Found it?
return i; // report success
return -1; // Failed
}
static SelectorType _lookup_selector_function(SegManager *segMan, int seg_id, Object *obj, Selector selector_id, reg_t *fptr) {
int index;
// "recursive" lookup
while (obj) {
index = _class_locate_funcselector(obj, selector_id);
if (index >= 0) {
if (fptr) {
*fptr = obj->getFunction(index);
}
return kSelectorMethod;
} else {
seg_id = obj->getSuperClassSelector().segment;
obj = segMan->getObject(obj->getSuperClassSelector());
}
}
return kSelectorNone;
}
SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) { SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) {
Object *obj = segMan->getObject(obj_location); Object *obj = segMan->getObject(obj_location);
Object *species;
int index; int index;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
@ -175,18 +137,6 @@ SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector se
PRINT_REG(obj_location)); PRINT_REG(obj_location));
} }
if (obj->isClass())
species = obj;
else
species = segMan->getObject(obj->getSpeciesSelector());
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->getSpeciesSelector()));
return kSelectorNone;
}
index = _obj_locate_varselector(segMan, obj, selector_id); index = _obj_locate_varselector(segMan, obj, selector_id);
if (index >= 0) { if (index >= 0) {
@ -196,9 +146,25 @@ SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector se
varp->varindex = index; varp->varindex = index;
} }
return kSelectorVariable; return kSelectorVariable;
} else {
// Check if it's a method, with recursive lookup in superclasses
while (obj) {
index = obj->funcSelectorPosition(selector_id);
if (index >= 0) {
if (fptr)
*fptr = obj->getFunction(index);
return kSelectorMethod;
} else {
obj = segMan->getObject(obj->getSuperClassSelector());
}
}
return kSelectorNone;
} }
return _lookup_selector_function(segMan, obj_location.segment, obj, selector_id, fptr);
// return _lookup_selector_function(segMan, obj, selector_id, fptr);
} }
} // End of namespace Sci } // End of namespace Sci

View file

@ -403,7 +403,7 @@ SciVersion EngineState::detectLofsType() {
// Check methods of the Game class for lofs operations // Check methods of the Game class for lofs operations
if (obj) { if (obj) {
for (int m = 0; m < obj->methods_nr; m++) { for (uint m = 0; m < obj->getMethodCount(); m++) {
reg_t fptr = obj->getFunction(m); reg_t fptr = obj->getFunction(m);
Script *script = _segMan->getScript(fptr.segment); Script *script = _segMan->getScript(fptr.segment);

View file

@ -67,9 +67,9 @@ static reg_t &validate_property(Object *obj, int index) {
return dummyReg; return dummyReg;
} }
if (index < 0 || (uint)index >= obj->_variables.size()) { if (index < 0 || (uint)index >= obj->getVarCount()) {
debugC(2, kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested!\n", debugC(2, kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested!\n",
index, obj->_variables.size()); index, obj->getVarCount());
return dummyReg; return dummyReg;
} }
@ -1598,7 +1598,7 @@ int script_instantiate_sci0(ResourceManager *resMan, SegManager *segMan, int scr
obj->setSpeciesSelector(INST_LOOKUP_CLASS(obj->getSpeciesSelector().offset)); obj->setSpeciesSelector(INST_LOOKUP_CLASS(obj->getSpeciesSelector().offset));
base_obj = segMan->getObject(obj->getSpeciesSelector()); base_obj = segMan->getObject(obj->getSpeciesSelector());
obj->variable_names_nr = base_obj->_variables.size(); obj->setVarCount(base_obj->getVarCount());
obj->base_obj = base_obj->base_obj; obj->base_obj = base_obj->base_obj;
// Copy base from species class, as we need its selector IDs // Copy base from species class, as we need its selector IDs

View file

@ -37,7 +37,7 @@ namespace Sci {
class SegManager; class SegManager;
struct EngineState; struct EngineState;
struct Object; class Object;
class ResourceManager; class ResourceManager;
/** Number of bytes to be allocated for the stack */ /** Number of bytes to be allocated for the stack */