SCI: Changed object / script local vars storage to use a Common::Array

svn-id: r40515
This commit is contained in:
Max Horn 2009-05-12 23:30:42 +00:00
parent 0255cd0213
commit 7f29670843
11 changed files with 99 additions and 129 deletions

View file

@ -686,7 +686,7 @@ int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) {
return KSIG_OBJECT | KSIG_INVALID; return KSIG_OBJECT | KSIG_INVALID;
case MEM_OBJ_LOCALS: case MEM_OBJ_LOCALS:
if (allow_invalid || reg.offset < (*(LocalVariables *)mobj).nr * sizeof(reg_t)) if (allow_invalid || reg.offset < (*(LocalVariables *)mobj)._locals.size() * sizeof(reg_t))
return KSIG_REF; return KSIG_REF;
else else
return KSIG_REF | KSIG_INVALID; return KSIG_REF | KSIG_INVALID;

View file

@ -44,7 +44,7 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) {
if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) { if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) {
// Penalty time- too many requests to this function without // Penalty time- too many requests to this function without
// waiting! // waiting!
int delay = s->script_000->locals_block->locals[SCI_VARIABLE_GAME_SPEED].offset; int delay = s->script_000->locals_block->_locals[SCI_VARIABLE_GAME_SPEED].offset;
gfxop_sleep(s->gfx_state, delay * 1000 / 60); gfxop_sleep(s->gfx_state, delay * 1000 / 60);
} }

View file

