diff options
Diffstat (limited to 'engines/sci/engine')
-rw-r--r-- | engines/sci/engine/kernel.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 12 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 6 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.cpp | 203 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.h | 4 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 12 | ||||
-rw-r--r-- | engines/sci/engine/vm.h | 134 |
7 files changed, 226 insertions, 147 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 4da9b62348..a08b31effe 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -722,7 +722,7 @@ int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) { return KSIG_NODE | KSIG_INVALID; case MEM_OBJ_DYNMEM: - if (allow_invalid || reg.offset < (*(DynMem *)mobj).size) + if (allow_invalid || reg.offset < (*(DynMem *)mobj)._size) return KSIG_REF; else return KSIG_REF | KSIG_INVALID; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 800774f01c..9c276aa0cc 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -394,13 +394,13 @@ static void sync_SystemStrings(Common::Serializer &s, SystemStrings &obj) { } static void sync_DynMem(Common::Serializer &s, DynMem &obj) { - s.syncAsSint32LE(obj.size); - syncCStr(s, &obj.description); - if (!obj.buf && obj.size) { - obj.buf = (byte *)sci_calloc(obj.size, 1); + s.syncAsSint32LE(obj._size); + syncCStr(s, &obj._description); + if (!obj._buf && obj._size) { + obj._buf = (byte *)sci_calloc(obj._size, 1); } - if (obj.size) - s.syncBytes(obj.buf, obj.size); + if (obj._size) + s.syncBytes(obj._buf, obj._size); } #pragma mark - diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 82d6461ebe..738b74367c 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -325,7 +325,7 @@ int c_segtable(EngineState *s) { break; case MEM_OBJ_DYNMEM: - sciprintf("M dynmem: %d bytes", (*(DynMem *)mobj).size); + sciprintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size); break; case MEM_OBJ_STRING_FRAG: @@ -483,9 +483,9 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) { case MEM_OBJ_DYNMEM: { sciprintf("dynmem (%s): %d bytes\n", - (*(DynMem *)mobj).description ? (*(DynMem *)mobj).description : "no description", (*(DynMem *)mobj).size); + (*(DynMem *)mobj)._description ? (*(DynMem *)mobj)._description : "no description", (*(DynMem *)mobj)._size); - sci_hexdump((*(DynMem *)mobj).buf, (*(DynMem *)mobj).size, 0); + sci_hexdump((*(DynMem *)mobj)._buf, (*(DynMem *)mobj)._size, 0); } break; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 773969514b..eccd1f793f 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -114,7 +114,7 @@ SegManager::~SegManager() { // Returns : 0 - allocation failure // 1 - allocated successfully // seg_id - allocated segment id -MemObject *SegManager::allocateScript(EngineState *s, int script_nr, int* seg_id) { +Script *SegManager::allocateScript(EngineState *s, int script_nr, int* seg_id) { int seg; bool was_added; MemObject* mem; @@ -122,7 +122,7 @@ MemObject *SegManager::allocateScript(EngineState *s, int script_nr, int* seg_id seg = id_seg_map->checkKey(script_nr, true, &was_added); if (!was_added) { *seg_id = seg; - return _heap[*seg_id]; + return (Script *)_heap[*seg_id]; } // allocate the MemObject @@ -133,7 +133,7 @@ MemObject *SegManager::allocateScript(EngineState *s, int script_nr, int* seg_id } *seg_id = seg; - return mem; + return (Script *)mem; } void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) { @@ -176,11 +176,11 @@ int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) { // allocate the script.buf setScriptSize(scr, s, script_nr); - scr.buf = (byte*)sci_malloc(scr.buf_size); + scr.buf = (byte *)sci_malloc(scr.buf_size); dbgPrint("scr.buf ", scr.buf); if (!scr.buf) { - freeScript(scr); + scr.freeScript(); sciprintf("SegManager: Not enough memory space for script size"); scr.buf_size = 0; return 0; @@ -215,68 +215,35 @@ int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) { int SegManager::deallocate(int seg, bool recursive) { MemObject *mobj; VERIFY(check(seg), "invalid seg id"); - int i; mobj = _heap[seg]; id_seg_map->removeKey(mobj->getSegMgrId()); switch (mobj->getType()) { case MEM_OBJ_SCRIPT: - freeScript((*(Script *)mobj)); - - (*(Script *)mobj).buf = NULL; + // FIXME: Get rid of the recursive flag, so that we can move the + // following into the destructor. The only time it is set to false + // is in the SegManager destructor. if (recursive && (*(Script *)mobj).locals_segment) deallocate((*(Script *)mobj).locals_segment, recursive); break; case MEM_OBJ_LOCALS: - free((*(LocalVariables *)mobj).locals); - (*(LocalVariables *)mobj).locals = NULL; break; case MEM_OBJ_DYNMEM: - free((*(DynMem *)mobj).description); - (*(DynMem *)mobj).description = NULL; - free((*(DynMem *)mobj).buf); - (*(DynMem *)mobj).buf = NULL; break; case MEM_OBJ_SYS_STRINGS: - for (i = 0; i < SYS_STRINGS_MAX; i++) { - SystemString *str = &(*(SystemStrings *)mobj).strings[i]; - if (str->name) { - free(str->name); - str->name = NULL; - - free(str->value); - str->value = NULL; - - str->max_size = 0; - } - } break; case MEM_OBJ_STACK: - free((*(dstack_t *)mobj).entries); - (*(dstack_t *)mobj).entries = NULL; break; case MEM_OBJ_LISTS: - free((*(ListTable *)mobj).table); - (*(ListTable *)mobj).table = NULL; - (*(ListTable *)mobj).entries_nr = (*(ListTable *)mobj).max_entry = 0; break; case MEM_OBJ_NODES: - free((*(NodeTable *)mobj).table); - (*(NodeTable *)mobj).table = NULL; - (*(NodeTable *)mobj).entries_nr = (*(NodeTable *)mobj).max_entry = 0; break; case MEM_OBJ_CLONES: - free((*(CloneTable *)mobj).table); - (*(CloneTable *)mobj).table = NULL; - (*(CloneTable *)mobj).entries_nr = (*(CloneTable *)mobj).max_entry = 0; break; case MEM_OBJ_HUNK: - free((*(HunkTable *)mobj).table); - (*(HunkTable *)mobj).table = NULL; - (*(HunkTable *)mobj).entries_nr = (*(HunkTable *)mobj).max_entry = 0; break; case MEM_OBJ_STRING_FRAG: break; @@ -393,30 +360,28 @@ MemObject *SegManager::memObjAllocate(SegmentId segid, int hash_id, MemObjectTyp return mem; } -void SegManager::freeScript(Script &scr) { - if (scr.buf) { - free(scr.buf); - scr.buf = NULL; - scr.buf_size = 0; +void Script::freeScript() { + if (buf) { + free(buf); + buf = NULL; + buf_size = 0; } - if (scr.objects) { - int i; - - for (i = 0; i < scr.objects_nr; i++) { - Object* object = &scr.objects[i]; + if (objects) { + for (int i = 0; i < objects_nr; i++) { + Object *object = &objects[i]; if (object->variables) { free(object->variables); object->variables = NULL; object->variables_nr = 0; } } - free(scr.objects); - scr.objects = NULL; - scr.objects_nr = 0; + free(objects); + objects = NULL; + objects_nr = 0; } - delete scr.obj_indices; - free(scr.code); + delete obj_indices; + free(code); } // memory operations @@ -979,12 +944,7 @@ dstack_t *SegManager::allocateStack(int size, SegmentId *segid) { } SystemStrings *SegManager::allocateSysStrings(SegmentId *segid) { - MemObject *mobj = allocNonscriptSegment(MEM_OBJ_SYS_STRINGS, segid); - SystemStrings *retval = (SystemStrings *)mobj; - - memset(retval->strings, 0, sizeof(retval->strings)); - - return retval; + return (SystemStrings *)allocNonscriptSegment(MEM_OBJ_SYS_STRINGS, segid); } SegmentId SegManager::allocateStringFrags() { @@ -1088,7 +1048,6 @@ Clone *SegManager::alloc_Clone(reg_t *addr) { if (!Clones_seg_id) { mobj = allocNonscriptSegment(MEM_OBJ_CLONES, &(Clones_seg_id)); - (*(CloneTable *)mobj).initTable(); } else mobj = _heap[Clones_seg_id]; @@ -1106,7 +1065,6 @@ List *SegManager::alloc_List(reg_t *addr) { if (!Lists_seg_id) { mobj = allocNonscriptSegment(MEM_OBJ_LISTS, &(Lists_seg_id)); - (*(ListTable *)mobj).initTable(); } else mobj = _heap[Lists_seg_id]; @@ -1124,7 +1082,6 @@ Node *SegManager::alloc_Node(reg_t *addr) { if (!Nodes_seg_id) { mobj = allocNonscriptSegment(MEM_OBJ_NODES, &(Nodes_seg_id)); - (*(NodeTable *)mobj).initTable(); } else mobj = _heap[Nodes_seg_id]; @@ -1142,7 +1099,6 @@ Hunk *SegManager::alloc_Hunk(reg_t *addr) { if (!Hunks_seg_id) { mobj = allocNonscriptSegment(MEM_OBJ_HUNK, &(Hunks_seg_id)); - (*(HunkTable *)mobj).initTable(); } else mobj = _heap[Hunks_seg_id]; @@ -1153,70 +1109,71 @@ Hunk *SegManager::alloc_Hunk(reg_t *addr) { return &(table->table[offset]); } - - -byte *SegManager::dereference(reg_t pointer, int *size) { - MemObject *mobj; - byte *base = NULL; - int count; - - if (!pointer.segment || (pointer.segment >= _heap.size()) || !_heap[pointer.segment]) { - sciprintf("Error: Attempt to dereference invalid pointer "PREG"!\n", +byte *MemObject::dereference(reg_t pointer, int *size) { + error("Error: Trying to dereference pointer "PREG" to inappropriate segment", PRINT_REG(pointer)); - return NULL; /* Invalid */ + return NULL; +} + +byte *Script::dereference(reg_t pointer, int *size) { + if (pointer.offset > buf_size) { + sciprintf("Error: Attempt to dereference invalid pointer "PREG" into script segment (script size=%d)\n", + PRINT_REG(pointer), (uint)buf_size); + return NULL; } + if (size) + *size = buf_size - pointer.offset; + return (byte *)(buf + pointer.offset); +} - mobj = _heap[pointer.segment]; +byte *LocalVariables::dereference(reg_t pointer, int *size) { + int count = nr * sizeof(reg_t); + byte *base = (byte *)locals; - switch (mobj->getType()) { - case MEM_OBJ_SCRIPT: - if (pointer.offset > (*(Script *)mobj).buf_size) { - sciprintf("Error: Attempt to dereference invalid pointer "PREG" into script segment (script size=%d)\n", - PRINT_REG(pointer), (uint)(*(Script *)mobj).buf_size); - return NULL; - } - if (size) - *size = (*(Script *)mobj).buf_size - pointer.offset; - return (byte *)((*(Script *)mobj).buf + pointer.offset); - break; + if (size) + *size = count; - case MEM_OBJ_LOCALS: - count = (*(LocalVariables *)mobj).nr * sizeof(reg_t); - base = (byte *)(*(LocalVariables *)mobj).locals; - break; + return base + pointer.offset; +} - case MEM_OBJ_STACK: - count = (*(dstack_t *)mobj).nr * sizeof(reg_t); - base = (byte *)(*(dstack_t *)mobj).entries; - break; +byte *dstack_t::dereference(reg_t pointer, int *size) { + int count = nr * sizeof(reg_t); + byte *base = (byte *)entries; - case MEM_OBJ_DYNMEM: - count = (*(DynMem *)mobj).size; - base = (byte *)(*(DynMem *)mobj).buf; - break; + if (size) + *size = count; - case MEM_OBJ_SYS_STRINGS: - if (size) - *size = (*(SystemStrings *)mobj).strings[pointer.offset].max_size; - if (pointer.offset < SYS_STRINGS_MAX && (*(SystemStrings *)mobj).strings[pointer.offset].name) - return (byte *)((*(SystemStrings *)mobj).strings[pointer.offset].value); - else { - sciprintf("Error: Attempt to dereference invalid pointer "PREG"!\n", - PRINT_REG(pointer)); - return NULL; - } + return base + pointer.offset; +} - default: - error("Error: Trying to dereference pointer "PREG" to inappropriate segment", - PRINT_REG(pointer)); - return NULL; - } +byte *DynMem::dereference(reg_t pointer, int *size) { + int count = _size; + byte *base = (byte *)_buf; if (size) *size = count; - return - base + pointer.offset; + return base + pointer.offset; +} + +byte *SystemStrings::dereference(reg_t pointer, int *size) { + if (size) + *size = strings[pointer.offset].max_size; + if (pointer.offset < SYS_STRINGS_MAX && strings[pointer.offset].name) + return (byte *)(strings[pointer.offset].value); + + error("Attempt to dereference invalid pointer "PREG"", PRINT_REG(pointer)); + return NULL; +} + +byte *SegManager::dereference(reg_t pointer, int *size) { + if (!pointer.segment || (pointer.segment >= _heap.size()) || !_heap[pointer.segment]) { + error("Attempt to dereference invalid pointer "PREG"", PRINT_REG(pointer)); + return NULL; /* Invalid */ + } + + MemObject *mobj = _heap[pointer.segment]; + return mobj->dereference(pointer, size); } unsigned char *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) { @@ -1226,16 +1183,16 @@ unsigned char *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) DynMem &d = *(DynMem *)mobj; - d.size = size; + d._size = size; if (size == 0) - d.buf = NULL; + d._buf = NULL; else - d.buf = (byte *)sci_malloc(size); + d._buf = (byte *)sci_malloc(size); - d.description = sci_strdup(descr); + d._description = sci_strdup(descr); - return (unsigned char *)(d.buf); + return (unsigned char *)(d._buf); } const char *SegManager::getDescription(reg_t addr) { @@ -1246,7 +1203,7 @@ const char *SegManager::getDescription(reg_t addr) { switch (mobj->getType()) { case MEM_OBJ_DYNMEM: - return (*(DynMem *)mobj).description; + return (*(DynMem *)mobj)._description; default: return ""; } diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 6a2cc14e65..c76d056383 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -62,15 +62,13 @@ public: // 1. Scripts - void freeScript(Script &scr); - // Allocate a script into the segment manager // Parameters: (int) script_nr: number of the script to load // (state_t *) s: The state containing resource manager handlers to load the // script data // Returns : (int) 0 on failure, 1 on success // (int) *seg_id: The segment ID of the newly allocated segment, on success - MemObject *allocateScript(EngineState *s, int script_nr, int* seg_id); + Script *allocateScript(EngineState *s, int script_nr, int* seg_id); // The script must then be initialised; see section (1b.), below. diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 079be6975f..7f997d62d3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1667,7 +1667,6 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script, int seg; int seg_id; int marked_for_deletion; - MemObject *mem; reg_t reg; *was_new = 1; @@ -1693,6 +1692,7 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script, return 0; } + Script *scr = 0; seg = s->seg_manager->segGet(script_nr); if (s->seg_manager->scriptIsLoaded(script_nr, SCRIPT_ID)) { marked_for_deletion = s->seg_manager->scriptMarkedDeleted(script_nr); @@ -1701,17 +1701,17 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script, return seg; } else { seg_id = seg; - mem = s->seg_manager->_heap[seg]; - assert(mem); - s->seg_manager->freeScript(*(Script *)mem); + scr = (Script *)s->seg_manager->_heap[seg]; + assert(scr); + scr->freeScript(); } - } else if (!(mem = s->seg_manager->allocateScript(s, script_nr, &seg_id))) { // ALL YOUR SCRIPT BASE ARE BELONG TO US + } else if (!(scr = s->seg_manager->allocateScript(s, script_nr, &seg_id))) { // ALL YOUR SCRIPT BASE ARE BELONG TO US sciprintf("Not enough heap space for script size 0x%x of script 0x%x, should this happen?`\n", (*script)->size, script_nr); script_debug_flag = script_error_flag = 1; return 0; } - s->seg_manager->initialiseScript(*(Script *)mem, s, script_nr); + s->seg_manager->initialiseScript(*scr, s, script_nr); reg.segment = seg_id; reg.offset = 0; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index f036ccb496..5576d98871 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -28,6 +28,7 @@ /* VM and kernel declarations */ +//#include "common/serializer.h" #include "sci/scicore/versions.h" // for sci_version_t #include "sci/engine/vm_types.h" // for reg_t #include "sci/engine/heapmgr.h" @@ -50,10 +51,15 @@ enum MemObjectType { MEM_OBJ_MAX // For sanity checking }; -struct MemObject { +struct MemObject /* : public Common::Serializable */ { MemObjectType _type; int _segmgrId; /**< Internal value used by the seg_manager's hash map */ +public: + virtual ~MemObject() {} + + virtual byte *dereference(reg_t pointer, int *size); + inline MemObjectType getType() const { return _type; } inline int getSegMgrId() const { return _segmgrId; } @@ -80,6 +86,29 @@ struct SystemString { struct SystemStrings : public MemObject { SystemString strings[SYS_STRINGS_MAX]; + +public: + SystemStrings() { + memset(strings, 0, sizeof(strings)); + } + ~SystemStrings() { + for (int i = 0; i < SYS_STRINGS_MAX; i++) { + SystemString *str = &strings[i]; + if (str->name) { + free(str->name); + str->name = NULL; + + free(str->value); + str->value = NULL; + + str->max_size = 0; + } + } + } + + virtual byte *dereference(reg_t pointer, int *size); + +// virtual void saveLoadWithSerializer(Common::Serializer &ser); }; /** Number of bytes to be allocated for the stack */ @@ -180,6 +209,21 @@ struct LocalVariables : public MemObject { int script_id; /**< Script ID this local variable block belongs to */ reg_t *locals; int nr; + +public: + LocalVariables() { + script_id = 0; + locals = 0; + nr = 0; + } + ~LocalVariables() { + free(locals); + locals = NULL; + } + + virtual byte *dereference(reg_t pointer, int *size); + +// virtual void saveLoadWithSerializer(Common::Serializer &ser); }; /** Clone has been marked as 'freed' */ @@ -227,7 +271,7 @@ struct CodeBlock { struct Script : public MemObject { int nr; /**< Script number */ - byte* buf; /**< Static data buffer, or NULL if not used */ + byte *buf; /**< Static data buffer, or NULL if not used */ size_t buf_size; size_t script_size; size_t heap_size; @@ -257,12 +301,65 @@ struct Script : public MemObject { int code_blocks_allocated; int relocated; int marked_as_deleted; + +public: + Script() { + nr = 0; + buf = NULL; + buf_size = 0; + script_size = 0; + heap_size = 0; + + synonyms = NULL; + heap_start = NULL; + export_table = NULL; + + obj_indices = NULL; + + objects = NULL; + objects_allocated = 0; + objects_nr = 0; + + locals_offset = 0; + locals_segment = 0; + locals_block = NULL; + + code = NULL; + code_blocks_nr = 0; + code_blocks_allocated = 0; + relocated = 0; + marked_as_deleted = 0; + } + + ~Script() { + freeScript(); + } + + virtual byte *dereference(reg_t pointer, int *size); + +// virtual void saveLoadWithSerializer(Common::Serializer &ser); + + void freeScript(); }; /** Data stack */ struct dstack_t : MemObject { int nr; /**< Number of stack entries */ reg_t *entries; + +public: + dstack_t() { + nr = 0; + entries = NULL; + } + ~dstack_t() { + free(entries); + entries = NULL; + } + + virtual byte *dereference(reg_t pointer, int *size); + +// virtual void saveLoadWithSerializer(Common::Serializer &ser); }; #define CLONE_USED -1 @@ -301,6 +398,20 @@ struct Table : public MemObject { Entry *table; +public: + Table() { + initTable(); + } + ~Table() { + // FIXME: Shouldn't we make sure that all table entries are disposed + // of properly? + free(table); + table = NULL; + entries_nr = max_entry = 0; + } + +// virtual void saveLoadWithSerializer(Common::Serializer &ser); + void initTable() { entries_nr = INITIAL; max_entry = 0; @@ -352,9 +463,22 @@ void free_Hunk_entry(HunkTable *table, int index); // Free-style memory struct DynMem : public MemObject { - int size; - char *description; - byte *buf; + int _size; + char *_description; + byte *_buf; + +public: + DynMem() : _size(0), _description(0), _buf(0) {} + ~DynMem() { + free(_description); + _description = NULL; + free(_buf); + _buf = NULL; + } + + virtual byte *dereference(reg_t pointer, int *size); + +// virtual void saveLoadWithSerializer(Common::Serializer &ser); }; /** Contains selector IDs for a few selected selectors */ |