diff options
-rw-r--r-- | engines/sci/engine/heapmgr.h | 73 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.cpp | 186 | ||||
-rw-r--r-- | engines/sci/engine/vm.h | 68 |
3 files changed, 247 insertions, 80 deletions
diff --git a/engines/sci/engine/heapmgr.h b/engines/sci/engine/heapmgr.h index f907e75afc..f8975d428d 100644 --- a/engines/sci/engine/heapmgr.h +++ b/engines/sci/engine/heapmgr.h @@ -28,85 +28,14 @@ #ifndef SCI_ENGINE_HEAPMGR_H #define SCI_ENGINE_HEAPMGR_H -#include "sci/tools.h" -#include "sci/sci_memory.h" - namespace Sci { -#define HEAPENTRY_INVALID -1 +enum { HEAPENTRY_INVALID = -1 }; // FIXME: We write (i == 0 || i > 0) instead of (i >= 0) to silence certain annoying warnings: // generated by GCC: "comparison is always true due to limited range of data type". #define ENTRY_IS_VALID(t, i) ((i == 0 || i > 0) && (i) < (t)->max_entry && (t)->table[(i)].next_free == (i)) -#define DECLARE_HEAPENTRY(ENTRY) \ -struct ENTRY##Entry { \ - int next_free; /* Only used for free entries */ \ - ENTRY entry; \ -}; \ - \ -struct ENTRY##Table { \ - 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##Entry *table; \ -}; \ - \ -void init_##ENTRY##_table(ENTRY##Table *table); \ -int alloc_##ENTRY##_entry(ENTRY##Table *table); \ -void free_##ENTRY##_entry(ENTRY##Table *table, int index); - - - -#define DEFINE_HEAPENTRY_WITH_CLEANUP(ENTRY, INITIAL, INCREMENT, CLEANUP_FN) \ -void init_##ENTRY##_table(ENTRY##Table *table) { \ - table->entries_nr = INITIAL; \ - table->max_entry = 0; \ - table->entries_used = 0; \ - table->first_free = HEAPENTRY_INVALID; \ - table->table = (ENTRY##Entry *)sci_malloc(sizeof(ENTRY##Entry) * INITIAL);\ - memset(table->table, 0, sizeof(ENTRY##Entry) * INITIAL); \ -} \ - \ -void free_##ENTRY##_entry(ENTRY##Table *table, int index) { \ - ENTRY##Entry *e = table->table + index; \ - \ - if (index < 0 || index >= table->max_entry) { \ - fprintf(stderr, "heapmgr: Attempt to release" \ - " invalid table index %d!\n", index); \ - BREAKPOINT(); \ - } \ - CLEANUP_FN(&(e->entry)); \ - \ - e->next_free = table->first_free; \ - table->first_free = index; \ - table->entries_used--; \ -} \ - \ -int alloc_##ENTRY##_entry(ENTRY##Table *table) { \ - table->entries_used++; \ - if (table->first_free != HEAPENTRY_INVALID) { \ - int oldff = table->first_free; \ - table->first_free = table->table[oldff].next_free; \ - \ - table->table[oldff].next_free = oldff; \ - return oldff; \ - } else { \ - if (table->max_entry == table->entries_nr) { \ - table->entries_nr += INCREMENT; \ - \ - table->table = (ENTRY##Entry *)sci_realloc(table->table,\ - sizeof(ENTRY##Entry) * table->entries_nr);\ - memset(&table->table[table->entries_nr-INCREMENT], 0, INCREMENT * sizeof(ENTRY##Entry));\ - } \ - table->table[table->max_entry].next_free = table->max_entry; /* Tag as 'valid' */\ - return table->max_entry++; \ - } \ -} - -#define _HEAPENTRY_IGNORE_ME(x) -#define DEFINE_HEAPENTRY(e, i, p) DEFINE_HEAPENTRY_WITH_CLEANUP(e, i, p, _HEAPENTRY_IGNORE_ME) } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 8665cf1d8e..b71e3a8e52 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -1292,10 +1292,188 @@ void _hunk_cleanup(Hunk *hunk) { free(hunk->mem); } -DEFINE_HEAPENTRY(List, 8, 4) -DEFINE_HEAPENTRY(Node, 32, 16) -DEFINE_HEAPENTRY_WITH_CLEANUP(Clone, 16, 4, _clone_cleanup) -DEFINE_HEAPENTRY_WITH_CLEANUP(Hunk, 4, 4, _hunk_cleanup) + +void init_List_table(ListTable *table) { + table->entries_nr = 8; + table->max_entry = 0; + table->entries_used = 0; + table->first_free = HEAPENTRY_INVALID; + table->table = (ListEntry *)sci_malloc(sizeof(ListEntry) * 8);\ + memset(table->table, 0, sizeof(ListEntry) * 8); +} + +void free_List_entry(ListTable *table, int index) { + ListEntry *e = table->table + index; + + if (index < 0 || index >= table->max_entry) { + fprintf(stderr, "heapmgr: Attempt to release" + " invalid table index %d!\n", index); + BREAKPOINT(); + } + + e->next_free = table->first_free; + table->first_free = index; + table->entries_used--; +} + +int alloc_List_entry(ListTable *table) { + table->entries_used++; + if (table->first_free != HEAPENTRY_INVALID) { + int oldff = table->first_free; + table->first_free = table->table[oldff].next_free; + + table->table[oldff].next_free = oldff; + return oldff; + } else { + if (table->max_entry == table->entries_nr) { + table->entries_nr += 4; + + table->table = (ListEntry *)sci_realloc(table->table,\ + sizeof(ListEntry) * table->entries_nr);\ + memset(&table->table[table->entries_nr-4], 0, 4 * sizeof(ListEntry));\ + } + table->table[table->max_entry].next_free = table->max_entry; /* Tag as 'valid' */\ + return table->max_entry++; + } +} + + +void init_Node_table(NodeTable *table) { + table->entries_nr = 32; + table->max_entry = 0; + table->entries_used = 0; + table->first_free = HEAPENTRY_INVALID; + table->table = (NodeEntry *)sci_malloc(sizeof(NodeEntry) * 32);\ + memset(table->table, 0, sizeof(NodeEntry) * 32); +} + +void free_Node_entry(NodeTable *table, int index) { + NodeEntry *e = table->table + index; + + if (index < 0 || index >= table->max_entry) { + fprintf(stderr, "heapmgr: Attempt to release" + " invalid table index %d!\n", index); + BREAKPOINT(); + } + + e->next_free = table->first_free; + table->first_free = index; + table->entries_used--; +} + +int alloc_Node_entry(NodeTable *table) { + table->entries_used++; + if (table->first_free != HEAPENTRY_INVALID) { + int oldff = table->first_free; + table->first_free = table->table[oldff].next_free; + + table->table[oldff].next_free = oldff; + return oldff; + } else { + if (table->max_entry == table->entries_nr) { + table->entries_nr += 16; + + table->table = (NodeEntry *)sci_realloc(table->table,\ + sizeof(NodeEntry) * table->entries_nr);\ + memset(&table->table[table->entries_nr-16], 0, 16 * sizeof(NodeEntry));\ + } + table->table[table->max_entry].next_free = table->max_entry; /* Tag as 'valid' */\ + return table->max_entry++; + } +} + + +void init_Clone_table(CloneTable *table) { + table->entries_nr = 16; + table->max_entry = 0; + table->entries_used = 0; + table->first_free = HEAPENTRY_INVALID; + table->table = (CloneEntry *)sci_malloc(sizeof(CloneEntry) * 16);\ + memset(table->table, 0, sizeof(CloneEntry) * 16); +} + +void free_Clone_entry(CloneTable *table, int index) { + CloneEntry *e = table->table + index; + + if (index < 0 || index >= table->max_entry) { + fprintf(stderr, "heapmgr: Attempt to release" + " invalid table index %d!\n", index); + BREAKPOINT(); + } + _clone_cleanup(&(e->entry)); + + e->next_free = table->first_free; + table->first_free = index; + table->entries_used--; +} + +int alloc_Clone_entry(CloneTable *table) { + table->entries_used++; + if (table->first_free != HEAPENTRY_INVALID) { + int oldff = table->first_free; + table->first_free = table->table[oldff].next_free; + + table->table[oldff].next_free = oldff; + return oldff; + } else { + if (table->max_entry == table->entries_nr) { + table->entries_nr += 4; + + table->table = (CloneEntry *)sci_realloc(table->table,\ + sizeof(CloneEntry) * table->entries_nr);\ + memset(&table->table[table->entries_nr-4], 0, 4 * sizeof(CloneEntry));\ + } + table->table[table->max_entry].next_free = table->max_entry; /* Tag as 'valid' */\ + return table->max_entry++; + } +} + + +void init_Hunk_table(HunkTable *table) { + table->entries_nr = 4; + table->max_entry = 0; + table->entries_used = 0; + table->first_free = HEAPENTRY_INVALID; + table->table = (HunkEntry *)sci_malloc(sizeof(HunkEntry) * 4);\ + memset(table->table, 0, sizeof(HunkEntry) * 4); +} + +void free_Hunk_entry(HunkTable *table, int index) { + HunkEntry *e = table->table + index; + + if (index < 0 || index >= table->max_entry) { + fprintf(stderr, "heapmgr: Attempt to release" + " invalid table index %d!\n", index); + BREAKPOINT(); + } + _hunk_cleanup(&(e->entry)); + + e->next_free = table->first_free; + table->first_free = index; + table->entries_used--; +} + +int alloc_Hunk_entry(HunkTable *table) { + table->entries_used++; + if (table->first_free != HEAPENTRY_INVALID) { + int oldff = table->first_free; + table->first_free = table->table[oldff].next_free; + + table->table[oldff].next_free = oldff; + return oldff; + } else { + if (table->max_entry == table->entries_nr) { + table->entries_nr += 4; + + table->table = (HunkEntry *)sci_realloc(table->table,\ + sizeof(HunkEntry) * table->entries_nr);\ + memset(&table->table[table->entries_nr-4], 0, 4 * sizeof(HunkEntry));\ + } + table->table[table->max_entry].next_free = table->max_entry; /* Tag as 'valid' */\ + return table->max_entry++; + } +} + #define DEFINE_ALLOC(TYPE, SEGTYPE, PLURAL) \ TYPE *SegManager::alloc_##TYPE(reg_t *addr) { \ diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 848188d263..861075c887 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -257,14 +257,74 @@ struct Hunk { const char *type; }; + /* CloneTable */ -DECLARE_HEAPENTRY(Clone) +struct CloneEntry { + int next_free; /* Only used for free entries */ + Clone entry; +}; +struct CloneTable { + 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 */ + CloneEntry *table; +}; +void init_Clone_table(CloneTable *table); +int alloc_Clone_entry(CloneTable *table); +void free_Clone_entry(CloneTable *table, int index); + + /* NodeTable */ -DECLARE_HEAPENTRY(Node) +struct NodeEntry { + int next_free; /* Only used for free entries */ + Node entry; +}; +struct NodeTable { + 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 */ + NodeEntry *table; +}; +void init_Node_table(NodeTable *table); +int alloc_Node_entry(NodeTable *table); +void free_Node_entry(NodeTable *table, int index); + + /* ListTable */ -DECLARE_HEAPENTRY(List) /* list entries */ +struct ListEntry { + int next_free; /* Only used for free entries */ + List entry; +}; +struct ListTable { + 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 */ + ListEntry *table; +}; +void init_List_table(ListTable *table); +int alloc_List_entry(ListTable *table); +void free_List_entry(ListTable *table, int index); + + /* HunkTable */ -DECLARE_HEAPENTRY(Hunk) +struct HunkEntry { + int next_free; /* Only used for free entries */ + Hunk entry; +}; +struct HunkTable { + 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 */ + HunkEntry *table; +}; +void init_Hunk_table(HunkTable *table); +int alloc_Hunk_entry(HunkTable *table); +void free_Hunk_entry(HunkTable *table, int index); + // Free-style memory struct DynMem { |