aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorMax Horn2009-05-11 13:32:00 +0000
committerMax Horn2009-05-11 13:32:00 +0000
commit1949133d22a3435c7a3ae4532d59967d27cf7708 (patch)
treebb06e84dda4275406d46a6708a811f060780e53c /engines/sci/engine
parentd66d1ffab302c6146d0262c873287347c9f69267 (diff)
downloadscummvm-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.cpp2
-rw-r--r--engines/sci/engine/klists.cpp4
-rw-r--r--engines/sci/engine/savegame.cpp123
-rw-r--r--engines/sci/engine/scriptconsole.cpp26
-rw-r--r--engines/sci/engine/scriptdebug.cpp27
-rw-r--r--engines/sci/engine/seg_manager.cpp25
-rw-r--r--engines/sci/engine/seg_manager.h1
-rw-r--r--engines/sci/engine/state.h10
-rw-r--r--engines/sci/engine/vm.cpp19
-rw-r--r--engines/sci/engine/vm.h58
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);
}
};