From 58ee0314aec034f83ed0fa2a70456ff321c81b2f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 3 May 2009 09:20:21 +0000 Subject: [PATCH] SCI: Added SegManager::getScript method and modified code to make use of it; moved VERIFY from seg_manager.h to seg_manager.cpp svn-id: r40268 --- engines/sci/engine/game.cpp | 2 +- engines/sci/engine/seg_manager.cpp | 224 ++++++++++------------------- engines/sci/engine/seg_manager.h | 15 +- engines/sci/engine/vm.cpp | 1 - 4 files changed, 78 insertions(+), 164 deletions(-) diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 0130ee7afe9..c9e8755c5da 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -424,7 +424,7 @@ int script_init_engine(EngineState *s, sci_version_t version) { return 1; } - s->script_000 = &(s->seg_manager->heap[s->script_000_segment]->data.script); + s->script_000 = s->seg_manager->getScript(s->script_000_segment, SEG_ID); s->sys_strings = s->seg_manager->allocateSysStrings(&s->sys_strings_segment); s->string_frag_segment = s->seg_manager->allocateStringFrags(); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 91d9f57cdf1..58dc324d3cb 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -29,6 +29,17 @@ namespace Sci { + +/** + * Verify the the given condition is true, output the message if condition is false, and exit. + * @param cond condition to be verified + * @param msg the message to be printed if condition fails + */ +#define VERIFY( cond, msg ) if (!(cond)) {\ + error("%s, line, %d, %s", __FILE__, __LINE__, msg); \ + } + + #define DEFAULT_SCRIPTS 32 #define DEFAULT_OBJECTS 8 // default # of objects per script #define DEFAULT_OBJECTS_INCREMENT 4 // Number of additional objects to instantiate if we're running out of them @@ -38,11 +49,6 @@ namespace Sci { #undef DEBUG_SEG_MANAGER // Define to turn on debugging -#define GET_SEGID() \ - if (flag == SCRIPT_ID) \ - id = segGet(id); \ - VERIFY(check(id), "invalid seg id"); - #define INVALID_SCRIPT_ID -1 int SegManager::findFreeId(int *id) { @@ -301,29 +307,17 @@ int SegManager::deallocate(int seg, bool recursive) { } int SegManager::scriptMarkedDeleted(int script_nr) { - Script *scr; - int seg = segGet(script_nr); - VERIFY(check(seg), "invalid seg id"); - - scr = &(heap[seg]->data.script); + Script *scr = getScript(script_nr, SCRIPT_ID); return scr->marked_as_deleted; } void SegManager::markScriptDeleted(int script_nr) { - Script *scr; - int seg = segGet(script_nr); - VERIFY(check(seg), "invalid seg id"); - - scr = &(heap[seg]->data.script); + Script *scr = getScript(script_nr, SCRIPT_ID); scr->marked_as_deleted = 1; } void SegManager::unmarkScriptDeleted(int script_nr) { - Script *scr; - int seg = segGet(script_nr); - VERIFY(check(seg), "invalid seg id"); - - scr = &(heap[seg]->data.script); + Script *scr = getScript(script_nr, SCRIPT_ID); scr->marked_as_deleted = 0; } @@ -423,22 +417,10 @@ void SegManager::freeScript(MemObject *mem) { // memory operations -void SegManager::mcpyInOut(int dst, const void *src, size_t n, int id, int flag) { - MemObject *mem_obj; - GET_SEGID(); - mem_obj = heap[id]; - switch (mem_obj->type) { - case MEM_OBJ_SCRIPT: - if (mem_obj->data.script.buf) { - memcpy(mem_obj->data.script.buf + dst, src, n); - } - break; - case MEM_OBJ_CLONES: - sciprintf("memcpy for clones hasn't been implemented yet\n"); - break; - default: - sciprintf("unknown mem obj type\n"); - break; +void SegManager::mcpyInOut(int dst, const void *src, size_t n, int id, idFlag flag) { + Script *scr = getScript(id, flag); + if (scr->buf) { + memcpy(scr->buf + dst, src, n); } } @@ -469,6 +451,21 @@ int SegManager::segGet(int script_id) const { return id_seg_map->lookupKey(script_id); } +Script *SegManager::getScript(const int id, idFlag flag) { + const int seg = (flag == SCRIPT_ID) ? segGet(id) : id; + + if (seg < 0 || seg >= heap_size) { + error("SegManager::getScript(%d,%d): seg id %x out of bounds", id, flag, seg); + } + if (!heap[seg]) { + error("SegManager::getScript(%d,%d): seg id %x is not in memory", id, flag, seg); + } + if (heap[seg]->type != MEM_OBJ_SCRIPT) { + error("SegManager::getScript(%d,%d): seg id %x refers to type %d != MEM_OBJ_SCRIPT", id, flag, seg, heap[seg]->type); + } + return &(heap[seg]->data.script); +} + // validate the seg // return: // false - invalid seg @@ -492,40 +489,29 @@ int SegManager::scriptIsLoaded(int id, idFlag flag) { } void SegManager::incrementLockers(int id, idFlag flag) { - if (flag == SCRIPT_ID) - id = segGet(id); - VERIFY(check(id), "invalid seg id"); - heap[id]->data.script.lockers++; + Script *scr = getScript(id, flag); + scr->lockers++; } void SegManager::decrementLockers(int id, idFlag flag) { - if (flag == SCRIPT_ID) - id = segGet(id); - VERIFY(check(id), "invalid seg id"); - - if (heap[id]->data.script.lockers > 0) - heap[id]->data.script.lockers--; + Script *scr = getScript(id, flag); + if (scr->lockers > 0) + scr->lockers--; } int SegManager::getLockers(int id, idFlag flag) { - if (flag == SCRIPT_ID) - id = segGet(id); - VERIFY(check(id), "invalid seg id"); - - return heap[id]->data.script.lockers; + Script *scr = getScript(id, flag); + return scr->lockers; } void SegManager::setLockers(int lockers, int id, idFlag flag) { - if (flag == SCRIPT_ID) - id = segGet(id); - VERIFY(check(id), "invalid seg id"); - heap[id]->data.script.lockers = lockers; + Script *scr = getScript(id, flag); + scr->lockers = lockers; } void SegManager::setExportTableOffset(int offset, int id, idFlag flag) { - Script *scr = &(heap[id]->data.script); + Script *scr = getScript(id, flag); - GET_SEGID(); if (offset) { scr->export_table = (uint16 *)(scr->buf + offset + 2); scr->exports_nr = READ_LE_UINT16((byte *)(scr->export_table - 1)); @@ -540,23 +526,23 @@ void SegManager::setExportWidth(int flag) { } void SegManager::setSynonymsOffset(int offset, int id, idFlag flag) { - GET_SEGID(); - heap[id]->data.script.synonyms = heap[id]->data.script.buf + offset; + Script *scr = getScript(id, flag); + scr->synonyms = scr->buf + offset; } byte *SegManager::getSynonyms(int id, idFlag flag) { - GET_SEGID(); - return heap[id]->data.script.synonyms; + Script *scr = getScript(id, flag); + return scr->synonyms; } void SegManager::setSynonymsNr(int nr, int id, idFlag flag) { - GET_SEGID(); - heap[id]->data.script.synonyms_nr = nr; + Script *scr = getScript(id, flag); + scr->synonyms_nr = nr; } int SegManager::getSynonymsNr(int id, idFlag flag) { - GET_SEGID(); - return heap[id]->data.script.synonyms_nr; + Script *scr = getScript(id, flag); + return scr->synonyms_nr; } int SegManager::relocateBlock(reg_t *block, int block_location, int block_items, SegmentId segment, int location) { @@ -594,40 +580,27 @@ int SegManager::relocateObject(Object *obj, SegmentId segment, int location) { } void SegManager::scriptAddCodeBlock(reg_t location) { - MemObject *mobj = heap[location.segment]; - Script *scr; - int index; - - VERIFY(!(location.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to add a code block to non-script\n"); - - scr = &(mobj->data.script); + Script *scr = getScript(location.segment, SEG_ID); if (++scr->code_blocks_nr > scr->code_blocks_allocated) { scr->code_blocks_allocated += DEFAULT_OBJECTS_INCREMENT; scr->code = (CodeBlock *)sci_realloc(scr->code, scr->code_blocks_allocated * sizeof(CodeBlock)); } - index = scr->code_blocks_nr - 1; + int index = scr->code_blocks_nr - 1; scr->code[index].pos = location; scr->code[index].size = READ_LE_UINT16(scr->buf + location.offset - 2); } void SegManager::scriptRelocate(reg_t block) { - MemObject *mobj = heap[block.segment]; - Script *scr; - int count; - int i; - - VERIFY(!(block.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt relocate non-script\n"); - - scr = &(mobj->data.script); + Script *scr = getScript(block.segment, SEG_ID); VERIFY(block.offset < (uint16)scr->buf_size && READ_LE_UINT16(scr->buf + block.offset) * 2 + block.offset < (uint16)scr->buf_size, "Relocation block outside of script\n"); - count = READ_LE_UINT16(scr->buf + block.offset); + int count = READ_LE_UINT16(scr->buf + block.offset); - for (i = 0; i <= count; i++) { + for (int i = 0; i <= count; i++) { int pos = READ_LE_UINT16(scr->buf + block.offset + 2 + (i * 2)); if (!pos) continue; // FIXME: A hack pending investigation @@ -665,14 +638,7 @@ void SegManager::scriptRelocate(reg_t block) { } void SegManager::heapRelocate(EngineState *s, reg_t block) { - MemObject *mobj = heap[block.segment]; - Script *scr; - int count; - int i; - - VERIFY(!(block.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt relocate non-script\n"); - - scr = &(mobj->data.script); + Script *scr = getScript(block.segment, SEG_ID); VERIFY(block.offset < (uint16)scr->heap_size && READ_LE_UINT16(scr->heap_start + block.offset) * 2 + block.offset < (uint16)scr->buf_size, "Relocation block outside of script\n"); @@ -680,9 +646,9 @@ void SegManager::heapRelocate(EngineState *s, reg_t block) { if (scr->relocated) return; scr->relocated = 1; - count = READ_LE_UINT16(scr->heap_start + block.offset); + int count = READ_LE_UINT16(scr->heap_start + block.offset); - for (i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { int pos = READ_LE_UINT16(scr->heap_start + block.offset + 2 + (i * 2)) + scr->script_size; if (!relocateLocal(scr, block.segment, pos)) { @@ -714,16 +680,12 @@ void SegManager::heapRelocate(EngineState *s, reg_t block) { reg_t get_class_address(EngineState *s, int classnr, int lock, reg_t caller); Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) { - MemObject *mobj = heap[obj_pos.segment]; - Script *scr; Object *obj; int id; unsigned int base = obj_pos.offset - SCRIPT_OBJECT_MAGIC_OFFSET; reg_t temp; - VERIFY(!(obj_pos.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize object in non-script\n"); - - scr = &(mobj->data.script); + Script *scr = getScript(obj_pos.segment, SEG_ID); VERIFY(base < scr->buf_size, "Attempt to initialize object beyond end of script\n"); @@ -782,15 +744,11 @@ Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) { } Object *SegManager::scriptObjInit11(EngineState *s, reg_t obj_pos) { - MemObject *mobj = heap[obj_pos.segment]; - Script *scr; Object *obj; int id; int base = obj_pos.offset; - VERIFY(!(obj_pos.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize object in non-script\n"); - - scr = &(mobj->data.script); + Script *scr = getScript(obj_pos.segment, SEG_ID); VERIFY(base < (uint16)scr->buf_size, "Attempt to initialize object beyond end of script\n"); @@ -882,12 +840,7 @@ LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) { } void SegManager::scriptInitialiseLocalsZero(SegmentId seg, int count) { - MemObject *mobj = heap[seg]; - Script *scr; - - VERIFY(!(seg >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize locals in non-script\n"); - - scr = &(mobj->data.script); + Script *scr = getScript(seg, SEG_ID); scr->locals_offset = -count * 2; // Make sure it's invalid @@ -895,14 +848,8 @@ void SegManager::scriptInitialiseLocalsZero(SegmentId seg, int count) { } void SegManager::scriptInitialiseLocals(reg_t location) { - MemObject *mobj = heap[location.segment]; + Script *scr = getScript(location.segment, SEG_ID); unsigned int count; - Script *scr; - LocalVariables *locals; - - VERIFY(!(location.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize locals in non-script\n"); - - scr = &(mobj->data.script); VERIFY(location.offset + 1 < (uint16)scr->buf_size, "Locals beyond end of script\n"); @@ -919,7 +866,7 @@ void SegManager::scriptInitialiseLocals(reg_t location) { count = (scr->buf_size - location.offset) >> 1; } - locals = allocLocalsSegment(scr, count); + LocalVariables *locals = allocLocalsSegment(scr, count); if (locals) { uint i; byte *base = (byte *)(scr->buf + location.offset); @@ -930,19 +877,12 @@ void SegManager::scriptInitialiseLocals(reg_t location) { } void SegManager::scriptRelocateExportsSci11(int seg) { - MemObject *mobj = heap[seg]; - Script *scr; - int i; - int location; - - VERIFY(!(seg >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to relocate exports in non-script\n"); - - scr = &(mobj->data.script); - for (i = 0; i < scr->exports_nr; i++) { + Script *scr = getScript(seg, SEG_ID); + for (int i = 0; i < scr->exports_nr; i++) { /* We are forced to use an ugly heuristic here to distinguish function exports from object/class exports. The former kind points into the script resource, the latter into the heap resource. */ - location = READ_LE_UINT16((byte *)(scr->export_table + i)); + int location = READ_LE_UINT16((byte *)(scr->export_table + i)); if (READ_LE_UINT16(scr->heap_start + location) == SCRIPT_OBJECT_MAGIC_NUMBER) { WRITE_LE_UINT16((byte *)(scr->export_table + i), location + scr->heap_start - scr->buf); } else { @@ -953,14 +893,8 @@ void SegManager::scriptRelocateExportsSci11(int seg) { } void SegManager::scriptInitialiseObjectsSci11(EngineState *s, int seg) { - MemObject *mobj = heap[seg]; - Script *scr; - byte *seeker; - - VERIFY(!(seg >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to relocate exports in non-script\n"); - - scr = &(mobj->data.script); - seeker = scr->heap_start + 4 + READ_LE_UINT16(scr->heap_start + 2) * 2; + Script *scr = getScript(seg, SEG_ID); + byte *seeker = scr->heap_start + 4 + READ_LE_UINT16(scr->heap_start + 2) * 2; while (READ_LE_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { if (READ_LE_UINT16(seeker + 14) & SCRIPT_INFO_CLASS) { @@ -1007,12 +941,7 @@ void SegManager::scriptInitialiseObjectsSci11(EngineState *s, int seg) { } void SegManager::scriptFreeUnusedObjects(SegmentId seg) { - MemObject *mobj = heap[seg]; - Script *scr; - - VERIFY(!(seg >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to free unused objects in non-script\n"); - - scr = &(mobj->data.script); + Script *scr = getScript(seg, SEG_ID); if (scr->objects_allocated > scr->objects_nr) { if (scr->objects_nr) scr->objects = (Object *)sci_realloc(scr->objects, sizeof(Object) * scr->objects_nr); @@ -1066,21 +995,16 @@ SegmentId SegManager::allocateStringFrags() { } uint16 SegManager::validateExportFunc(int pubfunct, int seg) { - Script* script; - uint16 offset; - VERIFY(check(seg), "invalid seg id"); - VERIFY(heap[seg]->type == MEM_OBJ_SCRIPT, "Can only validate exports on scripts"); - - script = &heap[seg]->data.script; - if (script->exports_nr <= pubfunct) { + Script *scr = getScript(seg, SEG_ID); + if (scr->exports_nr <= pubfunct) { sciprintf("pubfunct is invalid"); return 0; } if (exports_wide) pubfunct *= 2; - offset = READ_LE_UINT16((byte *)(script->export_table + pubfunct)); - VERIFY(offset < script->buf_size, "invalid export function pointer"); + uint16 offset = READ_LE_UINT16((byte *)(scr->export_table + pubfunct)); + VERIFY(offset < scr->buf_size, "invalid export function pointer"); return offset; } diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 9ea7e6afdf0..dc541e75bab 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -36,17 +36,6 @@ enum idFlag { SEG_ID }; -// Verify the the given condition is true, output the message if condition is false, and exit -// Parameters: -// cond - condition to be verified -// msg - the message to be printed if condition fails -// return: -// none, terminate the program if fails -#define VERIFY( cond, msg ) if (!(cond)) {\ - sciprintf("%s, line, %d, %s\n", __FILE__, __LINE__, msg); \ - BREAKPOINT(); \ - } - #define GET_SEGMENT(mgr, index, rtype) ((index) > 0 && (mgr).heap_size > index) ? \ (((mgr).heap[index] && (mgr).heap[index]->type == rtype)? (mgr).heap[index] : NULL) : NULL @@ -105,6 +94,8 @@ public: // Returns : (int) The associated segment ID, or -1 if no matching segment exists int segGet(int script_nr) const; + Script *getScript(int id, idFlag flag); + // script lock operations @@ -278,7 +269,7 @@ public: // by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, // but less convenient. // A dynamic failure is issued if the specified ID does not reference a proper script. - void mcpyInOut(int dst, const void *src, size_t n, int id, int flag); + void mcpyInOut(int dst, const void *src, size_t n, int id, idFlag flag); // 4. Stack diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 8a49efb906e..92da5c297b9 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -263,7 +263,6 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP seg = s->seg_manager->segGet(script); temp = s->seg_manager->validateExportFunc(pubfunct, seg); - VERIFY(temp, "Invalid pubfunct in export table"); if (!temp) { sciprintf("Request for invalid exported function 0x%x of script 0x%x\n", pubfunct, script); script_error_flag = script_debug_flag = 1;