diff options
author | Max Horn | 2009-05-11 13:32:00 +0000 |
---|---|---|
committer | Max Horn | 2009-05-11 13:32:00 +0000 |
commit | 1949133d22a3435c7a3ae4532d59967d27cf7708 (patch) | |
tree | bb06e84dda4275406d46a6708a811f060780e53c /engines/sci/engine | |
parent | d66d1ffab302c6146d0262c873287347c9f69267 (diff) | |
download | scummvm-rg350-1949133d22a3435c7a3ae4532d59967d27cf7708.tar.gz scummvm-rg350-1949133d22a3435c7a3ae4532d59967d27cf7708.tar.bz2 scummvm-rg350-1949133d22a3435c7a3ae4532d59967d27cf7708.zip |
SCI: Simplified the Table class, by making it use an Common::Array internally. Increased savegame version, breaking compatibility to the previous one -- sorry for that, but some of my previous changes accidentally messed up the table syncing, resulting in messed up savegames anyway; these breakages should be fixed with this commit
svn-id: r40453
Diffstat (limited to 'engines/sci/engine')
-rw-r--r-- | engines/sci/engine/kernel.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/klists.cpp | 4 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 123 | ||||
-rw-r--r-- | engines/sci/engine/scriptconsole.cpp | 26 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 27 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.cpp | 25 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/state.h | 10 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 19 | ||||
-rw-r--r-- | engines/sci/engine/vm.h | 58 |
10 files changed, 128 insertions, 167 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 43e78866ad..d5a1ba2bf5 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -246,7 +246,7 @@ byte *kmem(EngineState *s, reg_t handle) { return NULL; } - return (byte *)ht->table[handle.offset].mem; + return (byte *)ht->_table[handle.offset].mem; } // Frees the specified handle. Returns 0 on success, 1 otherwise. diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 20d8b97c0c..da115499a0 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -50,7 +50,7 @@ Node *lookup_node(EngineState *s, reg_t addr, const char *file, int line) { return NULL; } - return &(nt->table[addr.offset]); + return &(nt->_table[addr.offset]); } List *lookup_list(EngineState *s, reg_t addr, const char *file, int line) { @@ -70,7 +70,7 @@ List *lookup_list(EngineState *s, reg_t addr, const char *file, int line) { return NULL; } - return &(lt->table[addr.offset]); + return &(lt->_table[addr.offset]); } #ifdef DISABLE_VALIDATIONS diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index e099d81b88..544f918468 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -181,15 +181,14 @@ void Menubar::saveLoadWithSerializer(Common::Serializer &s) { } void SegManager::saveLoadWithSerializer(Common::Serializer &s) { - uint sync_heap_size = _heap.size(); - s.syncAsUint32LE(sync_heap_size); s.syncAsSint32LE(reserved_id); s.syncAsSint32LE(exports_wide); s.syncAsSint32LE(gc_mark_bits); - s.syncAsUint32LE(mem_allocated); id_seg_map->saveLoadWithSerializer(s); + uint sync_heap_size = _heap.size(); + s.syncAsUint32LE(sync_heap_size); _heap.resize(sync_heap_size); for (uint i = 0; i < sync_heap_size; ++i) sync_MemObjPtr(s, _heap[i]); @@ -269,8 +268,8 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { static void sync_LocalVariables(Common::Serializer &s, LocalVariables &obj) { s.syncAsSint32LE(obj.script_id); - s.syncAsSint32LE(obj.nr); + s.syncAsSint32LE(obj.nr); if (!obj.locals && obj.nr) obj.locals = (reg_t *)sci_calloc(obj.nr, sizeof(reg_t)); for (int i = 0; i < obj.nr; ++i) @@ -281,10 +280,10 @@ template <> void syncWithSerializer(Common::Serializer &s, Object &obj) { s.syncAsSint32LE(obj.flags); sync_reg_t(s, obj.pos); - s.syncAsSint32LE(obj.variables_nr); s.syncAsSint32LE(obj.variable_names_nr); s.syncAsSint32LE(obj.methods_nr); + s.syncAsSint32LE(obj.variables_nr); if (!obj.variables && obj.variables_nr) obj.variables = (reg_t *)sci_calloc(obj.variables_nr, sizeof(reg_t)); for (int i = 0; i < obj.variables_nr; ++i) @@ -292,13 +291,24 @@ void syncWithSerializer(Common::Serializer &s, Object &obj) { } template <> -void syncWithSerializer(Common::Serializer &s, List &obj) { +void syncWithSerializer(Common::Serializer &s, Table<Clone>::Entry &obj) { + s.syncAsSint32LE(obj.next_free); + + syncWithSerializer<Object>(s, obj); +} + +template <> +void syncWithSerializer(Common::Serializer &s, Table<List>::Entry &obj) { + s.syncAsSint32LE(obj.next_free); + sync_reg_t(s, obj.first); sync_reg_t(s, obj.last); } template <> -void syncWithSerializer(Common::Serializer &s, Node &obj) { +void syncWithSerializer(Common::Serializer &s, Table<Node>::Entry &obj) { + s.syncAsSint32LE(obj.next_free); + sync_reg_t(s, obj.pred); sync_reg_t(s, obj.succ); sync_reg_t(s, obj.key); @@ -306,18 +316,12 @@ void syncWithSerializer(Common::Serializer &s, Node &obj) { } template <typename T> -static void sync_Table(Common::Serializer &s, T &obj) { - s.syncAsSint32LE(obj.entries_nr); +void sync_Table(Common::Serializer &s, T &obj) { + // TODO: Change this to use syncArray. This involves breaking the savegame format compatibility. s.syncAsSint32LE(obj.first_free); s.syncAsSint32LE(obj.entries_used); - s.syncAsSint32LE(obj.max_entry); - if (!obj.table && obj.entries_nr) - obj.table = (typename T::Entry *)sci_calloc(obj.entries_nr, sizeof(typename T::Entry)); - for (int i = 0; i < obj.entries_nr; ++i) { - s.syncAsSint32LE(obj.table[i].next_free); - syncWithSerializer<typename T::value_type>(s, obj.table[i]); - } + syncArray<typename T::Entry>(s, obj._table); } static void sync_Script(Common::Serializer &s, Script &obj) { @@ -338,21 +342,7 @@ static void sync_Script(Common::Serializer &s, Script &obj) { s.syncAsSint32LE(obj.synonyms_nr); s.syncAsSint32LE(obj.lockers); -#if 1 - uint len = obj._objects.size(); - s.syncAsUint32LE(len); // Used to be obj.objects_allocated - s.skip(4); // Used to be obj.objects_nr - // Resize the array if loading. - if (s.isLoading()) - obj._objects.resize(len); - Common::Array<Object>::iterator i; - for (i = obj._objects.begin(); i != obj._objects.end(); ++i) { - syncWithSerializer<Object>(s, *i); - } -#else - s.skip(4); // Used to be obj.objects_allocated syncArray<Object>(s, obj._objects); -#endif s.syncAsSint32LE(obj.locals_offset); s.syncAsSint32LE(obj.locals_segment); @@ -384,6 +374,14 @@ static void sync_DynMem(Common::Serializer &s, DynMem &obj) { s.syncBytes(obj._buf, obj._size); } +static void sync_DataStack(Common::Serializer &s, DataStack &obj) { + s.syncAsUint32LE(obj.nr); + if (s.isLoading()) { + //free(obj.entries); + obj.entries = (reg_t *)sci_calloc(obj.nr, sizeof(reg_t)); + } +} + #pragma mark - static void sync_songlib_t(Common::Serializer &s, songlib_t &obj) { @@ -443,12 +441,7 @@ static void sync_MemObjPtr(Common::Serializer &s, MemObject *&mobj) { sync_SystemStrings(s, *(SystemStrings *)mobj); break; case MEM_OBJ_STACK: - // TODO: Switch this stack to use class Common::Stack? - s.syncAsUint32LE((*(DataStack *)mobj).nr); - if (s.isLoading()) { - //free((*(DataStack *)mobj).entries); - (*(DataStack *)mobj).entries = (reg_t *)sci_calloc((*(DataStack *)mobj).nr, sizeof(reg_t)); - } + sync_DataStack(s, *(DataStack *)mobj); break; case MEM_OBJ_HUNK: if (s.isLoading()) { @@ -551,20 +544,16 @@ static void reconstruct_stack(EngineState *retval) { retval->stack_top = retval->stack_base + VM_STACK_SIZE; } -static int clone_entry_used(CloneTable *table, int n) { - int backup; +static bool clone_entry_used(CloneTable *table, int n) { int seeker = table->first_free; - CloneTable::Entry *entries = table->table; - - if (seeker == CloneTable::HEAPENTRY_INVALID) return 1; - do { - if (seeker == n) return 0; - backup = seeker; - seeker = entries[seeker].next_free; - } while (entries[backup].next_free != CloneTable::HEAPENTRY_INVALID); + while (seeker != CloneTable::HEAPENTRY_INVALID) { + if (seeker == n) + return false; + seeker = table->_table[seeker].next_free; + } - return 1; + return true; } static void load_script(EngineState *s, SegmentId seg) { @@ -666,52 +655,46 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { // FIXME: The following should likely become a SegManager method static void reconstruct_clones(EngineState *s, SegManager *self) { - uint i; - MemObject *mobj; - - for (i = 0; i < self->_heap.size(); i++) { + for (uint i = 0; i < self->_heap.size(); i++) { if (self->_heap[i]) { - mobj = self->_heap[i]; + MemObject *mobj = self->_heap[i]; switch (mobj->getType()) { case MEM_OBJ_CLONES: { - int j; - CloneTable::Entry *seeker = (*(CloneTable *)mobj).table; + CloneTable *ct = (CloneTable *)mobj; /* sciprintf("Free list: "); - for (j = (*(CloneTable *)mobj).first_free; j != HEAPENTRY_INVALID; j = (*(CloneTable *)mobj).table[j].next_free) { + for (uint j = ct->first_free; j != HEAPENTRY_INVALID; j = ct->_table[j].next_free) { sciprintf("%d ", j); } sciprintf("\n"); sciprintf("Entries w/zero vars: "); - for (j = 0; j < (*(CloneTable *)mobj).max_entry; j++) { - if ((*(CloneTable *)mobj).table[j].variables == NULL) + for (uint j = 0; j < ct->_table.size(); j++) { + if (ct->_table[j].variables == NULL) sciprintf("%d ", j); } sciprintf("\n"); */ - for (j = 0; j < (*(CloneTable *)mobj).max_entry; j++) { + for (uint j = 0; j < ct->_table.size(); j++) { Object *base_obj; - if (!clone_entry_used(&(*(CloneTable *)mobj), j)) { - seeker++; + if (!clone_entry_used(ct, j)) { continue; } - base_obj = obj_get(s, seeker->variables[SCRIPT_SPECIES_SELECTOR]); + CloneTable::Entry &seeker = ct->_table[j]; + base_obj = obj_get(s, seeker.variables[SCRIPT_SPECIES_SELECTOR]); if (!base_obj) { sciprintf("Clone entry without a base class: %d\n", j); - seeker->base = seeker->base_obj = NULL; - seeker->base_vars = seeker->base_method = NULL; - continue; + seeker.base = seeker.base_obj = NULL; + seeker.base_vars = seeker.base_method = NULL; + } else { + seeker.base = base_obj->base; + seeker.base_obj = base_obj->base_obj; + seeker.base_vars = base_obj->base_vars; + seeker.base_method = base_obj->base_method; } - seeker->base = base_obj->base; - seeker->base_obj = base_obj->base_obj; - seeker->base_vars = base_obj->base_vars; - seeker->base_method = base_obj->base_method; - - seeker++; } break; diff --git a/engines/sci/engine/scriptconsole.cpp b/engines/sci/engine/scriptconsole.cpp index f894f3f931..c114314531 100644 --- a/engines/sci/engine/scriptconsole.cpp +++ b/engines/sci/engine/scriptconsole.cpp @@ -54,18 +54,16 @@ struct cmd_mm_entry_t { const char *description; }; // All later structures must "extend" this -typedef cmd_mm_entry_t cmd_page_t; // Simple info page +// Simple info page +struct cmd_page_t : public cmd_mm_entry_t { +}; -struct cmd_command_t { - const char *name; - const char *description; +struct cmd_command_t : public cmd_mm_entry_t { ConCommand command; const char *param; }; -struct cmd_var_t { - const char *name; - const char *description; +struct cmd_var_t : public cmd_mm_entry_t { union { int *intp; char **charpp; @@ -128,9 +126,11 @@ void _cmd_exit() { static cmd_mm_entry_t *cmd_mm_find(char *name, int type) { int i; - for (i = 0; i < cmd_mm[type].entries; i++) - if (!strcmp(((cmd_mm_entry_t *)((byte *)cmd_mm[type].data + i * cmd_mm[type].size_per_entry))->name, name)) - return ((cmd_mm_entry_t *)((byte *)cmd_mm[type].data + i * cmd_mm[type].size_per_entry)); + for (i = 0; i < cmd_mm[type].entries; i++) { + cmd_mm_entry_t *tmp = (cmd_mm_entry_t *)((byte *)cmd_mm[type].data + i * cmd_mm[type].size_per_entry); + if (!strcmp(tmp->name, name)) + return tmp; + } return NULL; } @@ -310,7 +310,7 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on if (mobj->getType() == MEM_OBJ_SCRIPT) max_index = (*(Script *)mobj)._objects.size(); else if (mobj->getType() == MEM_OBJ_CLONES) - max_index = (*(CloneTable *)mobj).max_entry; + max_index = (*(CloneTable *)mobj)._table.size(); } while (idx < max_index) { @@ -324,7 +324,7 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on obj = &(*(Script *)mobj)._objects[idx]; objpos.offset = obj->pos.offset; } else if (mobj->getType() == MEM_OBJ_CLONES) { - obj = &((*(CloneTable *)mobj).table[idx]); + obj = &((*(CloneTable *)mobj)._table[idx]); objpos.offset = idx; valid = clone_is_used((CloneTable *)mobj, idx); } @@ -579,7 +579,7 @@ static cmd_mm_entry_t *con_alloc_page_entry(int ID) { else nextsize <<= 1; - cmd_mm[ID].data = sci_realloc(cmd_mm[ID].data, nextsize * cmd_mm[ID].size_per_entry); + cmd_mm[ID].data = realloc(cmd_mm[ID].data, nextsize * cmd_mm[ID].size_per_entry); cmd_mm[ID].allocated = nextsize; } diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 4d90b15d54..0bfb46df1f 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -366,7 +366,7 @@ static void print_list(EngineState *s, List *l) { return; } - node = &((*(NodeTable *)mobj).table[pos.offset]); + node = &((*(NodeTable *)mobj)._table[pos.offset]); sciprintf("\t"PREG" : "PREG" -> "PREG"\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value)); @@ -437,28 +437,26 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) { break; case MEM_OBJ_CLONES: { - int i = 0; CloneTable *ct = (CloneTable *)mobj; sciprintf("clones\n"); - for (i = 0; i < ct->max_entry; i++) - if (ENTRY_IS_VALID(ct, i)) { + for (uint i = 0; i < ct->_table.size(); i++) + if (ct->isValidEntry(i)) { sciprintf(" [%04x] ", i); - print_obj_head(s, &(ct->table[i])); + print_obj_head(s, &(ct->_table[i])); } } break; case MEM_OBJ_LISTS: { - int i = 0; ListTable *lt = (ListTable *)mobj; sciprintf("lists\n"); - for (i = 0; i < lt->max_entry; i++) - if (ENTRY_IS_VALID(lt, i)) { + for (uint i = 0; i < lt->_table.size(); i++) + if (lt->isValidEntry(i)) { sciprintf(" [%04x]: ", i); - print_list(s, &(lt->table[i])); + print_list(s, &(lt->_table[i])); } } break; @@ -469,14 +467,13 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) { } case MEM_OBJ_HUNK: { - int i; HunkTable *ht = (HunkTable *)mobj; sciprintf("hunk (total %d)\n", ht->entries_used); - for (i = 0; i < ht->max_entry; i++) - if (ENTRY_IS_VALID(ht, i)) { + for (uint i = 0; i < ht->_table.size(); i++) + if (ht->isValidEntry(i)) { sciprintf(" [%04x] %d bytes at %p, type=%s\n", - i, ht->table[i].size, ht->table[i].mem, ht->table[i].type); + i, ht->_table[i].size, ht->_table[i].mem, ht->_table[i].type); } } @@ -511,7 +508,7 @@ static int show_node(EngineState *s, reg_t addr) { return 1; } - list = &(lt->table[addr.offset]); + list = &(lt->_table[addr.offset]); sciprintf(PREG" : first x last = ("PREG", "PREG")\n", PRINT_REG(addr), PRINT_REG(list->first), PRINT_REG(list->last)); } else { @@ -530,7 +527,7 @@ static int show_node(EngineState *s, reg_t addr) { sciprintf("Address does not contain a node\n"); return 1; } - node = &(nt->table[addr.offset]); + node = &(nt->_table[addr.offset]); sciprintf(PREG" : prev x next = ("PREG", "PREG"); maps "PREG" -> "PREG"\n", PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(node->succ), PRINT_REG(node->key), PRINT_REG(node->value)); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 0878703eb1..59773e00c6 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -75,9 +75,6 @@ MemObject *SegManager::allocNonscriptSegment(MemObjectType type, SegmentId *segi } SegManager::SegManager(bool sci1_1) { - // Initialise memory count - mem_allocated = 0; - id_seg_map = new IntMapper(); reserved_id = INVALID_SCRIPT_ID; id_seg_map->checkKey(reserved_id, true); // reserve 0 for seg_id @@ -966,7 +963,7 @@ Clone *SegManager::alloc_Clone(reg_t *addr) { offset = table->allocEntry(); *addr = make_reg(Clones_seg_id, offset); - return &(table->table[offset]); + return &(table->_table[offset]); } List *SegManager::alloc_List(reg_t *addr) { @@ -982,7 +979,7 @@ List *SegManager::alloc_List(reg_t *addr) { offset = table->allocEntry(); *addr = make_reg(Lists_seg_id, offset); - return &(table->table[offset]); + return &(table->_table[offset]); } Node *SegManager::alloc_Node(reg_t *addr) { @@ -998,7 +995,7 @@ Node *SegManager::alloc_Node(reg_t *addr) { offset = table->allocEntry(); *addr = make_reg(Nodes_seg_id, offset); - return &(table->table[offset]); + return &(table->_table[offset]); } Hunk *SegManager::alloc_Hunk(reg_t *addr) { @@ -1014,7 +1011,7 @@ Hunk *SegManager::alloc_Hunk(reg_t *addr) { offset = table->allocEntry(); *addr = make_reg(Hunks_seg_id, offset); - return &(table->table[offset]); + return &(table->_table[offset]); } byte *MemObject::dereference(reg_t pointer, int *size) { @@ -1181,9 +1178,9 @@ void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, //-------------------- clones -------------------- -template<typename T, int INITIAL, int INCREMENT> -void Table<T, INITIAL, INCREMENT>::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { - for (int i = 0; i < max_entry; i++) +template<typename T> +void Table<T>::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { + for (uint i = 0; i < _table.size(); i++) if (isValidEntry(i)) (*note)(param, make_reg(segId, i)); } @@ -1201,7 +1198,7 @@ void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *par return; } - clone = &(clone_table->table[addr.offset]); + clone = &(clone_table->_table[addr.offset]); // Emit all member variables (including references to the 'super' delegate) for (i = 0; i < clone->variables_nr; i++) @@ -1218,7 +1215,7 @@ void CloneTable::freeAtAddress(SegManager *segmgr, reg_t addr) { // assert(addr.segment == _segId); - victim_obj = &(clone_table->table[addr.offset]); + victim_obj = &(clone_table->_table[addr.offset]); #ifdef GC_DEBUG if (!(victim_obj->flags & OBJECT_FLAG_FREED)) @@ -1281,7 +1278,7 @@ void ListTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *para return; } - List *list = &(table[addr.offset]); + List *list = &(_table[addr.offset]); note(param, list->first); note(param, list->last); @@ -1300,7 +1297,7 @@ void NodeTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *para warning("Invalid node referenced for outgoing references: "PREG"", PRINT_REG(addr)); return; } - Node *node = &(table[addr.offset]); + Node *node = &(_table[addr.offset]); // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us // to walk around from any given node diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 9ebdd60837..50d34081e2 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -380,7 +380,6 @@ public: // TODO: make private // For standard Mark&Sweep: // 1 or 0, depending on what unreachable/freshly allocated // memory is tagged as - size_t mem_allocated; // Total amount of memory allocated SegmentId Clones_seg_id; // ID of the (a) clones segment SegmentId Lists_seg_id; // ID of the (a) list segment diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index d8068a0c99..67a29591a8 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -73,12 +73,14 @@ public: void nextFile(); }; -#define CURRENT_SAVEGAME_VERSION 8 -#define MINIMUM_SAVEGAME_VERSION 8 +enum { + CURRENT_SAVEGAME_VERSION = 9, + MINIMUM_SAVEGAME_VERSION = 9, -#define MAX_SAVEGAME_NR 20 /**< Maximum number of savegames */ + MAX_SAVEGAME_NR = 20, /**< Maximum number of savegames */ -#define MAX_SAVE_DIR_SIZE MAXPATHLEN + MAX_SAVE_DIR_SIZE = MAXPATHLEN +}; /** values for EngineState.restarting_flag */ enum { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 60faca0425..73215a5d96 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -2086,14 +2086,17 @@ Object *obj_get(EngineState *s, reg_t offset) { int idx; if (memobj != NULL) { - if (memobj->getType() == MEM_OBJ_CLONES && ENTRY_IS_VALID((CloneTable *)memobj, offset.offset)) - obj = &((*(CloneTable *)memobj).table[offset.offset]); - else if (memobj->getType() == MEM_OBJ_SCRIPT) { - if (offset.offset <= (*(Script *)memobj).buf_size && offset.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET - && RAW_IS_OBJECT((*(Script *)memobj).buf + offset.offset)) { - idx = RAW_GET_CLASS_INDEX((Script *)memobj, offset); - if (idx >= 0 && (uint)idx < (*(Script *)memobj)._objects.size()) - obj = &(*(Script *)memobj)._objects[idx]; + if (memobj->getType() == MEM_OBJ_CLONES) { + CloneTable *ct = (CloneTable *)memobj; + if (ct->isValidEntry(offset.offset)) + obj = &(ct->_table[offset.offset]); + } else if (memobj->getType() == MEM_OBJ_SCRIPT) { + Script *scr = (Script *)memobj; + if (offset.offset <= scr->buf_size && offset.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET + && RAW_IS_OBJECT(scr->buf + offset.offset)) { + idx = RAW_GET_CLASS_INDEX(scr, offset); + if (idx >= 0 && (uint)idx < scr->_objects.size()) + obj = &scr->_objects[idx]; } } } diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index f3dc1ce96a..f7b5adae7d 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -420,7 +420,7 @@ struct Hunk { const char *type; }; -template<typename T, int INITIAL, int INCREMENT> +template<typename T> struct Table : public MemObject { typedef T value_type; struct Entry : public T { @@ -429,67 +429,47 @@ struct Table : public MemObject { enum { HEAPENTRY_INVALID = -1 }; - int entries_nr; /**< Number of entries allocated */ int first_free; /**< Beginning of a singly linked list for entries */ int entries_used; /**< Statistical information */ - int max_entry; /**< Highest entry used */ - Entry *table; + Common::Array<Entry> _table; public: Table() { - entries_nr = 0; - max_entry = 0; entries_used = 0; first_free = HEAPENTRY_INVALID; - table = NULL; - } - - ~Table() { - // FIXME: Shouldn't we make sure that all table entries are disposed - // of properly? - free(table); - table = NULL; - entries_nr = max_entry = 0; } void initTable() { - entries_nr = INITIAL; - max_entry = 0; entries_used = 0; first_free = HEAPENTRY_INVALID; - table = (Entry *)calloc(INITIAL, sizeof(Entry)); } int allocEntry() { entries_used++; if (first_free != HEAPENTRY_INVALID) { int oldff = first_free; - first_free = table[oldff].next_free; + first_free = _table[oldff].next_free; - table[oldff].next_free = oldff; + _table[oldff].next_free = oldff; return oldff; } else { - if (max_entry == entries_nr) { - entries_nr += INCREMENT; - - table = (Entry *)sci_realloc(table, sizeof(Entry) * entries_nr); - memset(&table[entries_nr-INCREMENT], 0, INCREMENT * sizeof(Entry)); - } - table[max_entry].next_free = max_entry; /* Tag as 'valid' */ - return max_entry++; + uint newIdx = _table.size(); + _table.push_back(Entry()); + _table[newIdx].next_free = newIdx; // Tag as 'valid' + return newIdx; } } bool isValidEntry(int idx) { - return idx >= 0 && idx < max_entry && table[idx].next_free == idx; + return idx >= 0 && (uint)idx < _table.size() && _table[idx].next_free == idx; } virtual void freeEntry(int idx) { - if (idx < 0 || idx >= max_entry) + if (idx < 0 || (uint)idx >= _table.size()) ::error("Table::freeEntry: Attempt to release invalid table index %d", idx); - table[idx].next_free = first_free; + _table[idx].next_free = first_free; first_free = idx; entries_used--; } @@ -504,11 +484,11 @@ public: /* CloneTable */ -struct CloneTable : public Table<Clone, 16, 4> { +struct CloneTable : public Table<Clone> { virtual void freeEntry(int idx) { - Table<Clone, 16, 4>::freeEntry(idx); + Table<Clone>::freeEntry(idx); - free(table[idx].variables); // Free the dynamically allocated memory part + free(_table[idx].variables); // Free the dynamically allocated memory part } virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); @@ -517,25 +497,25 @@ struct CloneTable : public Table<Clone, 16, 4> { /* NodeTable */ -struct NodeTable : public Table<Node, 32, 16> { +struct NodeTable : public Table<Node> { virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); }; /* ListTable */ -struct ListTable : public Table<List, 8, 4> { +struct ListTable : public Table<List> { virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr); virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note); }; /* HunkTable */ -struct HunkTable : public Table<Hunk, 4, 4> { +struct HunkTable : public Table<Hunk> { virtual void freeEntry(int idx) { - Table<Hunk, 4, 4>::freeEntry(idx); + Table<Hunk>::freeEntry(idx); - free(table[idx].mem); + free(_table[idx].mem); } }; |