@ -160,7 +160,6 @@ reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) {
Object *parent_obj = obj_get(s, parent_addr); Object *parent_obj = obj_get(s, parent_addr);
reg_t clone_addr; reg_t clone_addr;
Clone *clone_obj; // same as Object* Clone *clone_obj; // same as Object*
int varblock_size;
if (!parent_obj) { if (!parent_obj) {
SCIkwarn(SCIkERROR, "Attempt to clone non-object/class at "PREG" failed", PRINT_REG(parent_addr)); SCIkwarn(SCIkERROR, "Attempt to clone non-object/class at "PREG" failed", PRINT_REG(parent_addr));
@ -176,17 +175,14 @@ reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return NULL_REG; return NULL_REG;
} }
memcpy(clone_obj, parent_obj, sizeof(Clone)); *clone_obj = *parent_obj;
clone_obj->flags = 0; clone_obj->flags = 0;
varblock_size = parent_obj->variables_nr * sizeof(reg_t);
clone_obj->variables = (reg_t*)malloc(varblock_size);
memcpy(clone_obj->variables, parent_obj->variables, varblock_size);
// Mark as clone // Mark as clone
clone_obj->variables[SCRIPT_INFO_SELECTOR].offset = SCRIPT_INFO_CLONE; clone_obj->_variables[SCRIPT_INFO_SELECTOR].offset = SCRIPT_INFO_CLONE;
clone_obj->variables[SCRIPT_SPECIES_SELECTOR] = clone_obj->pos; clone_obj->_variables[SCRIPT_SPECIES_SELECTOR] = clone_obj->pos;
if (IS_CLASS(parent_obj)) if (IS_CLASS(parent_obj))
clone_obj->variables[SCRIPT_SUPERCLASS_SELECTOR] = parent_obj->pos; clone_obj->_variables[SCRIPT_SUPERCLASS_SELECTOR] = parent_obj->pos;
s->seg_manager->incrementLockers(parent_obj->pos.segment, SEG_ID); s->seg_manager->incrementLockers(parent_obj->pos.segment, SEG_ID);
s->seg_manager->incrementLockers(clone_obj->pos.segment, SEG_ID); s->seg_manager->incrementLockers(clone_obj->pos.segment, SEG_ID);
@ -206,7 +202,7 @@ reg_t kDisposeClone(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return s->r_acc; return s->r_acc;
} }
if (victim_obj->variables[SCRIPT_INFO_SELECTOR].offset != SCRIPT_INFO_CLONE) { if (victim_obj->_variables[SCRIPT_INFO_SELECTOR].offset != SCRIPT_INFO_CLONE) {
//SCIkwarn("Attempt to dispose something other than a clone at %04x\n", offset); //SCIkwarn("Attempt to dispose something other than a clone at %04x\n", offset);
// SCI silently ignores this behaviour; some games actually depend on it // SCI silently ignores this behaviour; some games actually depend on it
return s->r_acc; return s->r_acc;

View file

@ -149,6 +149,12 @@ void syncArray(Common::Serializer &s, Common::Array<T> &arr) {
} }
template <>
void syncWithSerializer(Common::Serializer &s, reg_t &obj) {
sync_reg_t(s, obj);
}
void MenuItem::saveLoadWithSerializer(Common::Serializer &s) { void MenuItem::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(_type); s.syncAsSint32LE(_type);
@ -259,7 +265,6 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
sync_SegManagerPtr(s, seg_manager); sync_SegManagerPtr(s, seg_manager);
syncArray<Class>(s, _classtable); syncArray<Class>(s, _classtable);
sync_sfx_state_t(s, sound); sync_sfx_state_t(s, sound);
@ -267,12 +272,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
static void sync_LocalVariables(Common::Serializer &s, LocalVariables &obj) { static void sync_LocalVariables(Common::Serializer &s, LocalVariables &obj) {
s.syncAsSint32LE(obj.script_id); s.syncAsSint32LE(obj.script_id);
syncArray<reg_t>(s, obj._locals);
s.syncAsSint32LE(obj.nr);
if (!obj.locals && obj.nr)
obj.locals = (reg_t *)calloc(obj.nr, sizeof(reg_t));
for (int i = 0; i < obj.nr; ++i)
sync_reg_t(s, obj.locals[i]);
} }
template <> template <>
@ -282,11 +282,7 @@ void syncWithSerializer(Common::Serializer &s, Object &obj) {
s.syncAsSint32LE(obj.variable_names_nr); s.syncAsSint32LE(obj.variable_names_nr);
s.syncAsSint32LE(obj.methods_nr); s.syncAsSint32LE(obj.methods_nr);
s.syncAsSint32LE(obj.variables_nr); syncArray<reg_t>(s, obj._variables);
if (!obj.variables && obj.variables_nr)
obj.variables = (reg_t *)calloc(obj.variables_nr, sizeof(reg_t));
for (int i = 0; i < obj.variables_nr; ++i)
sync_reg_t(s, obj.variables[i]);
} }
template <> template <>
@ -629,14 +625,14 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) {
int funct_area = READ_LE_UINT16( data + SCRIPT_FUNCTAREAPTR_OFFSET ); int funct_area = READ_LE_UINT16( data + SCRIPT_FUNCTAREAPTR_OFFSET );
Object *base_obj; Object *base_obj;
base_obj = obj_get(s, scr->_objects[j].variables[SCRIPT_SPECIES_SELECTOR]); base_obj = obj_get(s, scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR]);
if (!base_obj) { if (!base_obj) {
sciprintf("Object without a base class: Script %d, index %d (reg address "PREG"\n", sciprintf("Object without a base class: Script %d, index %d (reg address "PREG"\n",
scr->nr, j, PRINT_REG(scr->_objects[j].variables[SCRIPT_SPECIES_SELECTOR])); scr->nr, j, PRINT_REG(scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR]));
continue; continue;
} }
scr->_objects[j].variable_names_nr = base_obj->variables_nr; scr->_objects[j].variable_names_nr = base_obj->_variables.size();
scr->_objects[j].base_obj = base_obj->base_obj; scr->_objects[j].base_obj = base_obj->base_obj;
scr->_objects[j].base_method = (uint16 *)(data + funct_area); scr->_objects[j].base_method = (uint16 *)(data + funct_area);
@ -683,7 +679,7 @@ static void reconstruct_clones(EngineState *s, SegManager *self) {
continue; continue;
} }
CloneTable::Entry &seeker = ct->_table[j]; CloneTable::Entry &seeker = ct->_table[j];
base_obj = obj_get(s, seeker.variables[SCRIPT_SPECIES_SELECTOR]); base_obj = obj_get(s, seeker._variables[SCRIPT_SPECIES_SELECTOR]);
if (!base_obj) { if (!base_obj) {
sciprintf("Clone entry without a base class: %d\n", j); sciprintf("Clone entry without a base class: %d\n", j);
seeker.base = seeker.base_obj = NULL; seeker.base = seeker.base_obj = NULL;

View file

@ -328,8 +328,8 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on
} }
if (valid) { if (valid) {
char *objname = (char *) obj->base char *objname = (char *)obj->base
+ obj->variables[SCRIPT_NAME_SELECTOR].offset; + obj->_variables[SCRIPT_NAME_SELECTOR].offset;
if (!strcmp(objname, str_objname)) { if (!strcmp(objname, str_objname)) {
// Found a match! // Found a match!
if (index < 0 || if (index < 0 ||

View file

@ -340,7 +340,7 @@ int c_segtable(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
static void print_obj_head(EngineState *s, Object *obj) { static void print_obj_head(EngineState *s, Object *obj) {
sciprintf(PREG" %s : %3d vars, %3d methods\n", PRINT_REG(obj->pos), obj_get_name(s, obj->pos), sciprintf(PREG" %s : %3d vars, %3d methods\n", PRINT_REG(obj->pos), obj_get_name(s, obj->pos),
obj->variables_nr, obj->methods_nr); obj->_variables.size(), obj->methods_nr);
} }
static void print_list(EngineState *s, List *l) { static void print_list(EngineState *s, List *l) {
@ -391,7 +391,7 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) {
sciprintf(" Synynms: %4d\n", scr->synonyms_nr); sciprintf(" Synynms: %4d\n", scr->synonyms_nr);
if (scr->locals_block) if (scr->locals_block)
sciprintf(" Locals : %4d in segment 0x%x\n", scr->locals_block->nr, scr->locals_segment); sciprintf(" Locals : %4d in segment 0x%x\n", scr->locals_block->_locals.size(), scr->locals_segment);
else else
sciprintf(" Locals : none\n"); sciprintf(" Locals : none\n");
@ -406,7 +406,7 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) {
case MEM_OBJ_LOCALS: { case MEM_OBJ_LOCALS: {
LocalVariables *locals = (LocalVariables *)mobj; LocalVariables *locals = (LocalVariables *)mobj;
sciprintf("locals for script.%03d\n", locals->script_id); sciprintf("locals for script.%03d\n", locals->script_id);
sciprintf(" %d (0x%x) locals\n", locals->nr, locals->nr); sciprintf(" %d (0x%x) locals\n", locals->_locals.size(), locals->_locals.size());
} }
break; break;
@ -1182,13 +1182,13 @@ int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) {
return -1; return -1;
} }
selectors = obj->variables_nr; selectors = obj->_variables.size();
if (s->version < SCI_VERSION(1, 001, 000)) if (s->version < SCI_VERSION(1, 001, 000))
selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2; selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2;
else { else {
if (!(obj->variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) { if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) {
obj = obj_get(s, obj->variables[SCRIPT_SUPERCLASS_SELECTOR]); obj = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
selectoroffset = (byte *)obj->base_vars; selectoroffset = (byte *)obj->base_vars;
} else } else
selectoroffset = (byte *)obj->base_vars; selectoroffset = (byte *)obj->base_vars;
@ -2533,17 +2533,17 @@ int objinfo(EngineState *s, reg_t pos) {
print_obj_head(s, obj); print_obj_head(s, obj);
if (!(obj->variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS))
var_container = obj_get(s, obj->variables[SCRIPT_SUPERCLASS_SELECTOR]); var_container = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
sciprintf(" -- member variables:\n"); sciprintf(" -- member variables:\n");
for (i = 0; i < obj->variables_nr; i++) { for (i = 0; (uint)i < obj->_variables.size(); i++) {
sciprintf(" "); sciprintf(" ");
if (i < var_container->variable_names_nr) if (i < var_container->variable_names_nr)
sciprintf("[%03x] %s = ", VM_OBJECT_GET_VARSELECTOR(var_container, i), selector_name(s, VM_OBJECT_GET_VARSELECTOR(var_container, i))); sciprintf("[%03x] %s = ", VM_OBJECT_GET_VARSELECTOR(var_container, i), selector_name(s, VM_OBJECT_GET_VARSELECTOR(var_container, i)));
else else
sciprintf("p#%x = ", i); sciprintf("p#%x = ", i);
sciprintf(PREG"\n", PRINT_REG(obj->variables[i])); sciprintf(PREG"\n", PRINT_REG(obj->_variables[i]));
} }
sciprintf(" -- methods:\n"); sciprintf(" -- methods:\n");
for (i = 0; i < obj->methods_nr; i++) { for (i = 0; i < obj->methods_nr; i++) {
@ -2870,7 +2870,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
disassemble(s, *pc, 0, 1); disassemble(s, *pc, 0, 1);
if (_debug_seeking == _DEBUG_SEEK_GLOBAL) if (_debug_seeking == _DEBUG_SEEK_GLOBAL)
sciprintf("Global %d (0x%x) = "PREG"\n", _debug_seek_special, sciprintf("Global %d (0x%x) = "PREG"\n", _debug_seek_special,
_debug_seek_special, PRINT_REG(s->script_000->locals_block->locals[_debug_seek_special])); _debug_seek_special, PRINT_REG(s->script_000->locals_block->_locals[_debug_seek_special]));
_debugstate_valid = old_debugstate; _debugstate_valid = old_debugstate;

View file

@ -361,9 +361,6 @@ void Script::freeScript() {
buf = NULL; buf = NULL;
buf_size = 0; buf_size = 0;
for (uint i = 0; i < _objects.size(); i++) {
free(_objects[i].variables);
}
_objects.clear(); _objects.clear();
delete obj_indices; delete obj_indices;
@ -498,38 +495,37 @@ int SegManager::getSynonymsNr(int id, idFlag flag) {
return scr->synonyms_nr; return scr->synonyms_nr;
} }
int SegManager::relocateBlock(reg_t *block, int block_location, int block_items, SegmentId segment, int location) { int SegManager::relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location) {
int rel = location - block_location; int rel = location - block_location;
int index;
if (rel < 0) if (rel < 0)
return 0; return 0;
index = rel >> 1; uint idx = rel >> 1;
if (index >= block_items) if (idx >= block.size())
return 0; return 0;
if (rel & 1) { if (rel & 1) {
sciprintf("Error: Attempt to relocate odd variable #%d.5e (relative to %04x)\n", index, block_location); sciprintf("Error: Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location);
return 0; return 0;
} }
block[index].segment = segment; // Perform relocation block[idx].segment = segment; // Perform relocation
if (isSci1_1) if (isSci1_1)
block[index].offset += getScript(segment, SEG_ID)->script_size; block[idx].offset += getScript(segment, SEG_ID)->script_size;
return 1; return 1;
} }
int SegManager::relocateLocal(Script *scr, SegmentId segment, int location) { int SegManager::relocateLocal(Script *scr, SegmentId segment, int location) {
if (scr->locals_block) if (scr->locals_block)
return relocateBlock(scr->locals_block->locals, scr->locals_offset, scr->locals_block->nr, segment, location); return relocateBlock(scr->locals_block->_locals, scr->locals_offset, segment, location);
else else
return 0; // No hands, no cookies return 0; // No hands, no cookies
} }
int SegManager::relocateObject(Object *obj, SegmentId segment, int location) { int SegManager::relocateObject(Object *obj, SegmentId segment, int location) {
return relocateBlock(obj->variables, obj->pos.offset, obj->variables_nr, segment, location); return relocateBlock(obj->_variables, obj->pos.offset, segment, location);
} }
void SegManager::scriptAddCodeBlock(reg_t location) { void SegManager::scriptAddCodeBlock(reg_t location) {
@ -573,11 +569,11 @@ void SegManager::scriptRelocate(reg_t block) {
sciprintf("While processing relocation block "PREG":\n", PRINT_REG(block)); sciprintf("While processing relocation block "PREG":\n", PRINT_REG(block));
sciprintf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count); sciprintf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count);
if (scr->locals_block) if (scr->locals_block)
sciprintf("- locals: %d at %04x\n", scr->locals_block->nr, scr->locals_offset); sciprintf("- locals: %d at %04x\n", scr->locals_block->_locals.size(), scr->locals_offset);
else else
sciprintf("- No locals\n"); sciprintf("- No locals\n");
for (k = 0; k < scr->_objects.size(); k++) for (k = 0; k < scr->_objects.size(); k++)
sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k].variables_nr); sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k]._variables.size());
// SQ3 script 71 has broken relocation entries. // SQ3 script 71 has broken relocation entries.
// Since this is mainstream, we can't break out as we used to do. // Since this is mainstream, we can't break out as we used to do.
sciprintf("Trying to continue anyway...\n"); sciprintf("Trying to continue anyway...\n");
@ -614,11 +610,11 @@ void SegManager::heapRelocate(EngineState *s, reg_t block) {
sciprintf("While processing relocation block "PREG":\n", PRINT_REG(block)); sciprintf("While processing relocation block "PREG":\n", PRINT_REG(block));
sciprintf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count); sciprintf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count);
if (scr->locals_block) if (scr->locals_block)
sciprintf("- locals: %d at %04x\n", scr->locals_block->nr, scr->locals_offset); sciprintf("- locals: %d at %04x\n", scr->locals_block->_locals.size(), scr->locals_offset);
else else
sciprintf("- No locals\n"); sciprintf("- No locals\n");
for (k = 0; k < scr->_objects.size(); k++) for (k = 0; k < scr->_objects.size(); k++)
sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k].variables_nr); sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k]._variables.size());
sciprintf("Triggering breakpoint...\n"); sciprintf("Triggering breakpoint...\n");
BREAKPOINT(); BREAKPOINT();
} }
@ -671,8 +667,7 @@ Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) {
// add again for classes, since those also store selectors // add again for classes, since those also store selectors
+ (is_class ? functions_nr * 2 : 0) < scr->buf_size, "Function area extends beyond end of script"); + (is_class ? functions_nr * 2 : 0) < scr->buf_size, "Function area extends beyond end of script");
obj->variables_nr = variables_nr; obj->_variables.resize(variables_nr);
obj->variables = (reg_t *)malloc(sizeof(reg_t) * variables_nr);
obj->methods_nr = functions_nr; obj->methods_nr = functions_nr;
obj->base = scr->buf; obj->base = scr->buf;
@ -681,7 +676,7 @@ Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) {
obj->base_vars = NULL; obj->base_vars = NULL;
for (i = 0; i < variables_nr; i++) for (i = 0; i < variables_nr; i++)
obj->variables[i] = make_reg(0, READ_LE_UINT16(data + (i * 2))); obj->_variables[i] = make_reg(0, READ_LE_UINT16(data + (i * 2)));
} }
return obj; return obj;
@ -727,16 +722,15 @@ Object *SegManager::scriptObjInit11(EngineState *s, reg_t obj_pos) {
VERIFY(((byte *) funct_area + functions_nr) < scr->buf + scr->buf_size, "Function area extends beyond end of script"); VERIFY(((byte *) funct_area + functions_nr) < scr->buf + scr->buf_size, "Function area extends beyond end of script");
obj->variables_nr = variables_nr;
obj->variable_names_nr = variables_nr; obj->variable_names_nr = variables_nr;
obj->variables = (reg_t *)malloc(sizeof(reg_t) * variables_nr); obj->_variables.resize(variables_nr);
obj->methods_nr = functions_nr; obj->methods_nr = functions_nr;
obj->base = scr->buf; obj->base = scr->buf;
obj->base_obj = data; obj->base_obj = data;
for (i = 0; i < variables_nr; i++) for (i = 0; i < variables_nr; i++)
obj->variables[i] = make_reg(0, READ_LE_UINT16(data + (i * 2))); obj->_variables[i] = make_reg(0, READ_LE_UINT16(data + (i * 2)));
} }
return obj; return obj;
@ -755,21 +749,19 @@ LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) {
scr->locals_block = NULL; scr->locals_block = NULL;
return NULL; return NULL;
} else { } else {
MemObject *mobj;
LocalVariables *locals; LocalVariables *locals;
if (scr->locals_segment) { if (scr->locals_segment) {
mobj = _heap[scr->locals_segment]; locals = (LocalVariables *)_heap[scr->locals_segment];
VERIFY(mobj != NULL, "Re-used locals segment was NULL'd out"); VERIFY(locals != NULL, "Re-used locals segment was NULL'd out");
VERIFY(mobj->getType() == MEM_OBJ_LOCALS, "Re-used locals segment did not consist of local variables"); VERIFY(locals->getType() == MEM_OBJ_LOCALS, "Re-used locals segment did not consist of local variables");
VERIFY((*(LocalVariables *)mobj).script_id == scr->nr, "Re-used locals segment belonged to other script"); VERIFY(locals->script_id == scr->nr, "Re-used locals segment belonged to other script");
} else } else
mobj = allocNonscriptSegment(MEM_OBJ_LOCALS, &scr->locals_segment); locals = (LocalVariables *)allocNonscriptSegment(MEM_OBJ_LOCALS, &scr->locals_segment);
locals = scr->locals_block = (LocalVariables *)mobj; scr->locals_block = locals;
locals->script_id = scr->nr; locals->script_id = scr->nr;
locals->locals = (reg_t *)calloc(count, sizeof(reg_t)); locals->_locals.resize(count);
locals->nr = count;
return locals; return locals;
} }
@ -808,7 +800,7 @@ void SegManager::scriptInitialiseLocals(reg_t location) {
byte *base = (byte *)(scr->buf + location.offset); byte *base = (byte *)(scr->buf + location.offset);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
locals->locals[i].offset = READ_LE_UINT16(base + i * 2); locals->_locals[i].offset = READ_LE_UINT16(base + i * 2);
} }
} }
@ -861,16 +853,16 @@ void SegManager::scriptInitialiseObjectsSci11(EngineState *s, int seg) {
obj = scriptObjInit(s, reg); obj = scriptObjInit(s, reg);
#if 0 #if 0
if (obj->variables[5].offset != 0xffff) { if (obj->_variables[5].offset != 0xffff) {
obj->variables[5] = INST_LOOKUP_CLASS(obj->variables[5].offset); obj->_variables[5] = INST_LOOKUP_CLASS(obj->_variables[5].offset);
base_obj = obj_get(s, obj->variables[5]); base_obj = obj_get(s, obj->_variables[5]);
obj->variable_names_nr = base_obj->variables_nr; obj->variable_names_nr = base_obj->variables_nr;
obj->base_obj = base_obj->base_obj; obj->base_obj = base_obj->base_obj;
} }
#endif #endif
// Copy base from species class, as we need its selector IDs // Copy base from species class, as we need its selector IDs
obj->variables[6] = INST_LOOKUP_CLASS(obj->variables[6].offset); obj->_variables[6] = INST_LOOKUP_CLASS(obj->_variables[6].offset);
seeker += READ_LE_UINT16(seeker + 2) * 2; seeker += READ_LE_UINT16(seeker + 2) * 2;
} }
@ -1032,8 +1024,11 @@ byte *Script::dereference(reg_t pointer, int *size) {
} }
byte *LocalVariables::dereference(reg_t pointer, int *size) { byte *LocalVariables::dereference(reg_t pointer, int *size) {
int count = nr * sizeof(reg_t); // FIXME: The following doesn't seem to be endian safe.
byte *base = (byte *)locals; // To fix this, we'd have to always treat the reg_t
// values stored here as in the little endian format.
int count = _locals.size() * sizeof(reg_t);
byte *base = (byte *)&_locals[0];
if (size) if (size)
*size = count; *size = count;
@ -1164,8 +1159,8 @@ void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param,
(*note)(param, make_reg(script->locals_segment, 0)); (*note)(param, make_reg(script->locals_segment, 0));
Object &obj = script->_objects[idx]; Object &obj = script->_objects[idx];
for (int i = 0; i < obj.variables_nr; i++) for (uint i = 0; i < obj._variables.size(); i++)
(*note)(param, obj.variables[i]); (*note)(param, obj._variables[i]);
} else { } else {
warning("Request for outgoing script-object reference at "PREG" yielded invalid index %d", PRINT_REG(addr), idx); warning("Request for outgoing script-object reference at "PREG" yielded invalid index %d", PRINT_REG(addr), idx);
} }
@ -1188,7 +1183,6 @@ void Table<T>::listAllDeallocatable(SegmentId segId, void *param, NoteCallback n
void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
CloneTable *clone_table = this; CloneTable *clone_table = this;
Clone *clone; Clone *clone;
int i;
// assert(addr.segment == _segId); // assert(addr.segment == _segId);
@ -1201,8 +1195,8 @@ void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *par
clone = &(clone_table->_table[addr.offset]); clone = &(clone_table->_table[addr.offset]);
// Emit all member variables (including references to the 'super' delegate) // Emit all member variables (including references to the 'super' delegate)
for (i = 0; i < clone->variables_nr; i++) for (uint i = 0; i < clone->_variables.size(); i++)
(*note)(param, clone->variables[i]); (*note)(param, clone->_variables[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->pos);
@ -1229,8 +1223,6 @@ void CloneTable::freeAtAddress(SegManager *segmgr, reg_t addr) {
sciprintf("[GC] Clone "PREG": Freeing\n", PRINT_REG(addr)); sciprintf("[GC] Clone "PREG": Freeing\n", PRINT_REG(addr));
sciprintf("[GC] Clone had pos "PREG"\n", PRINT_REG(victim_obj->pos)); sciprintf("[GC] Clone had pos "PREG"\n", PRINT_REG(victim_obj->pos));
*/ */
free(victim_obj->variables);
victim_obj->variables = NULL;
clone_table->freeEntry(addr.offset); clone_table->freeEntry(addr.offset);
} }
@ -1248,8 +1240,8 @@ reg_t LocalVariables::findCanonicAddress(SegManager *segmgr, reg_t addr) {
void LocalVariables::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { void LocalVariables::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
// assert(addr.segment == _segId); // assert(addr.segment == _segId);
for (int i = 0; i < nr; i++) for (uint i = 0; i < _locals.size(); i++)
(*note)(param, locals[i]); (*note)(param, _locals[i]);
} }

View file

@ -395,7 +395,7 @@ private:
Hunk *alloc_Hunk(reg_t *); Hunk *alloc_Hunk(reg_t *);
int relocateLocal(Script *scr, SegmentId segment, int location); int relocateLocal(Script *scr, SegmentId segment, int location);
int relocateBlock(reg_t *block, int block_location, int block_items, SegmentId segment, int location); int relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location);
int relocateObject(Object *obj, SegmentId segment, int location); int relocateObject(Object *obj, SegmentId segment, int location);
int findFreeId(int *id); int findFreeId(int *id);

View file

@ -231,7 +231,7 @@ public:
SegmentId script_000_segment; SegmentId script_000_segment;
Script *script_000; /**< script 000, e.g. for globals */ Script *script_000; /**< script 000, e.g. for globals */
uint16 currentRoomNumber() { return KP_UINT(script_000->locals_block->locals[13]); } uint16 currentRoomNumber() { return KP_UINT(script_000->locals_block->_locals[13]); }
int parser_lastmatch_word; /**< Position of the input word the parser last matched on, or SAID_NO_MATCH */ int parser_lastmatch_word; /**< Position of the input word the parser last matched on, or SAID_NO_MATCH */

View file

@ -72,16 +72,16 @@ static reg_t &validate_property(Object *obj, int index) {
return _dummy_register; return _dummy_register;
} }
if (index < 0 || index >= obj->variables_nr) { if (index < 0 || (uint)index >= obj->_variables.size()) {
if (sci_debug_flags & 4) if (sci_debug_flags & 4)
sciprintf("[VM] Invalid property #%d (out of [0..%d]) requested!\n", index, sciprintf("[VM] Invalid property #%d (out of [0..%d]) requested!\n", index,
obj->variables_nr); obj->_variables.size());
_dummy_register = NULL_REG; _dummy_register = NULL_REG;
return _dummy_register; return _dummy_register;
} }
return obj->variables[index]; return obj->_variables[index];
} }
static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) { static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) {
@ -176,7 +176,7 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
# define validate_variable(r, sb, t, m, i, l) # define validate_variable(r, sb, t, m, i, l)
# define validate_read_var(r, sb, t, m, i, l) ((r)[i]) # define validate_read_var(r, sb, t, m, i, l) ((r)[i])
# define validate_write_var(r, sb, t, m, i, l, v) ((r)[i] = (v)) # define validate_write_var(r, sb, t, m, i, l, v) ((r)[i] = (v))
# define validate_property(o, p) ((o)->variables[p]) # define validate_property(o, p) ((o)->_variables[p])
# define ASSERT_ARITHMETIC(v) (v).offset # define ASSERT_ARITHMETIC(v) (v).offset
#endif #endif
@ -614,7 +614,7 @@ void run_vm(EngineState *s, int restoring) {
#ifndef DISABLE_VALIDATIONS #ifndef DISABLE_VALIDATIONS
// Initialize maximum variable count // Initialize maximum variable count
if (s->script_000->locals_block) if (s->script_000->locals_block)
variables_max[VAR_GLOBAL] = s->script_000->locals_block->nr; variables_max[VAR_GLOBAL] = s->script_000->locals_block->_locals.size();
else else
variables_max[VAR_GLOBAL] = 0; variables_max[VAR_GLOBAL] = 0;
#endif #endif
@ -625,7 +625,7 @@ void run_vm(EngineState *s, int restoring) {
// SCI code reads the zeroeth argument to determine argc // SCI code reads the zeroeth argument to determine argc
if (s->script_000->locals_block) if (s->script_000->locals_block)
variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = s->script_000->locals_block->locals; variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = s->script_000->locals_block->_locals.begin();
else else
variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = NULL; variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = NULL;
@ -682,12 +682,12 @@ void run_vm(EngineState *s, int restoring) {
variables_seg[VAR_LOCAL] = local_script->locals_segment; variables_seg[VAR_LOCAL] = local_script->locals_segment;
if (local_script->locals_block) if (local_script->locals_block)
variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = local_script->locals_block->locals; variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = local_script->locals_block->_locals.begin();
else else
variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = NULL; variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = NULL;
#ifndef DISABLE_VALIDATIONS #ifndef DISABLE_VALIDATIONS
if (local_script->locals_block) if (local_script->locals_block)
variables_max[VAR_LOCAL] = local_script->locals_block->nr; variables_max[VAR_LOCAL] = local_script->locals_block->_locals.size();
else else
variables_max[VAR_LOCAL] = 0; variables_max[VAR_LOCAL] = 0;
variables_max[VAR_TEMP] = xs->sp - xs->fp; variables_max[VAR_TEMP] = xs->sp - xs->fp;
@ -1489,10 +1489,10 @@ static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) {
} else { } else {
byte *buf = (byte *) obj->base_vars; byte *buf = (byte *) obj->base_vars;
int i; int i;
int varnum = obj->variables[1].offset; int varnum = obj->_variables[1].offset;
if (!(obj->variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS))
buf = ((byte *) obj_get(s, obj->variables[SCRIPT_SUPERCLASS_SELECTOR])->base_vars); buf = ((byte *) obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR])->base_vars);
for (i = 0; i < varnum; i++) for (i = 0; i < varnum; i++)
if (READ_LE_UINT16(buf + (i << 1)) == slc) // Found it? if (READ_LE_UINT16(buf + (i << 1)) == slc) // Found it?
@ -1534,8 +1534,8 @@ static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object
return kSelectorMethod; return kSelectorMethod;
} else { } else {
seg_id = obj->variables[SCRIPT_SUPERCLASS_SELECTOR].segment; seg_id = obj->_variables[SCRIPT_SUPERCLASS_SELECTOR].segment;
obj = obj_get(s, obj->variables[SCRIPT_SUPERCLASS_SELECTOR]); obj = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
} }
} }
@ -1561,13 +1561,13 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select
if (IS_CLASS(obj)) if (IS_CLASS(obj))
species = obj; species = obj;
else else
species = obj_get(s, obj->variables[SCRIPT_SPECIES_SELECTOR]); species = obj_get(s, obj->_variables[SCRIPT_SPECIES_SELECTOR]);
if (!obj) { if (!obj) {
CORE_ERROR("SLC-LU", "Error while looking up Species class"); CORE_ERROR("SLC-LU", "Error while looking up Species class");
sciprintf("Original address was "PREG"\n", PRINT_REG(obj_location)); sciprintf("Original address was "PREG"\n", PRINT_REG(obj_location));
sciprintf("Species address was "PREG"\n", PRINT_REG(obj->variables[SCRIPT_SPECIES_SELECTOR])); sciprintf("Species address was "PREG"\n", PRINT_REG(obj->_variables[SCRIPT_SPECIES_SELECTOR]));
return kSelectorNone; return kSelectorNone;
} }
@ -1576,7 +1576,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select
if (index >= 0) { if (index >= 0) {
// Found it as a variable // Found it as a variable
if (vptr) if (vptr)
*vptr = obj->variables + index; *vptr = &obj->_variables[index];
return kSelectorVariable; return kSelectorVariable;
} }
@ -1851,14 +1851,14 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
Object *base_obj; Object *base_obj;
// Instantiate the superclass, if neccessary // Instantiate the superclass, if neccessary
obj->variables[SCRIPT_SPECIES_SELECTOR] = INST_LOOKUP_CLASS(obj->variables[SCRIPT_SPECIES_SELECTOR].offset); obj->_variables[SCRIPT_SPECIES_SELECTOR] = INST_LOOKUP_CLASS(obj->_variables[SCRIPT_SPECIES_SELECTOR].offset);
base_obj = obj_get(s, obj->variables[SCRIPT_SPECIES_SELECTOR]); base_obj = obj_get(s, obj->_variables[SCRIPT_SPECIES_SELECTOR]);
obj->variable_names_nr = base_obj->variables_nr; obj->variable_names_nr = base_obj->_variables.size();
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
obj->variables[SCRIPT_SUPERCLASS_SELECTOR] = INST_LOOKUP_CLASS(obj->variables[SCRIPT_SUPERCLASS_SELECTOR].offset); obj->_variables[SCRIPT_SUPERCLASS_SELECTOR] = INST_LOOKUP_CLASS(obj->_variables[SCRIPT_SUPERCLASS_SELECTOR].offset);
} // if object or class } // if object or class
break; break;
case sci_obj_pointers: // A relocation table case sci_obj_pointers: // A relocation table
@ -2114,7 +2114,7 @@ const char *obj_get_name(EngineState *s, reg_t pos) {
if (!obj) if (!obj)
return "<no such object>"; return "<no such object>";
return (const char *)(obj->base + obj->variables[SCRIPT_NAME_SELECTOR].offset); return (const char *)(obj->base + obj->_variables[SCRIPT_NAME_SELECTOR].offset);
} }
void quit_vm() { void quit_vm() {

View file

@ -225,7 +225,7 @@ struct Class {
#define RAW_GET_CLASS_INDEX(scr, reg) ((scr)->obj_indices->checkKey(reg.offset, false)) #define RAW_GET_CLASS_INDEX(scr, reg) ((scr)->obj_indices->checkKey(reg.offset, false))
#define RAW_IS_OBJECT(datablock) (READ_LE_UINT16(((byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) #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) #define IS_CLASS(obj) (obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)
/** This struct is used to buffer the list of send calls in send_selector() */ /** This struct is used to buffer the list of send calls in send_selector() */
struct CallsStruct { struct CallsStruct {
@ -242,18 +242,11 @@ struct CallsStruct {
struct LocalVariables : public MemObject { struct LocalVariables : public MemObject {
int script_id; /**< Script ID this local variable block belongs to */ int script_id; /**< Script ID this local variable block belongs to */
reg_t *locals; Common::Array<reg_t> _locals;
int nr;
public: public:
LocalVariables() { LocalVariables() {
script_id = 0; script_id = 0;
locals = 0;
nr = 0;
}
~LocalVariables() {
free(locals);
locals = NULL;
} }
virtual byte *dereference(reg_t pointer, int *size); virtual byte *dereference(reg_t pointer, int *size);
@ -269,14 +262,13 @@ public:
struct Object { struct Object {
int flags; int flags;
reg_t pos; /**< Object offset within its script; for clones, this is their base */ reg_t pos; /**< Object offset within its script; for clones, this is their base */
int variables_nr;
int variable_names_nr; /**< Number of variable names, may be less than variables_nr */ int variable_names_nr; /**< Number of variable names, may be less than variables_nr */
int methods_nr; int methods_nr;
byte *base; /**< Points to a buffer all relative references (code, strings) point to */ byte *base; /**< Points to a buffer all relative references (code, strings) point to */
byte *base_obj; /**< base + object offset within base */ byte *base_obj; /**< base + object offset within base */
uint16 *base_method; /**< Pointer to the method selector area for this object */ uint16 *base_method; /**< Pointer to the method selector area for this object */
uint16 *base_vars; /**< Pointer to the varselector area for this object */ uint16 *base_vars; /**< Pointer to the varselector area for this object */
reg_t *variables; Common::Array<reg_t> _variables;
}; };
struct CodeBlock { struct CodeBlock {
@ -286,9 +278,9 @@ struct CodeBlock {
#define VM_OBJECT_GET_VARSELECTOR(obj, i) \ #define VM_OBJECT_GET_VARSELECTOR(obj, i) \
(s->version < SCI_VERSION(1,001,000) ? \ (s->version < SCI_VERSION(1,001,000) ? \
READ_LE_UINT16(obj->base_obj + obj->variables_nr * 2 + i*2) : \ READ_LE_UINT16(obj->base_obj + obj->_variables.size() * 2 + i*2) : \
*(obj->base_vars + i)) *(obj->base_vars + i))
#define VM_OBJECT_READ_PROPERTY(obj, i) (obj->variables[i]) #define VM_OBJECT_READ_PROPERTY(obj, i) (obj->_variables[i])
#define VM_OBJECT_GET_FUNCSELECTOR(obj, i) \ #define VM_OBJECT_GET_FUNCSELECTOR(obj, i) \
(s->version < SCI_VERSION(1,001,000) ? \ (s->version < SCI_VERSION(1,001,000) ? \
READ_LE_UINT16((byte *) (obj->base_method + i)) : \ READ_LE_UINT16((byte *) (obj->base_method + i)) : \
@ -485,12 +477,6 @@ public:
/* CloneTable */ /* CloneTable */
struct CloneTable : public Table<Clone> { struct CloneTable : public Table<Clone> {
virtual void freeEntry(int idx) {
Table<Clone>::freeEntry(idx);
free(_table[idx].variables); // Free the dynamically allocated memory part
}
virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr);
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
}; };