diff options
author | Jordi Vilalta Prat | 2009-02-21 23:27:24 +0000 |
---|---|---|
committer | Jordi Vilalta Prat | 2009-02-21 23:27:24 +0000 |
commit | 817fde6cdddc700650e16018e9d6184ae29d1ecf (patch) | |
tree | 64379a245f082d7384bd45c015c8795a257d530c /engines/sci | |
parent | b5b4cb66a173bfea3792058e160f6b9a0b30e2ff (diff) | |
download | scummvm-rg350-817fde6cdddc700650e16018e9d6184ae29d1ecf.tar.gz scummvm-rg350-817fde6cdddc700650e16018e9d6184ae29d1ecf.tar.bz2 scummvm-rg350-817fde6cdddc700650e16018e9d6184ae29d1ecf.zip |
SCI: Convert the segment manager into a class
svn-id: r38767
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/engine/game.cpp | 14 | ||||
-rw-r--r-- | engines/sci/engine/gc.cpp | 16 | ||||
-rw-r--r-- | engines/sci/engine/kernel.cpp | 22 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 6 | ||||
-rw-r--r-- | engines/sci/engine/klists.cpp | 16 | ||||
-rw-r--r-- | engines/sci/engine/kmovement.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/kpathing.cpp | 8 | ||||
-rw-r--r-- | engines/sci/engine/kscripts.cpp | 18 | ||||
-rw-r--r-- | engines/sci/engine/kstring.cpp | 10 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cfsml | 47 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 87 | ||||
-rw-r--r-- | engines/sci/engine/scriptconsole.cpp | 6 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 38 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.cpp | 658 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.h | 750 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 108 | ||||
-rw-r--r-- | engines/sci/include/engine.h | 2 | ||||
-rw-r--r-- | engines/sci/include/vm.h | 17 |
18 files changed, 921 insertions, 904 deletions
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 4fd9b0208c..6d0dd3b925 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -467,7 +467,7 @@ int script_init_engine(EngineState *s, sci_version_t version) { else result = create_class_table_sci0(s); - sm_init(&s->seg_manager, s->version >= SCI_VERSION(1, 001, 000)); + s->seg_manager = new SegManager(s->version >= SCI_VERSION(1, 001, 000)); s->gc_countdown = GC_INTERVAL - 1; if (result) { @@ -482,9 +482,9 @@ 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->heap[s->script_000_segment]->data.script); - s->sys_strings = sm_allocate_sys_strings(&s->seg_manager, &s->sys_strings_segment); + s->sys_strings = s->seg_manager->allocateSysStrings(&s->sys_strings_segment); // Allocate static buffer for savegame and CWD directories sys_string_acquire(s->sys_strings, SYS_STRING_SAVEDIR, "savedir", MAX_SAVE_DIR_SIZE); @@ -523,9 +523,9 @@ int script_init_engine(EngineState *s, sci_version_t version) { if (s->version >= SCI_VERSION_FTU_LOFS_ABSOLUTE && s->version < SCI_VERSION(1, 001, 000)) - sm_set_export_width(&s->seg_manager, 1); + s->seg_manager->setExportWidth(1); else - sm_set_export_width(&s->seg_manager, 0); + s->seg_manager->setExportWidth(0); sciprintf("Engine initialized\n"); @@ -600,7 +600,7 @@ int game_init(EngineState *s) { reg_t game_obj; // Address of the game object dstack_t *stack; - stack = sm_allocate_stack(&s->seg_manager, VM_STACK_SIZE, &s->stack_segment); + stack = s->seg_manager->allocateStack(VM_STACK_SIZE, &s->stack_segment); s->stack_base = stack->entries; s->stack_top = s->stack_base + VM_STACK_SIZE; @@ -679,7 +679,7 @@ int game_exit(EngineState *s) { // Reinit because some other code depends on having a valid state game_init_sound(s, SFX_STATE_FLAG_NOSOUND); - sm_destroy(&s->seg_manager); + delete s->seg_manager; if (s->synonyms_nr) { free(s->synonyms); diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 0a0097aad5..94632a6b7c 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -100,11 +100,11 @@ static void free_worklist(worklist_t *wl) { } } -static reg_t_hash_map * normalise_hashmap_ptrs(reg_t_hash_map *nonnormal_map, seg_interface_t **interfaces, int interfaces_nr) { +static reg_t_hash_map * normalise_hashmap_ptrs(reg_t_hash_map *nonnormal_map, SegInterface **interfaces, int interfaces_nr) { reg_t_hash_map *normal_map = new reg_t_hash_map(); for (reg_t_hash_map::iterator i = nonnormal_map->begin(); i != nonnormal_map->end(); ++i) { - seg_interface_t *interfce; + SegInterface *interfce; reg_t reg = i->_key; interfce = (reg.segment < interfaces_nr) ? interfaces[reg.segment] : NULL; @@ -129,8 +129,8 @@ void add_outgoing_refs(void *pre_wm, reg_t addr) { } reg_t_hash_map *find_all_used_references(EngineState *s) { - SegManager *sm = &(s->seg_manager); - seg_interface_t **interfaces = (seg_interface_t**)sci_calloc(sizeof(seg_interface_t *), sm->heap_size); + SegManager *sm = s->seg_manager; + SegInterface **interfaces = (SegInterface **)sci_calloc(sizeof(SegInterface *), sm->heap_size); reg_t_hash_map *nonnormal_map = new reg_t_hash_map(); reg_t_hash_map *normal_map = NULL; worklist_t *worklist = new_worklist(); @@ -144,7 +144,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { if (sm->heap[i] == NULL) interfaces[i] = NULL; else - interfaces[i] = get_seg_interface(sm, i); + interfaces[i] = sm->getSegInterface(i); // Initialise // Init: Registers @@ -229,7 +229,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { } struct deallocator_t { - seg_interface_t *interfce; + SegInterface *interfce; #ifdef DEBUG_GC char *segnames[MEM_OBJ_MAX + 1]; int segcount[MEM_OBJ_MAX + 1]; @@ -255,7 +255,7 @@ void free_unless_used(void *pre_use_map, reg_t addr) { void run_gc(EngineState *s) { int seg_nr; deallocator_t deallocator; - SegManager *sm = &(s->seg_manager); + SegManager *sm = s->seg_manager; #ifdef DEBUG_GC c_segtable(s); @@ -267,7 +267,7 @@ void run_gc(EngineState *s) { for (seg_nr = 1; seg_nr < sm->heap_size; seg_nr++) { if (sm->heap[seg_nr] != NULL) { - deallocator.interfce = get_seg_interface(sm, seg_nr); + deallocator.interfce = sm->getSegInterface(seg_nr); #ifdef DEBUG_GC deallocator.segnames[deallocator.interfce->type_id] = deallocator.interfce->type; #endif diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index d01451f2e3..5c5cf51a04 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -370,7 +370,7 @@ int kernel_oops(EngineState *s, const char *file, int line, const char *reason) reg_t kalloc(EngineState *s, const char *type, int space) { reg_t reg; - sm_alloc_hunk_entry(&s->seg_manager, type, space, ®); + s->seg_manager->alloc_hunk_entry(type, space, ®); SCIkdebug(SCIkMEM, "Allocated %d at hunk "PREG" (%s)\n", space, PRINT_REG(reg), type); return reg; @@ -390,7 +390,7 @@ int has_kernel_function(EngineState *s, const char *kname) { // Returns a pointer to the memory indicated by the specified handle byte *kmem(EngineState *s, reg_t handle) { - mem_obj_t *mobj = GET_SEGMENT(s->seg_manager, handle.segment, MEM_OBJ_HUNK); + mem_obj_t *mobj = GET_SEGMENT(*s->seg_manager, handle.segment, MEM_OBJ_HUNK); hunk_table_t *ht = &(mobj->data.hunks); if (!mobj || !ENTRY_IS_VALID(ht, handle.offset)) { @@ -403,7 +403,7 @@ byte *kmem(EngineState *s, reg_t handle) { // Frees the specified handle. Returns 0 on success, 1 otherwise. int kfree(EngineState *s, reg_t handle) { - sm_free_hunk_entry(&s->seg_manager, handle); + s->seg_manager->free_hunk_entry(handle); return 0; } @@ -567,17 +567,17 @@ reg_t kGetTime(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) { switch (UKPV(0)) { case K_MEMORY_ALLOCATE_CRITICAL : - if (!sm_alloc_dynmem(&s->seg_manager, UKPV(1), "kMemory() critical", &s->r_acc)) { + if (!s->seg_manager->allocDynmem(UKPV(1), "kMemory() critical", &s->r_acc)) { SCIkwarn(SCIkERROR, "Critical heap allocation failed\n"); script_error_flag = script_debug_flag = 1; } return s->r_acc; break; case K_MEMORY_ALLOCATE_NONCRITICAL : - sm_alloc_dynmem(&s->seg_manager, UKPV(1), "kMemory() non-critical", &s->r_acc); + s->seg_manager->allocDynmem(UKPV(1), "kMemory() non-critical", &s->r_acc); break; case K_MEMORY_FREE : - if (sm_free_dynmem(&s->seg_manager, argv[1])) { + if (s->seg_manager->freeDynmem(argv[1])) { SCIkwarn(SCIkERROR, "Attempt to kMemory::free() non-dynmem pointer "PREG"!\n", PRINT_REG(argv[1])); } break; @@ -606,7 +606,7 @@ reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) { SCIkdebug(SCIkERROR, "Attempt to poke invalid memory at "PREG"!\n", PRINT_REG(argv[1])); return s->r_acc; } - if (s->seg_manager.heap[argv[1].segment]->type == MEM_OBJ_LOCALS) + if (s->seg_manager->heap[argv[1].segment]->type == MEM_OBJ_LOCALS) return *((reg_t *) ref); else return make_reg(0, getInt16(ref)); @@ -620,7 +620,7 @@ reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } - if (s->seg_manager.heap[argv[1].segment]->type == MEM_OBJ_LOCALS) + if (s->seg_manager->heap[argv[1].segment]->type == MEM_OBJ_LOCALS) *((reg_t *) ref) = argv[2]; else { if (argv[2].segment) { @@ -828,10 +828,10 @@ int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) { return KSIG_ARITHMETIC; } - if ((reg.segment >= s->seg_manager.heap_size) || !s->seg_manager.heap[reg.segment]) + if ((reg.segment >= s->seg_manager->heap_size) || !s->seg_manager->heap[reg.segment]) return 0; // Invalid - mobj = s->seg_manager.heap[reg.segment]; + mobj = s->seg_manager->heap[reg.segment]; switch (mobj->type) { case MEM_OBJ_SCRIPT: @@ -937,7 +937,7 @@ int kernel_matches_signature(EngineState *s, const char *sig, int argc, reg_t *a static inline void *_kernel_dereference_pointer(EngineState *s, reg_t pointer, int entries, int align) { int maxsize; - void *retval = sm_dereference(&s->seg_manager, pointer, &maxsize); + void *retval = s->seg_manager->dereference(pointer, &maxsize); if (pointer.offset & (align - 1)) { SCIkdebug(SCIkERROR, "Unaligned pointer read: "PREG" expected with %d alignment!\n", PRINT_REG(pointer), align); diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index c4cf477e42..ff31b4b2bd 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1308,7 +1308,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse); static void _k_disable_delete_for_now(EngineState *s, reg_t obj) { reg_t text_pos = GET_SEL32(obj, text); - char *text = IS_NULL_REG(text_pos) ? NULL : (char *) sm_dereference(&s->seg_manager, text_pos, NULL); + char *text = IS_NULL_REG(text_pos) ? NULL : (char *)s->seg_manager->dereference(text_pos, NULL); int type = GET_SEL32V(obj, type); int state = GET_SEL32V(obj, state); @@ -1378,7 +1378,7 @@ reg_t kEditControl(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t text_pos = GET_SEL32(obj, text); int display_offset = 0; - char *text = (char *) sm_dereference(&s->seg_manager, text_pos, NULL); + char *text = (char *)s->seg_manager->dereference(text_pos, NULL); int textlen; if (!text) { @@ -1545,7 +1545,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) { int font_nr = GET_SEL32V(obj, font); reg_t text_pos = GET_SEL32(obj, text); - char *text = IS_NULL_REG(text_pos) ? NULL : (char *)sm_dereference(&s->seg_manager, text_pos, NULL); + char *text = IS_NULL_REG(text_pos) ? NULL : (char *)s->seg_manager->dereference(text_pos, NULL); int view = GET_SEL32V(obj, view); int cel = sign_extend_byte(GET_SEL32V(obj, cel)); int loop = sign_extend_byte(GET_SEL32V(obj, loop)); diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index e2cd12d7c7..7693e835a8 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -39,7 +39,7 @@ inline node_t *inline_lookup_node(EngineState *s, reg_t addr, const char *file, if (!addr.offset && !addr.segment) return NULL; // Non-error null - mobj = GET_SEGMENT(s->seg_manager, addr.segment, MEM_OBJ_NODES); + mobj = GET_SEGMENT(*s->seg_manager, addr.segment, MEM_OBJ_NODES); if (!mobj) { sciprintf("%s, L%d: Attempt to use non-node "PREG" as list node\n", __FILE__, __LINE__, PRINT_REG(addr)); script_debug_flag = script_error_flag = 1; @@ -70,7 +70,7 @@ inline list_t *_lookup_list(EngineState *s, reg_t addr, const char *file, int li if (may_be_null && !addr.segment && !addr.offset) return NULL; - mobj = GET_SEGMENT(s->seg_manager, addr.segment, MEM_OBJ_LISTS); + mobj = GET_SEGMENT(*s->seg_manager, addr.segment, MEM_OBJ_LISTS); if (!mobj) { sciprintf("%s, L%d: Attempt to use non-list "PREG" as list\n", __FILE__, __LINE__, PRINT_REG(addr)); @@ -159,7 +159,7 @@ int sane_listp(EngineState *s, reg_t addr) { reg_t kNewList(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t listbase; list_t *l; - l = sm_alloc_list(&s->seg_manager, &listbase); + l = s->seg_manager->alloc_list(&listbase); l->first = l->last = NULL_REG; SCIkdebug(SCIkNODES, "New listbase at "PREG"\n", PRINT_REG(listbase)); @@ -182,19 +182,19 @@ reg_t kDisposeList(EngineState *s, int funct_nr, int argc, reg_t *argv) { while (!IS_NULL_REG(n_addr)) { // Free all nodes node_t *n = LOOKUP_NODE(n_addr); - sm_free_node(&s->seg_manager, n_addr); + s->seg_manager->free_node(n_addr); n_addr = n->succ; } } - sm_free_list(&s->seg_manager, argv[0]); + s->seg_manager->free_list(argv[0]); */ return s->r_acc; } inline reg_t _k_new_node(EngineState *s, reg_t value, reg_t key) { reg_t nodebase; - node_t *n = sm_alloc_node(&s->seg_manager, &nodebase); + node_t *n = s->seg_manager->alloc_node(&nodebase); if (!n) { KERNEL_OOPS("Out of memory while creating a node"); @@ -422,7 +422,7 @@ reg_t kDeleteKey(EngineState *s, int funct_nr, int argc, reg_t *argv) { if (!IS_NULL_REG(n->succ)) LOOKUP_NODE(n->succ)->pred = n->pred; - //sm_free_node(&s->seg_manager, node_pos); + //s->seg_manager->free_node(node_pos); return make_reg(0, 1); // Signal success } @@ -465,7 +465,7 @@ reg_t kSort(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; if (IS_NULL_REG(output_data)) { - list = sm_alloc_list(&s->seg_manager, &output_data); + list = s->seg_manager->alloc_list(&output_data); list->first = list->last = NULL_REG; PUT_SEL32(dest, elements, output_data); } diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index c9a7718f9c..25161890c7 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -270,7 +270,7 @@ static void bresenham_autodetect(EngineState *s) { return; } - buf = s->seg_manager.heap[fptr.segment]->data.script.buf + fptr.offset; + buf = s->seg_manager->heap[fptr.segment]->data.script.buf + fptr.offset; handle_movecnt = (SCI_VERSION_MAJOR(s->version) == 0 || checksum_bytes(buf, 8) == 0x216) ? INCREMENT_MOVECNT : IGNORE_MOVECNT; sciprintf("b-moveCnt action based on checksum: %s\n", handle_movecnt == IGNORE_MOVECNT ? "ignore" : "increment"); } else { diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index b84ea704f0..204dae4258 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -1381,7 +1381,7 @@ static reg_t output_path(pf_state_t *p, EngineState *s) { if (unreachable) { // If pathfinding failed we only return the path up to vertex_start - oref = sm_alloc_dynmem(&s->seg_manager, POLY_POINT_SIZE * 3, AVOIDPATH_DYNMEM_STRING, &output); + oref = s->seg_manager->allocDynmem(POLY_POINT_SIZE * 3, AVOIDPATH_DYNMEM_STRING, &output); if (p->keep_start) POLY_SET_POINT(oref, 0, p->start.x, p->start.y); @@ -1400,7 +1400,7 @@ static reg_t output_path(pf_state_t *p, EngineState *s) { vertex = vertex->path_prev; } - oref = sm_alloc_dynmem(&s->seg_manager, POLY_POINT_SIZE * (path_len + 1 + p->keep_start + p->keep_end), AVOIDPATH_DYNMEM_STRING, &output); + oref = s->seg_manager->allocDynmem(POLY_POINT_SIZE * (path_len + 1 + p->keep_start + p->keep_end), AVOIDPATH_DYNMEM_STRING, &output); // Sentinel POLY_SET_POINT(oref, path_len + p->keep_start + p->keep_end, POLY_LAST_POINT, POLY_LAST_POINT); @@ -1504,8 +1504,8 @@ reg_t kAvoidPath(EngineState *s, int funct_nr, int argc, reg_t *argv) { sciprintf("[avoidpath] Error: pathfinding failed for following input:\n"); print_input(s, poly_list, start, end, opt); sciprintf("[avoidpath] Returning direct path from start point to end point\n"); - oref = sm_alloc_dynmem(&s->seg_manager, POLY_POINT_SIZE * 3, - AVOIDPATH_DYNMEM_STRING, &output); + oref = s->seg_manager->allocDynmem(POLY_POINT_SIZE * 3, + AVOIDPATH_DYNMEM_STRING, &output); POLY_SET_POINT(oref, 0, start.x, start.y); POLY_SET_POINT(oref, 1, end.x, end.y); diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index df36d41708..d3fb235120 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -166,7 +166,7 @@ reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) { SCIkdebug(SCIkMEM, "Attempting to clone from "PREG"\n", PRINT_REG(parent_addr)); - clone_obj = sm_alloc_clone(&s->seg_manager, &clone_addr); + clone_obj = s->seg_manager->alloc_clone(&clone_addr); if (!clone_obj) { SCIkwarn(SCIkERROR, "Cloning "PREG" failed-- internal error!\n", PRINT_REG(parent_addr)); @@ -184,8 +184,8 @@ reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) { clone_obj->variables[SCRIPT_SPECIES_SELECTOR] = clone_obj->pos; if (IS_CLASS(parent_obj)) clone_obj->variables[SCRIPT_SUPERCLASS_SELECTOR] = parent_obj->pos; - sm_increment_lockers(&s->seg_manager, parent_obj->pos.segment, SEG_ID); - sm_increment_lockers(&s->seg_manager, clone_obj->pos.segment, SEG_ID); + s->seg_manager->incrementLockers(parent_obj->pos.segment, SEG_ID); + s->seg_manager->incrementLockers(clone_obj->pos.segment, SEG_ID); return clone_addr; } @@ -243,7 +243,7 @@ reg_t kScriptID(EngineState *s, int funct_nr, int argc, reg_t *argv) { if (!scriptid) return NULL_REG; - scr = &(s->seg_manager.heap[scriptid]->data.script); + scr = &(s->seg_manager->heap[scriptid]->data.script); if (!scr->exports_nr) { SCIkdebug(SCIkERROR, "Script 0x%x does not have a dispatch table\n", script); @@ -255,7 +255,7 @@ reg_t kScriptID(EngineState *s, int funct_nr, int argc, reg_t *argv) { return NULL_REG; } - return make_reg(scriptid, sm_validate_export_func(&s->seg_manager, index, scriptid)); + return make_reg(scriptid, s->seg_manager->validateExportFunc(index, scriptid)); } reg_t kDisposeScript(EngineState *s, int funct_nr, int argc, reg_t *argv) { @@ -265,11 +265,11 @@ reg_t kDisposeScript(EngineState *s, int funct_nr, int argc, reg_t *argv) { if (argv[0].segment) return s->r_acc; - if (sm_script_is_loaded(&(s->seg_manager), script, SCRIPT_ID)) { - int id = sm_seg_get(&(s->seg_manager), script); + if (s->seg_manager->scriptIsLoaded(script, SCRIPT_ID)) { + int id = s->seg_manager->segGet(script); if (s->execution_stack[s->execution_stack_pos].addr.pc.segment != id) - sm_set_lockers(&(s->seg_manager), 1, script, SCRIPT_ID); + s->seg_manager->setLockers(1, script, SCRIPT_ID); } script_uninstantiate(s, script); @@ -279,7 +279,7 @@ reg_t kDisposeScript(EngineState *s, int funct_nr, int argc, reg_t *argv) { int is_heap_object(EngineState *s, reg_t pos) { object_t *obj = obj_get(s, pos); - return (obj != NULL && (!(obj->flags & OBJECT_FLAG_FREED)) && (!sm_script_is_marked_as_deleted(&s->seg_manager, pos.segment))); + return (obj != NULL && (!(obj->flags & OBJECT_FLAG_FREED)) && (!s->seg_manager->scriptIsMarkedAsDeleted(pos.segment))); } reg_t kIsObject(EngineState *s, int funct_nr, int argc, reg_t *argv) { diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 55a86fcdda..f961515c94 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -200,14 +200,14 @@ reg_t kSetSynonyms(EngineState *s, int funct_nr, int argc, reg_t *argv) { int synonyms_nr = 0; script = GET_SEL32V(objpos, number); - seg = sm_seg_get(&(s->seg_manager), script); + seg = s->seg_manager->segGet(script); - if (seg >= 0) synonyms_nr = sm_get_synonyms_nr(&(s->seg_manager), seg, SEG_ID); + if (seg >= 0) synonyms_nr = s->seg_manager->getSynonymsNr(seg, SEG_ID); if (synonyms_nr) { byte *synonyms; - synonyms = sm_get_synonyms(&(s->seg_manager), seg, SEG_ID); + synonyms = s->seg_manager->getSynonyms(seg, SEG_ID); if (synonyms) { int i; if (s->synonyms_nr) @@ -389,7 +389,7 @@ reg_t kStrCpy(EngineState *s, int funct_nr, int argc, reg_t *argv) { if (length >= 0) strncpy(dest, src, length); else { - if (s->seg_manager.heap[argv[0].segment]->type == MEM_OBJ_DYNMEM) { + if (s->seg_manager->heap[argv[0].segment]->type == MEM_OBJ_DYNMEM) { reg_t *srcp = (reg_t *) src; int i; @@ -421,7 +421,7 @@ reg_t kStrAt(EngineState *s, int funct_nr, int argc, reg_t *argv) { if ((argc == 2) && /* Our pathfinder already works around the issue we're trying to fix */ - (strcmp(sm_get_description(&(s->seg_manager), argv[0]), + (strcmp(s->seg_manager->getDescription(argv[0]), AVOIDPATH_DYNMEM_STRING) != 0) && ((strlen((const char*)dest) < 2) || (!is_print_str((char*)dest)))) /* SQ4 array handling detected */ diff --git a/engines/sci/engine/savegame.cfsml b/engines/sci/engine/savegame.cfsml index d977ec8eb9..e61925329d 100644 --- a/engines/sci/engine/savegame.cfsml +++ b/engines/sci/engine/savegame.cfsml @@ -291,7 +291,7 @@ RECORD SegManager "SegManager" { int heap_size; int reserved_id; int exports_wide; - int sci1_1; + int isSci1_1; int gc_mark_bits; size_t mem_allocated; seg_id_t clones_seg_id; @@ -641,11 +641,13 @@ void write_mem_obj_t(Common::WriteStream *fh, mem_obj_t *foo) { case MEM_OBJ_DYNMEM: %CFSMLWRITE dynmem_t &foo->data.dynmem INTO fh; break; + default: + break; } } int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *lastval, int *line, int *hiteof) { - foo->type = mem_obj_string_to_enum(lastval); + foo->type = (memObjType)mem_obj_string_to_enum(lastval); if (foo->type < 0) { sciprintf("Unknown mem_obj_t type %s on line %d\n", lastval, *line); return 1; @@ -681,6 +683,8 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l case MEM_OBJ_DYNMEM: %CFSMLREAD dynmem_t &foo->data.dynmem FROM fh ERRVAR *hiteof LINECOUNTER *line; break; + default: + break; } return *hiteof; @@ -787,8 +791,8 @@ static byte *find_unique_script_block(EngineState *s, byte *buf, int type) { } static void reconstruct_stack(EngineState *retval) { - seg_id_t stack_seg = find_unique_seg_by_type(&retval->seg_manager, MEM_OBJ_STACK); - dstack_t *stack = &(retval->seg_manager.heap[stack_seg]->data.stack); + seg_id_t stack_seg = find_unique_seg_by_type(retval->seg_manager, MEM_OBJ_STACK); + dstack_t *stack = &(retval->seg_manager->heap[stack_seg]->data.stack); retval->stack_segment = stack_seg; retval->stack_base = stack->entries; @@ -813,7 +817,7 @@ static int clone_entry_used(clone_table_t *table, int n) { static void load_script(EngineState *s, seg_id_t seg) { resource_t *script, *heap = NULL; - script_t *scr = &(s->seg_manager.heap[seg]->data.script); + script_t *scr = &(s->seg_manager->heap[seg]->data.script); scr->buf = (byte *)malloc(scr->buf_size); @@ -821,13 +825,13 @@ static void load_script(EngineState *s, seg_id_t seg) { if (s->version >= SCI_VERSION(1,001,000)) heap = scir_find_resource(s->resmgr, sci_heap, scr->nr, 0); - switch (s->seg_manager.sci1_1) { + switch (s->seg_manager->isSci1_1) { case 0 : - sm_mcpy_in_out(&s->seg_manager, 0, script->data, script->size, seg, SEG_ID); + s->seg_manager->mcpyInOut(0, script->data, script->size, seg, SEG_ID); break; case 1 : - sm_mcpy_in_out(&s->seg_manager, 0, script->data, script->size, seg, SEG_ID); - sm_mcpy_in_out(&s->seg_manager, scr->script_size, heap->data, heap->size, seg, SEG_ID); + s->seg_manager->mcpyInOut(0, script->data, script->size, seg, SEG_ID); + s->seg_manager->mcpyInOut(scr->script_size, heap->data, heap->size, seg, SEG_ID); break; } } @@ -844,14 +848,14 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { script_t *scr = &mobj->data.script; load_script(s, i); - scr->locals_block = scr->locals_segment == 0 ? NULL : &s->seg_manager.heap[scr->locals_segment]->data.locals; + scr->locals_block = scr->locals_segment == 0 ? NULL : &s->seg_manager->heap[scr->locals_segment]->data.locals; scr->export_table = (uint16 *) find_unique_script_block(s, scr->buf, sci_obj_exports); scr->synonyms = find_unique_script_block(s, scr->buf, sci_obj_synonyms); scr->code = NULL; scr->code_blocks_nr = 0; scr->code_blocks_allocated = 0; - if (!self->sci1_1) + if (!self->isSci1_1) scr->export_table += 3; for (j = 0; j < scr->objects_nr; j++) { @@ -859,8 +863,10 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { scr->objects[j].base = scr->buf; scr->objects[j].base_obj = data; } - + break; } + default: + break; } } } @@ -876,7 +882,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { for (j = 0; j < scr->objects_nr; j++) { byte *data = scr->buf + scr->objects[j].pos.offset; - if (self->sci1_1) { + if (self->isSci1_1) { uint16 *funct_area = (uint16 *) (scr->buf + getUInt16( data + 6 )); uint16 *prop_area = (uint16 *) (scr->buf + getUInt16( data + 4 )); @@ -900,7 +906,10 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { scr->objects[j].base_vars = (uint16 *) (data + scr->objects[j].variable_names_nr * 2 + SCRIPT_SELECTOR_OFFSET); } } + break; } + default: + break; } } } @@ -955,6 +964,8 @@ void reconstruct_clones(EngineState *s, SegManager *self) { break; } + default: + break; } } } @@ -1071,15 +1082,15 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { _reset_graphics_input(retval); reconstruct_stack(retval); - reconstruct_scripts(retval, &retval->seg_manager); - reconstruct_clones(retval, &retval->seg_manager); + reconstruct_scripts(retval, retval->seg_manager); + reconstruct_clones(retval, retval->seg_manager); retval->game_obj = s->game_obj; - retval->script_000 = &retval->seg_manager.heap[script_get_segment(s, 0, SCRIPT_GET_DONT_LOAD)]->data.script; + retval->script_000 = &retval->seg_manager->heap[script_get_segment(s, 0, SCRIPT_GET_DONT_LOAD)]->data.script; retval->gc_countdown = GC_INTERVAL - 1; retval->save_dir_copy = make_reg(s->sys_strings_segment, SYS_STRING_SAVEDIR); retval->save_dir_edit_offset = 0; - retval->sys_strings_segment = find_unique_seg_by_type(&retval->seg_manager, MEM_OBJ_SYS_STRINGS); - retval->sys_strings = &(((mem_obj_t *)(GET_SEGMENT(retval->seg_manager, retval->sys_strings_segment, MEM_OBJ_SYS_STRINGS)))->data.sys_strings); + retval->sys_strings_segment = find_unique_seg_by_type(retval->seg_manager, MEM_OBJ_SYS_STRINGS); + retval->sys_strings = &(((mem_obj_t *)(GET_SEGMENT(*retval->seg_manager, retval->sys_strings_segment, MEM_OBJ_SYS_STRINGS)))->data.sys_strings); sys_strings_restore(retval->sys_strings, s->sys_strings); // Time state: diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 2fd439bf4f..76ef6f7710 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -1269,8 +1269,8 @@ _cfsml_write_SegManager(Common::WriteStream *fh, SegManager* save_struc) WSprintf(fh, "exports_wide = "); _cfsml_write_int(fh, (int*) &(save_struc->exports_wide)); WSprintf(fh, "\n"); - WSprintf(fh, "sci1_1 = "); - _cfsml_write_int(fh, (int*) &(save_struc->sci1_1)); + WSprintf(fh, "isSci1_1 = "); + _cfsml_write_int(fh, (int*) &(save_struc->isSci1_1)); WSprintf(fh, "\n"); WSprintf(fh, "gc_mark_bits = "); _cfsml_write_int(fh, (int*) &(save_struc->gc_mark_bits)); @@ -1399,10 +1399,10 @@ _cfsml_read_SegManager(Common::SeekableReadStream *fh, SegManager* save_struc, c return CFSML_FAILURE; } } else - if (!strcmp(token, "sci1_1")) { + if (!strcmp(token, "isSci1_1")) { #line 690 "engines/sci/engine/savegame.cfsml" - if (_cfsml_read_int(fh, (int*) &(save_struc->sci1_1), value, line, hiteof)) { - _cfsml_error("Token expected by _cfsml_read_int() for sci1_1 at line %d\n", *line); + if (_cfsml_read_int(fh, (int*) &(save_struc->isSci1_1), value, line, hiteof)) { + _cfsml_error("Token expected by _cfsml_read_int() for isSci1_1 at line %d\n", *line); return CFSML_FAILURE; } } else @@ -4348,11 +4348,13 @@ void write_mem_obj_t(Common::WriteStream *fh, mem_obj_t *foo) { // End of auto-generated CFSML data writer code #line 643 "engines/sci/engine/savegame.cfsml" break; + default: + break; } } int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *lastval, int *line, int *hiteof) { - foo->type = mem_obj_string_to_enum(lastval); + foo->type = (memObjType)mem_obj_string_to_enum(lastval); if (foo->type < 0) { sciprintf("Unknown mem_obj_t type %s on line %d\n", lastval, *line); return 1; @@ -4381,7 +4383,7 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l } } // End of auto-generated CFSML data reader code -#line 655 "engines/sci/engine/savegame.cfsml" +#line 657 "engines/sci/engine/savegame.cfsml" switch (foo->type) { case MEM_OBJ_SCRIPT: // Auto-generated CFSML data reader code @@ -4407,7 +4409,7 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l } } // End of auto-generated CFSML data reader code -#line 658 "engines/sci/engine/savegame.cfsml" +#line 660 "engines/sci/engine/savegame.cfsml" break; case MEM_OBJ_CLONES: // Auto-generated CFSML data reader code @@ -4433,7 +4435,7 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l } } // End of auto-generated CFSML data reader code -#line 661 "engines/sci/engine/savegame.cfsml" +#line 663 "engines/sci/engine/savegame.cfsml" break; case MEM_OBJ_LOCALS: // Auto-generated CFSML data reader code @@ -4459,7 +4461,7 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l } } // End of auto-generated CFSML data reader code -#line 664 "engines/sci/engine/savegame.cfsml" +#line 666 "engines/sci/engine/savegame.cfsml" break; case MEM_OBJ_SYS_STRINGS: // Auto-generated CFSML data reader code @@ -4485,7 +4487,7 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l } } // End of auto-generated CFSML data reader code -#line 667 "engines/sci/engine/savegame.cfsml" +#line 669 "engines/sci/engine/savegame.cfsml" break; case MEM_OBJ_LISTS: // Auto-generated CFSML data reader code @@ -4511,7 +4513,7 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l } } // End of auto-generated CFSML data reader code -#line 670 "engines/sci/engine/savegame.cfsml" +#line 672 "engines/sci/engine/savegame.cfsml" break; case MEM_OBJ_NODES: // Auto-generated CFSML data reader code @@ -4537,7 +4539,7 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l } } // End of auto-generated CFSML data reader code -#line 673 "engines/sci/engine/savegame.cfsml" +#line 675 "engines/sci/engine/savegame.cfsml" break; case MEM_OBJ_STACK: // Auto-generated CFSML data reader code @@ -4563,7 +4565,7 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l } } // End of auto-generated CFSML data reader code -#line 676 "engines/sci/engine/savegame.cfsml" +#line 678 "engines/sci/engine/savegame.cfsml" foo->data.stack.entries = (reg_t *)sci_calloc(foo->data.stack.nr, sizeof(reg_t)); break; case MEM_OBJ_HUNK: @@ -4593,8 +4595,10 @@ int read_mem_obj_t(Common::SeekableReadStream *fh, mem_obj_t *foo, const char *l } } // End of auto-generated CFSML data reader code -#line 683 "engines/sci/engine/savegame.cfsml" +#line 685 "engines/sci/engine/savegame.cfsml" break; + default: + break; } return *hiteof; @@ -4607,7 +4611,7 @@ void write_mem_obj_tp(Common::WriteStream *fh, mem_obj_t **foo) { write_mem_obj_t(fh, (*foo)); WSprintf(fh, "\n"); // End of auto-generated CFSML data writer code -#line 692 "engines/sci/engine/savegame.cfsml" +#line 696 "engines/sci/engine/savegame.cfsml" } else { // Nothing to write WSprintf(fh, "\\null\\"); } @@ -4640,7 +4644,7 @@ int read_mem_obj_tp(Common::SeekableReadStream *fh, mem_obj_t **foo, const char } } // End of auto-generated CFSML data reader code -#line 703 "engines/sci/engine/savegame.cfsml" +#line 707 "engines/sci/engine/savegame.cfsml" return *hiteof; } return 0; @@ -4694,13 +4698,13 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename _cfsml_write_SavegameMetadata(fh, meta); WSprintf(fh, "\n"); // End of auto-generated CFSML data writer code -#line 752 "engines/sci/engine/savegame.cfsml" +#line 756 "engines/sci/engine/savegame.cfsml" #line 814 "engines/sci/engine/savegame.cfsml" // Auto-generated CFSML data writer code _cfsml_write_EngineState(fh, s); WSprintf(fh, "\n"); // End of auto-generated CFSML data writer code -#line 753 "engines/sci/engine/savegame.cfsml" +#line 757 "engines/sci/engine/savegame.cfsml" delete meta; @@ -4738,8 +4742,8 @@ static byte *find_unique_script_block(EngineState *s, byte *buf, int type) { } static void reconstruct_stack(EngineState *retval) { - seg_id_t stack_seg = find_unique_seg_by_type(&retval->seg_manager, MEM_OBJ_STACK); - dstack_t *stack = &(retval->seg_manager.heap[stack_seg]->data.stack); + seg_id_t stack_seg = find_unique_seg_by_type(retval->seg_manager, MEM_OBJ_STACK); + dstack_t *stack = &(retval->seg_manager->heap[stack_seg]->data.stack); retval->stack_segment = stack_seg; retval->stack_base = stack->entries; @@ -4764,7 +4768,7 @@ static int clone_entry_used(clone_table_t *table, int n) { static void load_script(EngineState *s, seg_id_t seg) { resource_t *script, *heap = NULL; - script_t *scr = &(s->seg_manager.heap[seg]->data.script); + script_t *scr = &(s->seg_manager->heap[seg]->data.script); scr->buf = (byte *)malloc(scr->buf_size); @@ -4772,13 +4776,13 @@ static void load_script(EngineState *s, seg_id_t seg) { if (s->version >= SCI_VERSION(1,001,000)) heap = scir_find_resource(s->resmgr, sci_heap, scr->nr, 0); - switch (s->seg_manager.sci1_1) { + switch (s->seg_manager->isSci1_1) { case 0 : - sm_mcpy_in_out(&s->seg_manager, 0, script->data, script->size, seg, SEG_ID); + s->seg_manager->mcpyInOut(0, script->data, script->size, seg, SEG_ID); break; case 1 : - sm_mcpy_in_out(&s->seg_manager, 0, script->data, script->size, seg, SEG_ID); - sm_mcpy_in_out(&s->seg_manager, scr->script_size, heap->data, heap->size, seg, SEG_ID); + s->seg_manager->mcpyInOut(0, script->data, script->size, seg, SEG_ID); + s->seg_manager->mcpyInOut(scr->script_size, heap->data, heap->size, seg, SEG_ID); break; } } @@ -4795,14 +4799,14 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { script_t *scr = &mobj->data.script; load_script(s, i); - scr->locals_block = scr->locals_segment == 0 ? NULL : &s->seg_manager.heap[scr->locals_segment]->data.locals; + scr->locals_block = scr->locals_segment == 0 ? NULL : &s->seg_manager->heap[scr->locals_segment]->data.locals; scr->export_table = (uint16 *) find_unique_script_block(s, scr->buf, sci_obj_exports); scr->synonyms = find_unique_script_block(s, scr->buf, sci_obj_synonyms); scr->code = NULL; scr->code_blocks_nr = 0; scr->code_blocks_allocated = 0; - if (!self->sci1_1) + if (!self->isSci1_1) scr->export_table += 3; for (j = 0; j < scr->objects_nr; j++) { @@ -4810,8 +4814,10 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { scr->objects[j].base = scr->buf; scr->objects[j].base_obj = data; } - + break; } + default: + break; } } } @@ -4827,7 +4833,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { for (j = 0; j < scr->objects_nr; j++) { byte *data = scr->buf + scr->objects[j].pos.offset; - if (self->sci1_1) { + if (self->isSci1_1) { uint16 *funct_area = (uint16 *) (scr->buf + getUInt16( data + 6 )); uint16 *prop_area = (uint16 *) (scr->buf + getUInt16( data + 4 )); @@ -4851,7 +4857,10 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { scr->objects[j].base_vars = (uint16 *) (data + scr->objects[j].variable_names_nr * 2 + SCRIPT_SELECTOR_OFFSET); } } + break; } + default: + break; } } } @@ -4906,6 +4915,8 @@ void reconstruct_clones(EngineState *s, SegManager *self) { break; } + default: + break; } } } @@ -5003,7 +5014,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { } } // End of auto-generated CFSML data reader code -#line 1027 "engines/sci/engine/savegame.cfsml" +#line 1038 "engines/sci/engine/savegame.cfsml" if ((meta->savegame_version < FREESCI_MINIMUM_SAVEGAME_VERSION) || (meta->savegame_version > FREESCI_CURRENT_SAVEGAME_VERSION)) { if (meta->savegame_version < FREESCI_MINIMUM_SAVEGAME_VERSION) @@ -5055,7 +5066,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { } } // End of auto-generated CFSML data reader code -#line 1050 "engines/sci/engine/savegame.cfsml" +#line 1061 "engines/sci/engine/savegame.cfsml" sfx_exit(&s->sound); _gamestate_unfrob(retval); @@ -5080,15 +5091,15 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { _reset_graphics_input(retval); reconstruct_stack(retval); - reconstruct_scripts(retval, &retval->seg_manager); - reconstruct_clones(retval, &retval->seg_manager); + reconstruct_scripts(retval, retval->seg_manager); + reconstruct_clones(retval, retval->seg_manager); retval->game_obj = s->game_obj; - retval->script_000 = &retval->seg_manager.heap[script_get_segment(s, 0, SCRIPT_GET_DONT_LOAD)]->data.script; + retval->script_000 = &retval->seg_manager->heap[script_get_segment(s, 0, SCRIPT_GET_DONT_LOAD)]->data.script; retval->gc_countdown = GC_INTERVAL - 1; retval->save_dir_copy = make_reg(s->sys_strings_segment, SYS_STRING_SAVEDIR); retval->save_dir_edit_offset = 0; - retval->sys_strings_segment = find_unique_seg_by_type(&retval->seg_manager, MEM_OBJ_SYS_STRINGS); - retval->sys_strings = &(((mem_obj_t *)(GET_SEGMENT(retval->seg_manager, retval->sys_strings_segment, MEM_OBJ_SYS_STRINGS)))->data.sys_strings); + retval->sys_strings_segment = find_unique_seg_by_type(retval->seg_manager, MEM_OBJ_SYS_STRINGS); + retval->sys_strings = &(((mem_obj_t *)(GET_SEGMENT(*retval->seg_manager, retval->sys_strings_segment, MEM_OBJ_SYS_STRINGS)))->data.sys_strings); sys_strings_restore(retval->sys_strings, s->sys_strings); // Time state: @@ -5179,7 +5190,7 @@ bool get_savegame_metadata(Common::SeekableReadStream* stream, SavegameMetadata* } } // End of auto-generated CFSML data reader code -#line 1145 "engines/sci/engine/savegame.cfsml" +#line 1156 "engines/sci/engine/savegame.cfsml" if (read_eof) return false; diff --git a/engines/sci/engine/scriptconsole.cpp b/engines/sci/engine/scriptconsole.cpp index 65cf110f61..9384d73467 100644 --- a/engines/sci/engine/scriptconsole.cpp +++ b/engines/sci/engine/scriptconsole.cpp @@ -271,7 +271,7 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on if (*endptr) return 1; - dest->segment = sm_seg_get(&s->seg_manager, script_nr); + dest->segment = s->seg_manager->segGet(script_nr); if (!dest->segment) { return 1; @@ -307,8 +307,8 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on str_objname = str + 1; // Now all values are available; iterate over all objects. - for (i = 0; i < s->seg_manager.heap_size; i++) { - mem_obj_t *mobj = s->seg_manager.heap[i]; + for (i = 0; i < s->seg_manager->heap_size; i++) { + mem_obj_t *mobj = s->seg_manager->heap[i]; int idx = 0; int max_index = 0; diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index bb6ea309d1..4fd1dffc9a 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -277,8 +277,8 @@ int c_segtable(EngineState *s) { int i; sciprintf(" ---- segment table ----\n"); - for (i = 0; i < s->seg_manager.heap_size; i++) { - mem_obj_t *mobj = s->seg_manager.heap[i]; + for (i = 0; i < s->seg_manager->heap_size; i++) { + mem_obj_t *mobj = s->seg_manager->heap[i]; if (mobj && mobj->type) { sciprintf(" [%04x] ", i); @@ -345,7 +345,7 @@ static void print_list(EngineState *s, list_t *l) { while (!IS_NULL_REG(pos)) { node_t *node; - mem_obj_t *mobj = GET_SEGMENT(s->seg_manager, pos.segment, MEM_OBJ_NODES); + mem_obj_t *mobj = GET_SEGMENT(*s->seg_manager, pos.segment, MEM_OBJ_NODES); if (!mobj || !ENTRY_IS_VALID(&(mobj->data.nodes), pos.offset)) { sciprintf(" WARNING: "PREG": Doesn't contain list node!\n", @@ -482,7 +482,7 @@ static void _c_single_seg_info(EngineState *s, mem_obj_t *mobj) { } static int show_node(EngineState *s, reg_t addr) { - mem_obj_t *mobj = GET_SEGMENT(s->seg_manager, addr.segment, MEM_OBJ_LISTS); + mem_obj_t *mobj = GET_SEGMENT(*s->seg_manager, addr.segment, MEM_OBJ_LISTS); if (mobj) { list_table_t *lt = &(mobj->data.lists); @@ -499,7 +499,7 @@ static int show_node(EngineState *s, reg_t addr) { } else { node_table_t *nt; node_t *node; - mobj = GET_SEGMENT(s->seg_manager, addr.segment, MEM_OBJ_NODES); + mobj = GET_SEGMENT(*s->seg_manager, addr.segment, MEM_OBJ_NODES); if (!mobj) { sciprintf("Segment #%04x is not a list or node segment\n", addr.segment); @@ -588,7 +588,7 @@ static int c_vr(EngineState *s) { case KSIG_REF: { int size; - unsigned char *block = sm_dereference(&s->seg_manager, reg, &size); + unsigned char *block = s->seg_manager->dereference(reg, &size); sciprintf("raw data\n"); @@ -631,7 +631,7 @@ int c_segkill(EngineState *s) { while (i < cmd_paramlength) { int nr = cmd_params[i++].val; - sm_set_lockers(&(s->seg_manager), nr, 0, SEG_ID); + s->seg_manager->setLockers(nr, 0, SEG_ID); } return 0; } @@ -654,18 +654,18 @@ int c_seginfo(EngineState *s) { if (cmd_paramlength) { while (i < cmd_paramlength) { int nr = cmd_params[i++].val; - if (nr < 0 || nr >= s->seg_manager.heap_size || !s->seg_manager.heap[nr]) { + if (nr < 0 || nr >= s->seg_manager->heap_size || !s->seg_manager->heap[nr]) { sciprintf("Segment %04x does not exist\n", nr); return 1; } sciprintf("[%04x] ", nr); - _c_single_seg_info(s, s->seg_manager.heap[nr]); + _c_single_seg_info(s, s->seg_manager->heap[nr]); } } else - for (i = 0; i < (unsigned int)s->seg_manager.heap_size; i++) { - if (s->seg_manager.heap[i]) { + for (i = 0; i < (unsigned int)s->seg_manager->heap_size; i++) { + if (s->seg_manager->heap[i]) { sciprintf("[%04x] ", i); - _c_single_seg_info(s, s->seg_manager.heap[i]); + _c_single_seg_info(s, s->seg_manager->heap[i]); sciprintf("\n"); } } @@ -1213,7 +1213,7 @@ int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) { reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode) { // Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered. - mem_obj_t *memobj = GET_SEGMENT(s->seg_manager, pos.segment, MEM_OBJ_SCRIPT); + mem_obj_t *memobj = GET_SEGMENT(*s->seg_manager, pos.segment, MEM_OBJ_SCRIPT); script_t *script_entity = NULL; byte *scr; int scr_size; @@ -1591,7 +1591,7 @@ static int c_backtrace(EngineState *s) { sciprintf(" argp:"PSTK, PRINT_STK(call->variables_argp)); if (call->type == EXEC_STACK_TYPE_CALL) - sciprintf(" script: %d", s->seg_manager.heap[call->addr.pc.segment]->data.script.nr); + sciprintf(" script: %d", s->seg_manager->heap[call->addr.pc.segment]->data.script.nr); sciprintf("\n"); } @@ -2024,7 +2024,7 @@ static int c_disasm_addr(EngineState *s) { int invalid = 0; int size; - sm_dereference(&s->seg_manager, vpc, &size); + s->seg_manager->dereference(vpc, &size); size += vpc.offset; // total segment size for (i = 1; i < cmd_paramlength; i++) { @@ -2559,8 +2559,8 @@ int objinfo(EngineState *s, reg_t pos) { reg_t fptr = VM_OBJECT_READ_FUNCTION(obj, i); sciprintf(" [%03x] %s = "PREG"\n", VM_OBJECT_GET_FUNCSELECTOR(obj, i), selector_name(s, VM_OBJECT_GET_FUNCSELECTOR(obj, i)), PRINT_REG(fptr)); } - if (s->seg_manager.heap[pos.segment]->type == MEM_OBJ_SCRIPT) - sciprintf("\nOwner script:\t%d\n", s->seg_manager.heap[pos.segment]->data.script.nr); + if (s->seg_manager->heap[pos.segment]->type == MEM_OBJ_SCRIPT) + sciprintf("\nOwner script:\t%d\n", s->seg_manager->heap[pos.segment]->data.script.nr); return 0; } @@ -2795,7 +2795,7 @@ static void _print_address(void * _, reg_t addr) { } #define GET_SEG_INTERFACE(seg_id) \ - seg_interface_t * seg_interface = get_seg_interface(&(s->seg_manager), seg_id); \ + SegInterface *seg_interface = s->seg_manager->getSegInterface(seg_id); \ if (!seg_interface) { \ sciprintf("Unknown segment : %x\n", seg_id); \ return 1; \ @@ -2889,7 +2889,7 @@ void script_debug(EngineState *s, reg_t *pc, stack_ptr_t *sp, stack_ptr_t *pp, r } if (_debug_seeking && !bp) { // Are we looking for something special? - mem_obj_t *memobj = GET_SEGMENT(s->seg_manager, pc->segment, MEM_OBJ_SCRIPT); + mem_obj_t *memobj = GET_SEGMENT(*s->seg_manager, pc->segment, MEM_OBJ_SCRIPT); if (memobj) { script_t *scr = &(memobj->data.script); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index ed9d6461a7..bbcc310d74 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -24,125 +24,102 @@ */ #include "sci/engine/seg_manager.h" -#include "sci/include/sciresource.h" -#include "sci/include/versions.h" #include "sci/include/engine.h" namespace Sci { -//#define GC_DEBUG*/ // Debug garbage collection -//#define GC_DEBUG_VERBOSE*/ // Debug garbage verbosely +#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 -#define SM_MEMORY_POISON // Poison memory upon deallocation - -mem_obj_t* mem_obj_allocate(SegManager *self, seg_id_t segid, int hash_id, mem_obj_enum type); +//#define GC_DEBUG // Debug garbage collection +//#define GC_DEBUG_VERBOSE // Debug garbage verbosely #undef DEBUG_SEG_MANAGER // Define to turn on debugging #define GET_SEGID() \ if (flag == SCRIPT_ID) \ - id = sm_seg_get (self, id); \ - VERIFY(sm_check(self, id), "invalid seg id"); + id = segGet(id); \ + VERIFY(check(id), "invalid seg id"); +#if 0 +// Unreferenced - removed #define VERIFY_MEM(mem_ptr, ret) \ if (!(mem_ptr)) {\ sciprintf( "%s, *d, no enough memory", __FILE__, __LINE__ ); \ return ret; \ } - -#define INVALID_SCRIPT_ID -1 - -void dbg_print(const char* msg, void *i) { -#ifdef DEBUG_SEG_MANAGER - char buf[1000]; - sprintf(buf, "%s = [0x%x], dec:[%d]", msg, i, i); - perror(buf); #endif -} - -//-- forward declarations -- - -void sm_script_initialise_locals_zero(SegManager *self, seg_id_t seg, int count); -void sm_script_initialise_locals(SegManager *self, reg_t location); -static int _sm_deallocate(SegManager* self, int seg, int recursive); -static hunk_t *sm_alloc_hunk(SegManager *self, reg_t *); -static void sm_free_hunk(SegManager *self, reg_t addr); -static int sm_check(SegManager* self, int seg); -/* Check segment validity -** Parameters: (int) seg: The segment to validate -** Returns : (int) 0 if 'seg' is an invalid segment -** 1 if 'seg' is a valid segment -*/ -// End of Memory Management +#define INVALID_SCRIPT_ID -1 -static inline int find_free_id(SegManager *self, int *id) { +inline int SegManager::findFreeId(int *id) { char was_added = 0; int retval = 0; while (!was_added) { - retval = self->id_seg_map->check_value(self->reserved_id, true, &was_added); - *id = self->reserved_id--; - if (self->reserved_id < -1000000) - self->reserved_id = -10; + retval = id_seg_map->check_value(reserved_id, true, &was_added); + *id = reserved_id--; + if (reserved_id < -1000000) + reserved_id = -10; // Make sure we don't underflow } return retval; } -static mem_obj_t * alloc_nonscript_segment(SegManager *self, mem_obj_enum type, seg_id_t *segid) { +mem_obj_t *SegManager::allocNonscriptSegment(memObjType type, seg_id_t *segid) { // Allocates a non-script segment int id; - *segid = find_free_id(self, &id); - return mem_obj_allocate(self, *segid, id, type); + *segid = findFreeId(&id); + return memObjAllocate(*segid, id, type); } -void sm_init(SegManager* self, int sci1_1) { +SegManager::SegManager(bool sci1_1) { int i; - self->mem_allocated = 0; // Initialise memory count + // Initialise memory count + mem_allocated = 0; - self->id_seg_map = new int_hash_map_t(); - self->reserved_id = INVALID_SCRIPT_ID; - self->id_seg_map->check_value(self->reserved_id, true); // reserve 0 for seg_id - self->reserved_id--; // reserved_id runs in the reversed direction to make sure no one will use it. + id_seg_map = new int_hash_map_t(); + reserved_id = INVALID_SCRIPT_ID; + id_seg_map->check_value(reserved_id, true); // reserve 0 for seg_id + reserved_id--; // reserved_id runs in the reversed direction to make sure no one will use it. - self->heap_size = DEFAULT_SCRIPTS; - self->heap = (mem_obj_t**)sci_calloc(self->heap_size, sizeof(mem_obj_t *)); + heap_size = DEFAULT_SCRIPTS; + heap = (mem_obj_t **)sci_calloc(heap_size, sizeof(mem_obj_t *)); - self->clones_seg_id = 0; - self->lists_seg_id = 0; - self->nodes_seg_id = 0; - self->hunks_seg_id = 0; + clones_seg_id = 0; + lists_seg_id = 0; + nodes_seg_id = 0; + hunks_seg_id = 0; - self->exports_wide = 0; - self->sci1_1 = sci1_1; + exports_wide = 0; + isSci1_1 = sci1_1; // initialize the heap pointers - for (i = 0; i < self->heap_size; i++) { - self->heap[i] = NULL; + for (i = 0; i < heap_size; i++) { + heap[i] = NULL; } // gc initialisation - self->gc_mark_bits = 0; + gc_mark_bits = 0; } -// destroy the object, free the memorys if allocated before -void sm_destroy(SegManager* self) { +// Destroy the object, free the memorys if allocated before +SegManager::~SegManager() { int i; - // free memory - for (i = 0; i < self->heap_size; i++) { - if (self->heap[i]) - _sm_deallocate(self, i, 0); + // Free memory + for (i = 0; i < heap_size; i++) { + if (heap[i]) + deallocate(i, false); } - delete self->id_seg_map; + delete id_seg_map; - free(self->heap); - self->heap = NULL; + free(heap); } // allocate a memory for script from heap @@ -151,19 +128,19 @@ void sm_destroy(SegManager* self) { // Returns : 0 - allocation failure // 1 - allocated successfully // seg_id - allocated segment id -mem_obj_t *sm_allocate_script(SegManager* self, EngineState *s, int script_nr, int* seg_id) { +mem_obj_t *SegManager::allocateScript(EngineState *s, int script_nr, int* seg_id) { int seg; char was_added; mem_obj_t* mem; - seg = self->id_seg_map->check_value(script_nr, true, &was_added); + seg = id_seg_map->check_value(script_nr, true, &was_added); if (!was_added) { *seg_id = seg; - return self->heap[*seg_id]; + return heap[*seg_id]; } // allocate the mem_obj_t - mem = mem_obj_allocate(self, seg, script_nr, MEM_OBJ_SCRIPT); + mem = memObjAllocate(seg, script_nr, MEM_OBJ_SCRIPT); if (!mem) { sciprintf("%s, %d, Not enough memory, ", __FILE__, __LINE__); return NULL; @@ -173,7 +150,7 @@ mem_obj_t *sm_allocate_script(SegManager* self, EngineState *s, int script_nr, i return mem; } -static void sm_set_script_size(mem_obj_t *mem, EngineState *s, int script_nr) { +void SegManager::setScriptSize(mem_obj_t *mem, EngineState *s, int script_nr) { resource_t *script = scir_find_resource(s->resmgr, sci_script, script_nr, 0); resource_t *heap = scir_find_resource(s->resmgr, sci_heap, script_nr, 0); @@ -209,17 +186,17 @@ static void sm_set_script_size(mem_obj_t *mem, EngineState *s, int script_nr) { } } -int sm_initialise_script(mem_obj_t *mem, EngineState *s, int script_nr) { +int SegManager::initialiseScript(mem_obj_t *mem, EngineState *s, int script_nr) { // allocate the script.buf script_t *scr; - sm_set_script_size(mem, s, script_nr); + setScriptSize(mem, s, script_nr); mem->data.script.buf = (byte*) sci_malloc(mem->data.script.buf_size); - dbg_print("mem->data.script.buf ", mem->data.script.buf); + dbgPrint("mem->data.script.buf ", mem->data.script.buf); if (!mem->data.script.buf) { - sm_free_script(mem); - sciprintf("seg_manager.c: Not enough memory space for script size"); + freeScript(mem); + sciprintf("SegManager: Not enough memory space for script size"); mem->data.script.buf_size = 0; return 0; } @@ -251,20 +228,20 @@ int sm_initialise_script(mem_obj_t *mem, EngineState *s, int script_nr) { return 1; } -int _sm_deallocate(SegManager *self, int seg, int recursive) { +int SegManager::deallocate(int seg, bool recursive) { mem_obj_t *mobj; - VERIFY(sm_check(self, seg), "invalid seg id"); + VERIFY(check(seg), "invalid seg id"); - mobj = self->heap[seg]; - self->id_seg_map->remove_value(mobj->segmgr_id); + mobj = heap[seg]; + id_seg_map->remove_value(mobj->segmgr_id); switch (mobj->type) { case MEM_OBJ_SCRIPT: - sm_free_script(mobj); + freeScript(mobj); mobj->data.script.buf = NULL; if (recursive && mobj->data.script.locals_segment) - _sm_deallocate(self, mobj->data.script.locals_segment, recursive); + deallocate(mobj->data.script.locals_segment, recursive); break; case MEM_OBJ_LOCALS: @@ -314,105 +291,105 @@ int _sm_deallocate(SegManager *self, int seg, int recursive) { } free(mobj); - self->heap[seg] = NULL; + heap[seg] = NULL; return 1; } -int sm_script_marked_deleted(SegManager *self, int script_nr) { +int SegManager::scriptMarkedDeleted(int script_nr) { script_t *scr; - int seg = sm_seg_get(self, script_nr); - VERIFY(sm_check(self, seg), "invalid seg id"); + int seg = segGet(script_nr); + VERIFY(check(seg), "invalid seg id"); - scr = &(self->heap[seg]->data.script); + scr = &(heap[seg]->data.script); return scr->marked_as_deleted; } -void sm_mark_script_deleted(SegManager *self, int script_nr) { +void SegManager::markScriptDeleted(int script_nr) { script_t *scr; - int seg = sm_seg_get(self, script_nr); - VERIFY(sm_check(self, seg), "invalid seg id"); + int seg = segGet(script_nr); + VERIFY(check(seg), "invalid seg id"); - scr = &(self->heap[seg]->data.script); + scr = &(heap[seg]->data.script); scr->marked_as_deleted = 1; } -void sm_unmark_script_deleted(SegManager* self, int script_nr) { +void SegManager::unmarkScriptDeleted(int script_nr) { script_t *scr; - int seg = sm_seg_get(self, script_nr); - VERIFY(sm_check(self, seg), "invalid seg id"); + int seg = segGet(script_nr); + VERIFY(check(seg), "invalid seg id"); - scr = &(self->heap[seg]->data.script); + scr = &(heap[seg]->data.script); scr->marked_as_deleted = 0; } -int sm_script_is_marked_as_deleted(SegManager* self, seg_id_t seg) { +int SegManager::scriptIsMarkedAsDeleted(seg_id_t seg) { script_t *scr; - if (!sm_check(self, seg)) + if (!check(seg)) return 0; - if (self->heap[seg]->type != MEM_OBJ_SCRIPT) + if (heap[seg]->type != MEM_OBJ_SCRIPT) return 0; - scr = &(self->heap[seg]->data.script); + scr = &(heap[seg]->data.script); return scr->marked_as_deleted; } -int sm_deallocate_script(SegManager* self, int script_nr) { - int seg = sm_seg_get(self, script_nr); +int SegManager::deallocateScript(int script_nr) { + int seg = segGet(script_nr); - _sm_deallocate(self, seg, 1); + deallocate(seg, true); return 1; } -mem_obj_t* mem_obj_allocate(SegManager *self, seg_id_t segid, int hash_id, mem_obj_enum type) { - mem_obj_t* mem = (mem_obj_t*) sci_calloc(sizeof(mem_obj_t), 1); +mem_obj_t *SegManager::memObjAllocate(seg_id_t segid, int hash_id, memObjType type) { + mem_obj_t *mem = (mem_obj_t *)sci_calloc(sizeof(mem_obj_t), 1); if (!mem) { - sciprintf("seg_manager.c: invalid mem_obj "); + sciprintf("SegManager: invalid mem_obj "); return NULL; } - if (segid >= self->heap_size) { + if (segid >= heap_size) { void *temp; - int oldhs = self->heap_size; + int oldhs = heap_size; - if (segid >= self->heap_size * 2) { - sciprintf("seg_manager.c: hash_map error or others??"); + if (segid >= heap_size * 2) { + sciprintf("SegManager: hash_map error or others??"); return NULL; } - self->heap_size *= 2; - temp = sci_realloc((void*)self->heap, self->heap_size * sizeof(mem_obj_t*)); + heap_size *= 2; + temp = sci_realloc((void *)heap, heap_size * sizeof(mem_obj_t *)); if (!temp) { - sciprintf("seg_manager.c: Not enough memory space for script size"); + sciprintf("SegManager: Not enough memory space for script size"); return NULL; } - self->heap = (mem_obj_t**) temp; + heap = (mem_obj_t **)temp; // Clear pointers - memset(self->heap + oldhs, 0, sizeof(mem_obj_t *) * (self->heap_size - oldhs)); + memset(heap + oldhs, 0, sizeof(mem_obj_t *) * (heap_size - oldhs)); } mem->segmgr_id = hash_id; mem->type = type; // hook it to the heap - self->heap[segid] = mem; + heap[segid] = mem; return mem; } /* No longer in use? -void sm_object_init(object_t *object) { +void SegManager::sm_object_init(object_t *object) { if (!object) return; object->variables_nr = 0; object->variables = NULL; };*/ -void sm_free_script(mem_obj_t *mem) { +void SegManager::freeScript(mem_obj_t *mem) { if (!mem) return; if (mem->data.script.buf) { @@ -445,10 +422,10 @@ void sm_free_script(mem_obj_t *mem) { // memory operations #if 0 // Unreferenced - removed -static void sm_mset(SegManager *self, int offset, int c, size_t n, int id, int flag) { +static void SegManager::sm_mset(int offset, int c, size_t n, int id, int flag) { mem_obj_t *mem_obj; GET_SEGID(); - mem_obj = self->heap[id]; + mem_obj = heap[id]; switch (mem_obj->type) { case MEM_OBJ_SCRIPT: if (mem_obj->data.script.buf) { @@ -467,10 +444,10 @@ static void sm_mset(SegManager *self, int offset, int c, size_t n, int id, int f #if 0 // Unreferenced - removed -static void sm_mcpy_in_in(SegManager *self, int dst, const int src, size_t n, int id, int flag) { +static void SegManager::sm_mcpy_in_in(int dst, const int src, size_t n, int id, int flag) { mem_obj_t *mem_obj; GET_SEGID(); - mem_obj = self->heap[id]; + mem_obj = heap[id]; switch (mem_obj->type) { case MEM_OBJ_SCRIPT: if (mem_obj->data.script.buf) { @@ -487,10 +464,10 @@ static void sm_mcpy_in_in(SegManager *self, int dst, const int src, size_t n, in } #endif -void sm_mcpy_in_out(SegManager *self, int dst, const void *src, size_t n, int id, int flag) { +void SegManager::mcpyInOut(int dst, const void *src, size_t n, int id, int flag) { mem_obj_t *mem_obj; GET_SEGID(); - mem_obj = self->heap[id]; + mem_obj = heap[id]; switch (mem_obj->type) { case MEM_OBJ_SCRIPT: if (mem_obj->data.script.buf) { @@ -508,10 +485,10 @@ void sm_mcpy_in_out(SegManager *self, int dst, const void *src, size_t n, int id #if 0 // Unreferenced - removed -static void sm_mcpy_out_in(SegManager *self, void *dst, const int src, size_t n, int id, int flag) { +static void SegManager::sm_mcpy_out_in(void *dst, const int src, size_t n, int id, int flag) { mem_obj_t *mem_obj; GET_SEGID(); - mem_obj = self->heap[id]; + mem_obj = heap[id]; switch (mem_obj->type) { case MEM_OBJ_SCRIPT: if (mem_obj->data.script.buf) { @@ -528,12 +505,12 @@ static void sm_mcpy_out_in(SegManager *self, void *dst, const int src, size_t n, } #endif -int16 sm_get_heap(SegManager *self, reg_t reg) { +int16 SegManager::getHeap(reg_t reg) { mem_obj_t *mem_obj; - mem_obj_enum mem_type; + memObjType mem_type; - VERIFY(sm_check(self, reg.segment), "Invalid seg id"); - mem_obj = self->heap[reg.segment]; + VERIFY(check(reg.segment), "Invalid seg id"); + mem_obj = heap[reg.segment]; mem_type = mem_obj->type; switch (mem_type) { @@ -550,12 +527,14 @@ int16 sm_get_heap(SegManager *self, reg_t reg) { return 0; // never get here } -void sm_put_heap(SegManager *self, reg_t reg, int16 value) { +#if 0 +// Unreferenced - removed +void SegManager::sm_put_heap(reg_t reg, int16 value) { mem_obj_t *mem_obj; - mem_obj_enum mem_type; + memObjType mem_type; - VERIFY(sm_check(self, reg.segment), "Invalid seg id"); - mem_obj = self->heap[reg.segment]; + VERIFY(check(reg.segment), "Invalid seg id"); + mem_obj = heap[reg.segment]; mem_type = mem_obj->type; switch (mem_type) { @@ -572,67 +551,68 @@ void sm_put_heap(SegManager *self, reg_t reg, int16 value) { break; } } +#endif // return the seg if script_id is valid and in the map, else -1 -int sm_seg_get(SegManager *self, int script_id) { - return self->id_seg_map->check_value(script_id, false); +int SegManager::segGet(int script_id) { + return id_seg_map->check_value(script_id, false); } // validate the seg // return: -// 0 - invalid seg -// 1 - valid seg -static int sm_check(SegManager *self, int seg) { - if (seg < 0 || seg >= self->heap_size) { - return 0; +// false - invalid seg +// true - valid seg +bool SegManager::check(int seg) { + if (seg < 0 || seg >= heap_size) { + return false; } - if (!self->heap[seg]) { - sciprintf("seg_manager.c: seg %x is removed from memory, but not removed from hash_map\n", seg); - return 0; + if (!heap[seg]) { + sciprintf("SegManager: seg %x is removed from memory, but not removed from hash_map\n", seg); + return false; } - return 1; + return true; } -int sm_script_is_loaded(SegManager *self, int id, id_flag flag) { +int SegManager::scriptIsLoaded(int id, idFlag flag) { if (flag == SCRIPT_ID) - id = sm_seg_get(self, id); + id = segGet(id); - return sm_check(self, id); + return check(id); } -void sm_increment_lockers(SegManager *self, int id, id_flag flag) { +void SegManager::incrementLockers(int id, idFlag flag) { if (flag == SCRIPT_ID) - id = sm_seg_get(self, id); - VERIFY(sm_check(self, id), "invalid seg id"); - self->heap[id]->data.script.lockers++; + id = segGet(id); + VERIFY(check(id), "invalid seg id"); + heap[id]->data.script.lockers++; } -void sm_decrement_lockers(SegManager *self, int id, id_flag flag) { +void SegManager::decrementLockers(int id, idFlag flag) { if (flag == SCRIPT_ID) - id = sm_seg_get(self, id); - VERIFY(sm_check(self, id), "invalid seg id"); + id = segGet(id); + VERIFY(check(id), "invalid seg id"); - if (self->heap[id]->data.script.lockers > 0) - self->heap[id]->data.script.lockers--; + if (heap[id]->data.script.lockers > 0) + heap[id]->data.script.lockers--; } -int sm_get_lockers(SegManager *self, int id, id_flag flag) { +int SegManager::getLockers(int id, idFlag flag) { if (flag == SCRIPT_ID) - id = sm_seg_get(self, id); - VERIFY(sm_check(self, id), "invalid seg id"); + id = segGet(id); + VERIFY(check(id), "invalid seg id"); - return self->heap[id]->data.script.lockers; + return heap[id]->data.script.lockers; } -void sm_set_lockers(SegManager *self, int lockers, int id, id_flag flag) { +void SegManager::setLockers(int lockers, int id, idFlag flag) { if (flag == SCRIPT_ID) - id = sm_seg_get(self, id); - VERIFY(sm_check(self, id), "invalid seg id"); - self->heap[id]->data.script.lockers = lockers; + id = segGet(id); + VERIFY(check(id), "invalid seg id"); + heap[id]->data.script.lockers = lockers; } -void sm_set_export_table_offset(SegManager *self, int offset, int id, id_flag flag) { - script_t *scr = &(self->heap[id]->data.script); +void SegManager::setExportTableOffset(int offset, int id, idFlag flag) { + script_t *scr = &(heap[id]->data.script); GET_SEGID(); if (offset) { @@ -644,62 +624,65 @@ void sm_set_export_table_offset(SegManager *self, int offset, int id, id_flag fl } } -int sm_hash_segment_data(SegManager *self, int id) { +#if 0 +// Unreferenced - removed +int SegManager::sm_hash_segment_data(int id) { int i, len, hash_code = 0x55555555; char *buf; - if (self->heap[id]->type == MEM_OBJ_LISTS) + if (heap[id]->type == MEM_OBJ_LISTS) return 0; - if (self->heap[id]->type == MEM_OBJ_NODES) + if (heap[id]->type == MEM_OBJ_NODES) return 0; - if (self->heap[id]->type == MEM_OBJ_CLONES) + if (heap[id]->type == MEM_OBJ_CLONES) return 0; - buf = (char *)sm_dereference(self, make_reg(id, 0), &len); + buf = (char *)dereference(make_reg(id, 0), &len); for (i = 0; i < len; i++) hash_code = (hash_code * 19) + *(buf + i); return hash_code; } +#endif -void sm_set_export_width(SegManager *self, int flag) { - self->exports_wide = flag; +void SegManager::setExportWidth(int flag) { + exports_wide = flag; } #if 0 // Unreferenced - removed -static uint16 *sm_get_export_table_offset(SegManager *self, int id, int flag, int *max) { +static uint16 *SegManager::sm_get_export_table_offset(int id, int flag, int *max) { GET_SEGID(); if (max) - *max = self->heap[id]->data.script.exports_nr; + *max = heap[id]->data.script.exports_nr; - return self->heap[id]->data.script.export_table; + return heap[id]->data.script.export_table; } #endif -void sm_set_synonyms_offset(SegManager *self, int offset, int id, id_flag flag) { +void SegManager::setSynonymsOffset(int offset, int id, idFlag flag) { GET_SEGID(); - self->heap[id]->data.script.synonyms = self->heap[id]->data.script.buf + offset; + heap[id]->data.script.synonyms = heap[id]->data.script.buf + offset; } -byte *sm_get_synonyms(SegManager *self, int id, id_flag flag) { +byte *SegManager::getSynonyms(int id, idFlag flag) { GET_SEGID(); - return self->heap[id]->data.script.synonyms; + return heap[id]->data.script.synonyms; } -void sm_set_synonyms_nr(SegManager *self, int nr, int id, id_flag flag) { +void SegManager::setSynonymsNr(int nr, int id, idFlag flag) { GET_SEGID(); - self->heap[id]->data.script.synonyms_nr = nr; + heap[id]->data.script.synonyms_nr = nr; } -int sm_get_synonyms_nr(SegManager *self, int id, id_flag flag) { +int SegManager::getSynonymsNr(int id, idFlag flag) { GET_SEGID(); - return self->heap[id]->data.script.synonyms_nr; + return heap[id]->data.script.synonyms_nr; } #if 0 // Unreferenced - removed -static int sm_get_heappos(SegManager *self, int id, int flag) { +static int SegManager::sm_get_heappos(int id, int flag) { GET_SEGID(); return 0; } @@ -707,12 +690,12 @@ static int sm_get_heappos(SegManager *self, int id, int flag) { #if 0 // Unreferenced - removed -static void sm_set_variables(SegManager *self, reg_t reg, int obj_index, reg_t variable_reg, int variable_index) { +static void SegManager::sm_set_variables(reg_t reg, int obj_index, reg_t variable_reg, int variable_index) { script_t *script; - VERIFY(sm_check(self, reg.segment), "invalid seg id"); - VERIFY(self->heap[reg.segment], "invalid mem"); + VERIFY(check(reg.segment), "invalid seg id"); + VERIFY(heap[reg.segment], "invalid mem"); - script = &(self->heap[reg.segment]->data.script); + script = &(heap[reg.segment]->data.script); VERIFY(obj_index < script->objects_nr, "Invalid obj_index"); @@ -722,7 +705,7 @@ static void sm_set_variables(SegManager *self, reg_t reg, int obj_index, reg_t v } #endif -static inline int _relocate_block(SegManager *self, reg_t *block, int block_location, int block_items, seg_id_t segment, int location) { +inline int SegManager::relocateBlock(reg_t *block, int block_location, int block_items, seg_id_t segment, int location) { int rel = location - block_location; int index; @@ -739,29 +722,29 @@ static inline int _relocate_block(SegManager *self, reg_t *block, int block_loca return 0; } block[index].segment = segment; // Perform relocation - if (self->sci1_1) - block[index].offset += self->heap[segment]->data.script.script_size; + if (isSci1_1) + block[index].offset += heap[segment]->data.script.script_size; return 1; } -static inline int _relocate_local(SegManager *self, script_t *scr, seg_id_t segment, int location) { +inline int SegManager::relocateLocal(script_t *scr, seg_id_t segment, int location) { if (scr->locals_block) - return _relocate_block(self, scr->locals_block->locals, scr->locals_offset, scr->locals_block->nr, segment, location); + return relocateBlock(scr->locals_block->locals, scr->locals_offset, scr->locals_block->nr, segment, location); else return 0; // No hands, no cookies } -static inline int _relocate_object(SegManager *self, object_t *obj, seg_id_t segment, int location) { - return _relocate_block(self, obj->variables, obj->pos.offset, obj->variables_nr, segment, location); +inline int SegManager::relocateObject(object_t *obj, seg_id_t segment, int location) { + return relocateBlock(obj->variables, obj->pos.offset, obj->variables_nr, segment, location); } -void sm_script_add_code_block(SegManager *self, reg_t location) { - mem_obj_t *mobj = self->heap[location.segment]; +void SegManager::scriptAddCodeBlock(reg_t location) { + mem_obj_t *mobj = heap[location.segment]; script_t *scr; int index; - VERIFY(!(location.segment >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to add a code block to non-script\n"); + VERIFY(!(location.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to add a code block to non-script\n"); scr = &(mobj->data.script); @@ -775,13 +758,13 @@ void sm_script_add_code_block(SegManager *self, reg_t location) { scr->code[index].size = getUInt16(scr->buf + location.offset - 2); } -void sm_script_relocate(SegManager *self, reg_t block) { - mem_obj_t *mobj = self->heap[block.segment]; +void SegManager::scriptRelocate(reg_t block) { + mem_obj_t *mobj = heap[block.segment]; script_t *scr; int count; int i; - VERIFY(!(block.segment >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt relocate non-script\n"); + VERIFY(!(block.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt relocate non-script\n"); scr = &(mobj->data.script); @@ -795,11 +778,11 @@ void sm_script_relocate(SegManager *self, reg_t block) { if (!pos) continue; // FIXME: A hack pending investigation - if (!_relocate_local(self, scr, block.segment, pos)) { + if (!relocateLocal(scr, block.segment, pos)) { int k, done = 0; for (k = 0; !done && k < scr->objects_nr; k++) { - if (_relocate_object(self, scr->objects + k, block.segment, pos)) + if (relocateObject(scr->objects + k, block.segment, pos)) done = 1; } @@ -827,13 +810,13 @@ void sm_script_relocate(SegManager *self, reg_t block) { } } -void sm_heap_relocate(SegManager *self, EngineState *s, reg_t block) { - mem_obj_t *mobj = self->heap[block.segment]; +void SegManager::heapRelocate(EngineState *s, reg_t block) { + mem_obj_t *mobj = heap[block.segment]; script_t *scr; int count; int i; - VERIFY(!(block.segment >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt relocate non-script\n"); + VERIFY(!(block.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt relocate non-script\n"); scr = &(mobj->data.script); @@ -848,11 +831,11 @@ void sm_heap_relocate(SegManager *self, EngineState *s, reg_t block) { for (i = 0; i < count; i++) { int pos = getUInt16(scr->heap_start + block.offset + 2 + (i * 2)) + scr->script_size; - if (!_relocate_local(self, scr, block.segment, pos)) { + if (!relocateLocal(scr, block.segment, pos)) { int k, done = 0; for (k = 0; !done && k < scr->objects_nr; k++) { - if (_relocate_object(self, scr->objects + k, block.segment, pos)) + if (relocateObject(scr->objects + k, block.segment, pos)) done = 1; } @@ -876,15 +859,15 @@ void sm_heap_relocate(SegManager *self, EngineState *s, reg_t block) { reg_t get_class_address(EngineState *s, int classnr, int lock, reg_t caller); -static object_t *sm_script_obj_init0(SegManager *self, EngineState *s, reg_t obj_pos) { - mem_obj_t *mobj = self->heap[obj_pos.segment]; +object_t *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) { + mem_obj_t *mobj = heap[obj_pos.segment]; script_t *scr; object_t *obj; int id; unsigned int base = obj_pos.offset - SCRIPT_OBJECT_MAGIC_OFFSET; reg_t temp; - VERIFY(!(obj_pos.segment >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize object in non-script\n"); + VERIFY(!(obj_pos.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize object in non-script\n"); scr = &(mobj->data.script); @@ -944,14 +927,14 @@ static object_t *sm_script_obj_init0(SegManager *self, EngineState *s, reg_t obj return obj; } -static object_t *sm_script_obj_init11(SegManager *self, EngineState *s, reg_t obj_pos) { - mem_obj_t *mobj = self->heap[obj_pos.segment]; +object_t *SegManager::scriptObjInit11(EngineState *s, reg_t obj_pos) { + mem_obj_t *mobj = heap[obj_pos.segment]; script_t *scr; object_t *obj; int id; int base = obj_pos.offset; - VERIFY(!(obj_pos.segment >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize object in non-script\n"); + VERIFY(!(obj_pos.segment >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize object in non-script\n"); scr = &(mobj->data.script); @@ -1011,14 +994,14 @@ static object_t *sm_script_obj_init11(SegManager *self, EngineState *s, reg_t ob return obj; } -object_t *sm_script_obj_init(SegManager *self, EngineState *s, reg_t obj_pos) { - if (!self->sci1_1) - return sm_script_obj_init0(self, s, obj_pos); +object_t *SegManager::scriptObjInit(EngineState *s, reg_t obj_pos) { + if (!isSci1_1) + return scriptObjInit0(s, obj_pos); else - return sm_script_obj_init11(self, s, obj_pos); + return scriptObjInit11(s, obj_pos); } -static local_variables_t *_sm_alloc_locals_segment(SegManager *self, script_t *scr, int count) { +local_variables_t *SegManager::allocLocalsSegment(script_t *scr, int count) { if (!count) { // No locals scr->locals_segment = 0; scr->locals_block = NULL; @@ -1028,12 +1011,12 @@ static local_variables_t *_sm_alloc_locals_segment(SegManager *self, script_t *s local_variables_t *locals; if (scr->locals_segment) { - mobj = self->heap[scr->locals_segment]; + mobj = heap[scr->locals_segment]; VERIFY(mobj != NULL, "Re-used locals segment was NULL'd out"); VERIFY(mobj->type == MEM_OBJ_LOCALS, "Re-used locals segment did not consist of local variables"); VERIFY(mobj->data.locals.script_id == scr->nr, "Re-used locals segment belonged to other script"); } else - mobj = alloc_nonscript_segment(self, MEM_OBJ_LOCALS, &scr->locals_segment); + mobj = allocNonscriptSegment(MEM_OBJ_LOCALS, &scr->locals_segment); locals = scr->locals_block = &(mobj->data.locals); locals->script_id = scr->nr; @@ -1044,32 +1027,32 @@ static local_variables_t *_sm_alloc_locals_segment(SegManager *self, script_t *s } } -void sm_script_initialise_locals_zero(SegManager *self, seg_id_t seg, int count) { - mem_obj_t *mobj = self->heap[seg]; +void SegManager::scriptInitialiseLocalsZero(seg_id_t seg, int count) { + mem_obj_t *mobj = heap[seg]; script_t *scr; - VERIFY(!(seg >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize locals in non-script\n"); + VERIFY(!(seg >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize locals in non-script\n"); scr = &(mobj->data.script); scr->locals_offset = -count * 2; // Make sure it's invalid - _sm_alloc_locals_segment(self, scr, count); + allocLocalsSegment(scr, count); } -void sm_script_initialise_locals(SegManager *self, reg_t location) { - mem_obj_t *mobj = self->heap[location.segment]; +void SegManager::scriptInitialiseLocals(reg_t location) { + mem_obj_t *mobj = heap[location.segment]; unsigned int count; script_t *scr; local_variables_t *locals; - VERIFY(!(location.segment >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to initialize locals in non-script\n"); + 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"); - if (self->sci1_1) + if (isSci1_1) count = getUInt16(scr->buf + location.offset - 2); else count = (getUInt16(scr->buf + location.offset - 2) - 4) >> 1; @@ -1082,7 +1065,7 @@ void sm_script_initialise_locals(SegManager *self, reg_t location) { count = (scr->buf_size - location.offset) >> 1; } - locals = _sm_alloc_locals_segment(self, scr, count); + locals = allocLocalsSegment(scr, count); if (locals) { uint i; byte *base = (byte *)(scr->buf + location.offset); @@ -1092,13 +1075,13 @@ void sm_script_initialise_locals(SegManager *self, reg_t location) { } } -void sm_script_relocate_exports_sci11(SegManager *self, int seg) { - mem_obj_t *mobj = self->heap[seg]; +void SegManager::scriptRelocateExportsSci11(int seg) { + mem_obj_t *mobj = heap[seg]; script_t *scr; int i; int location; - VERIFY(!(seg >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to relocate exports in non-script\n"); + 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++) { @@ -1115,12 +1098,12 @@ void sm_script_relocate_exports_sci11(SegManager *self, int seg) { } } -void sm_script_initialise_objects_sci11(SegManager *self, EngineState *s, int seg) { - mem_obj_t *mobj = self->heap[seg]; +void SegManager::scriptInitialiseObjectsSci11(EngineState *s, int seg) { + mem_obj_t *mobj = heap[seg]; script_t *scr; byte *seeker; - VERIFY(!(seg >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to relocate exports in non-script\n"); + 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 + getUInt16(scr->heap_start + 2) * 2; @@ -1151,7 +1134,7 @@ void sm_script_initialise_objects_sci11(SegManager *self, EngineState *s, int se reg.segment = seg; reg.offset = seeker - scr->buf; - obj = sm_script_obj_init(&s->seg_manager, s, reg); + obj = scriptObjInit(s, reg); #if 0 if (obj->variables[5].offset != 0xffff) { @@ -1169,11 +1152,11 @@ void sm_script_initialise_objects_sci11(SegManager *self, EngineState *s, int se } } -void sm_script_free_unused_objects(SegManager *self, seg_id_t seg) { - mem_obj_t *mobj = self->heap[seg]; +void SegManager::scriptFreeUnusedObjects(seg_id_t seg) { + mem_obj_t *mobj = heap[seg]; script_t *scr; - VERIFY(!(seg >= self->heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to free unused objects in non-script\n"); + VERIFY(!(seg >= heap_size || mobj->type != MEM_OBJ_SCRIPT), "Attempt to free unused objects in non-script\n"); scr = &(mobj->data.script); if (scr->objects_allocated > scr->objects_nr) { @@ -1188,7 +1171,8 @@ void sm_script_free_unused_objects(SegManager *self, seg_id_t seg) { } } -static inline char *dynprintf(char *msg, ...) { +/* +static inline char *SegManager::dynprintf(char *msg, ...) { va_list argp; char *buf = (char *)sci_malloc(strlen(msg) + 100); @@ -1198,9 +1182,10 @@ static inline char *dynprintf(char *msg, ...) { return buf; } +*/ -dstack_t *sm_allocate_stack(SegManager *self, int size, seg_id_t *segid) { - mem_obj_t *memobj = alloc_nonscript_segment(self, MEM_OBJ_STACK, segid); +dstack_t *SegManager::allocateStack(int size, seg_id_t *segid) { + mem_obj_t *memobj = allocNonscriptSegment(MEM_OBJ_STACK, segid); dstack_t *retval = &(memobj->data.stack); retval->entries = (reg_t*)sci_calloc(size, sizeof(reg_t)); @@ -1209,8 +1194,8 @@ dstack_t *sm_allocate_stack(SegManager *self, int size, seg_id_t *segid) { return retval; } -sys_strings_t *sm_allocate_sys_strings(SegManager *self, seg_id_t *segid) { - mem_obj_t *memobj = alloc_nonscript_segment(self, MEM_OBJ_SYS_STRINGS, segid); +sys_strings_t *SegManager::allocateSysStrings(seg_id_t *segid) { + mem_obj_t *memobj = allocNonscriptSegment(MEM_OBJ_SYS_STRINGS, segid); sys_strings_t *retval = &(memobj->data.sys_strings); memset(retval, 0, sizeof(sys_string_t)*SYS_STRINGS_MAX); @@ -1218,29 +1203,32 @@ sys_strings_t *sm_allocate_sys_strings(SegManager *self, seg_id_t *segid) { return retval; } -seg_id_t sm_allocate_reserved_segment(SegManager *self, char *src_name) { +#if 0 +// Unreferenced - removed +seg_id_t SegManager::sm_allocate_reserved_segment(char *src_name) { seg_id_t segid; - mem_obj_t *memobj = alloc_nonscript_segment(self, MEM_OBJ_RESERVED, &segid); + mem_obj_t *memobj = allocNonscriptSegment(MEM_OBJ_RESERVED, &segid); char *name = sci_strdup(src_name); memobj->data.reserved = name; return segid; } +#endif -uint16 sm_validate_export_func(SegManager* self, int pubfunct, int seg) { +uint16 SegManager::validateExportFunc(int pubfunct, int seg) { script_t* script; uint16 offset; - VERIFY(sm_check(self, seg), "invalid seg id"); - VERIFY(self->heap[seg]->type == MEM_OBJ_SCRIPT, "Can only validate exports on scripts"); + VERIFY(check(seg), "invalid seg id"); + VERIFY(heap[seg]->type == MEM_OBJ_SCRIPT, "Can only validate exports on scripts"); - script = &self->heap[seg]->data.script; + script = &heap[seg]->data.script; if (script->exports_nr <= pubfunct) { sciprintf("pubfunct is invalid"); return 0; } - if (self->exports_wide) + if (exports_wide) pubfunct *= 2; offset = getUInt16((byte *)(script->export_table + pubfunct)); VERIFY(offset < script->buf_size, "invalid export function pointer"); @@ -1248,12 +1236,12 @@ uint16 sm_validate_export_func(SegManager* self, int pubfunct, int seg) { return offset; } -void sm_free_hunk_entry(SegManager *self, reg_t addr) { - sm_free_hunk(self, addr); +void SegManager::free_hunk_entry(reg_t addr) { + free_hunk(addr); } -hunk_t *sm_alloc_hunk_entry(SegManager *self, const char *hunk_type, int size, reg_t *reg) { - hunk_t *h = sm_alloc_hunk(self, reg); +hunk_t *SegManager::alloc_hunk_entry(const char *hunk_type, int size, reg_t *reg) { + hunk_t *h = alloc_hunk(reg); if (!h) return NULL; @@ -1265,12 +1253,12 @@ hunk_t *sm_alloc_hunk_entry(SegManager *self, const char *hunk_type, int size, r return h; } -static void _clone_cleanup(clone_t *clone) { +void _clone_cleanup(clone_t *clone) { if (clone->variables) free(clone->variables); // Free the dynamically allocated memory part } -static void _hunk_cleanup(hunk_t *hunk) { +void _hunk_cleanup(hunk_t *hunk) { if (hunk->mem) free(hunk->mem); } @@ -1280,53 +1268,53 @@ DEFINE_HEAPENTRY(node, 32, 16) DEFINE_HEAPENTRY_WITH_CLEANUP(clone, 16, 4, _clone_cleanup) DEFINE_HEAPENTRY_WITH_CLEANUP(hunk, 4, 4, _hunk_cleanup) -#define DEFINE_ALLOC_DEALLOC(STATIC, TYPE, SEGTYPE, PLURAL) \ -STATIC TYPE##_t *sm_alloc_##TYPE(SegManager *self, reg_t *addr) { \ +#define DEFINE_ALLOC_DEALLOC(TYPE, SEGTYPE, PLURAL) \ +TYPE##_t *SegManager::alloc_##TYPE(reg_t *addr) { \ mem_obj_t *mobj; \ TYPE##_table_t *table; \ int offset; \ \ - if (!self->TYPE##s_seg_id) { \ - mobj = alloc_nonscript_segment(self, SEGTYPE, &(self->TYPE##s_seg_id)); \ + if (!TYPE##s_seg_id) { \ + mobj = allocNonscriptSegment(SEGTYPE, &(TYPE##s_seg_id)); \ init_##TYPE##_table(&(mobj->data.PLURAL)); \ } else \ - mobj = self->heap[self->TYPE##s_seg_id]; \ + mobj = heap[TYPE##s_seg_id]; \ \ table = &(mobj->data.PLURAL); \ - offset = alloc_##TYPE##_entry(table); \ + offset = Sci::alloc_##TYPE##_entry(table); \ \ - *addr = make_reg(self->TYPE##s_seg_id, offset); \ + *addr = make_reg(TYPE##s_seg_id, offset); \ return &(mobj->data.PLURAL.table[offset].entry); \ } \ \ -STATIC void sm_free_##TYPE(SegManager *self, reg_t addr) { \ - mem_obj_t *mobj = GET_SEGMENT(*self, addr.segment, SEGTYPE); \ +void SegManager::free_##TYPE(reg_t addr) { \ + mem_obj_t *mobj = GET_SEGMENT(*this, addr.segment, SEGTYPE); \ \ if (!mobj) { \ sciprintf("Attempt to free " #TYPE " from address "PREG": Invalid segment type\n", PRINT_REG(addr)); \ return; \ } \ \ - free_##TYPE##_entry(&(mobj->data.PLURAL), addr.offset); \ + Sci::free_##TYPE##_entry(&(mobj->data.PLURAL), addr.offset); \ } -DEFINE_ALLOC_DEALLOC(, clone, MEM_OBJ_CLONES, clones) -DEFINE_ALLOC_DEALLOC(, list, MEM_OBJ_LISTS, lists) -DEFINE_ALLOC_DEALLOC(, node, MEM_OBJ_NODES, nodes) -DEFINE_ALLOC_DEALLOC(static, hunk, MEM_OBJ_HUNK, hunks) +DEFINE_ALLOC_DEALLOC(clone, MEM_OBJ_CLONES, clones) +DEFINE_ALLOC_DEALLOC(list, MEM_OBJ_LISTS, lists) +DEFINE_ALLOC_DEALLOC(node, MEM_OBJ_NODES, nodes) +DEFINE_ALLOC_DEALLOC(hunk, MEM_OBJ_HUNK, hunks) -byte *sm_dereference(SegManager *self, reg_t pointer, int *size) { +byte *SegManager::dereference(reg_t pointer, int *size) { mem_obj_t *mobj; byte *base = NULL; int count; - if (!pointer.segment || (pointer.segment >= self->heap_size) || !self->heap[pointer.segment]) { + if (!pointer.segment || (pointer.segment >= heap_size) || !heap[pointer.segment]) { sciprintf("Error: Attempt to dereference invalid pointer "PREG"!\n", PRINT_REG(pointer)); return NULL; /* Invalid */ } - mobj = self->heap[pointer.segment]; + mobj = heap[pointer.segment]; switch (mobj->type) { case MEM_OBJ_SCRIPT: @@ -1387,9 +1375,9 @@ byte *sm_dereference(SegManager *self, reg_t pointer, int *size) { base + pointer.offset; } -unsigned char *sm_alloc_dynmem(SegManager *self, int size, const char *descr, reg_t *addr) { +unsigned char *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) { seg_id_t seg; - mem_obj_t *mobj = alloc_nonscript_segment(self, MEM_OBJ_DYNMEM, &seg); + mem_obj_t *mobj = allocNonscriptSegment(MEM_OBJ_DYNMEM, &seg); *addr = make_reg(seg, 0); mobj->data.dynmem.size = size; @@ -1404,10 +1392,10 @@ unsigned char *sm_alloc_dynmem(SegManager *self, int size, const char *descr, re return (unsigned char *)(mobj->data.dynmem.buf); } -const char *sm_get_description(SegManager *self, reg_t addr) { - mem_obj_t *mobj = self->heap[addr.segment]; +const char *SegManager::getDescription(reg_t addr) { + mem_obj_t *mobj = heap[addr.segment]; - if (addr.segment >= self->heap_size) + if (addr.segment >= heap_size) return ""; switch (mobj->type) { @@ -1418,50 +1406,58 @@ const char *sm_get_description(SegManager *self, reg_t addr) { } } -int sm_free_dynmem(SegManager *self, reg_t addr) { - if (addr.segment <= 0 || addr.segment >= self->heap_size || !self->heap[addr.segment] || self->heap[addr.segment]->type != MEM_OBJ_DYNMEM) +int SegManager::freeDynmem(reg_t addr) { + if (addr.segment <= 0 || addr.segment >= heap_size || !heap[addr.segment] || heap[addr.segment]->type != MEM_OBJ_DYNMEM) return 1; // error - _sm_deallocate(self, addr.segment, 1); + deallocate(addr.segment, true); return 0; // OK } +void SegManager::dbgPrint(const char* msg, void *i) { +#ifdef DEBUG_SEG_MANAGER + char buf[1000]; + sprintf(buf, "%s = [0x%x], dec:[%d]", msg, i, i); + perror(buf); +#endif +} + // ------------------- Segment interface ------------------ -static void free_at_address_stub(seg_interface_t *self, reg_t sub_addr) { +static void free_at_address_stub(SegInterface *self, reg_t sub_addr) { //sciprintf(" Request to free "PREG"\n", PRINT_REG(sub_addr)); // STUB } -static reg_t find_canonic_address_base(seg_interface_t *self, reg_t addr) { +static reg_t find_canonic_address_base(SegInterface *self, reg_t addr) { addr.offset = 0; return addr; } -static reg_t find_canonic_address_id(seg_interface_t *self, reg_t addr) { +static reg_t find_canonic_address_id(SegInterface *self, reg_t addr) { return addr; } -static void free_at_address_nop(seg_interface_t *self, reg_t sub_addr) { +static void free_at_address_nop(SegInterface *self, reg_t sub_addr) { } -static void list_all_deallocatable_nop(seg_interface_t *self, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_deallocatable_nop(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) { } -static void list_all_deallocatable_base(seg_interface_t *self, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_deallocatable_base(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) { (*note)(param, make_reg(self->seg_id, 0)); } -static void list_all_outgoing_references_nop(seg_interface_t *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_outgoing_references_nop(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { } -static void deallocate_self(seg_interface_t *self) { +static void deallocate_self(SegInterface *self) { free(self); } -static void free_at_address_script(seg_interface_t *self, reg_t addr) { +static void free_at_address_script(SegInterface *self, reg_t addr) { script_t *script; VERIFY(self->mobj->type == MEM_OBJ_SCRIPT, "Trying to free a non-script!"); script = &(self->mobj->data.script); @@ -1472,10 +1468,10 @@ static void free_at_address_script(seg_interface_t *self, reg_t addr) { */ if (script->marked_as_deleted) - sm_deallocate_script(self->segmgr, script->nr); + self->segmgr->deallocateScript(script->nr); } -static void list_all_outgoing_references_script(seg_interface_t *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_outgoing_references_script(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { script_t *script = &(self->mobj->data.script); if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) { @@ -1500,7 +1496,7 @@ static void list_all_outgoing_references_script(seg_interface_t *self, EngineSta } //-------------------- script -------------------- -static seg_interface_t seg_interface_script = { +static SegInterface seg_interface_script = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1523,11 +1519,11 @@ static seg_interface_t seg_interface_script = { if (ENTRY_IS_VALID(table, i)) \ (*note) (param, make_reg(self->seg_id, i)); -static void list_all_deallocatable_clones(seg_interface_t *self, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_deallocatable_clones(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) { LIST_ALL_DEALLOCATABLE(clone, clones); } -static void list_all_outgoing_references_clones(seg_interface_t *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_outgoing_references_clones(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { mem_obj_t *mobj = self->mobj; clone_table_t *clone_table = &(mobj->data.clones); clone_t *clone; @@ -1552,7 +1548,7 @@ static void list_all_outgoing_references_clones(seg_interface_t *self, EngineSta //sciprintf("[GC] Reporting clone-pos "PREG"\n", PRINT_REG(clone->pos)); } -void free_at_address_clones(seg_interface_t *self, reg_t addr) { +void free_at_address_clones(SegInterface *self, reg_t addr) { object_t *victim_obj; assert(addr.segment == self->seg_id); @@ -1573,11 +1569,11 @@ void free_at_address_clones(seg_interface_t *self, reg_t addr) { */ free(victim_obj->variables); victim_obj->variables = NULL; - sm_free_clone(self->segmgr, addr); + self->segmgr->free_clone(addr); } //-------------------- clones -------------------- -static seg_interface_t seg_interface_clones = { +static SegInterface seg_interface_clones = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1590,17 +1586,17 @@ static seg_interface_t seg_interface_clones = { /* deallocate_self = */ deallocate_self }; -static reg_t find_canonic_address_locals(seg_interface_t *self, reg_t addr) { +static reg_t find_canonic_address_locals(SegInterface *self, reg_t addr) { local_variables_t *locals = &(self->mobj->data.locals); // Reference the owning script - seg_id_t owner_seg = sm_seg_get(self->segmgr, locals->script_id); + seg_id_t owner_seg = self->segmgr->segGet(locals->script_id); assert(owner_seg >= 0); return make_reg(owner_seg, 0); } -static void list_all_outgoing_references_locals(seg_interface_t *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_outgoing_references_locals(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { local_variables_t *locals = &(self->mobj->data.locals); int i; @@ -1611,7 +1607,7 @@ static void list_all_outgoing_references_locals(seg_interface_t *self, EngineSta } //-------------------- locals -------------------- -static seg_interface_t seg_interface_locals = { +static SegInterface seg_interface_locals = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1624,7 +1620,7 @@ static seg_interface_t seg_interface_locals = { /* deallocate_self = */ deallocate_self }; -static void list_all_outgoing_references_stack(seg_interface_t *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_outgoing_references_stack(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { int i; fprintf(stderr, "Emitting %d stack entries\n", self->mobj->data.stack.nr); for (i = 0; i < self->mobj->data.stack.nr; i++) @@ -1634,7 +1630,7 @@ static void list_all_outgoing_references_stack(seg_interface_t *self, EngineStat //-------------------- stack -------------------- -static seg_interface_t seg_interface_stack = { +static SegInterface seg_interface_stack = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1648,7 +1644,7 @@ static seg_interface_t seg_interface_stack = { }; //-------------------- system strings -------------------- -static seg_interface_t seg_interface_sys_strings = { +static SegInterface seg_interface_sys_strings = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1661,11 +1657,11 @@ static seg_interface_t seg_interface_sys_strings = { /* deallocate_self = */ deallocate_self }; -static void list_all_deallocatable_list(seg_interface_t *self, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_deallocatable_list(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) { LIST_ALL_DEALLOCATABLE(list, lists); } -static void list_all_outgoing_references_list(seg_interface_t *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_outgoing_references_list(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { list_table_t *table = &(self->mobj->data.lists); list_t *list = &(table->table[addr.offset].entry); @@ -1680,12 +1676,12 @@ static void list_all_outgoing_references_list(seg_interface_t *self, EngineState // let's be conservative here. } -static void free_at_address_lists(seg_interface_t *self, reg_t sub_addr) { - sm_free_list(self->segmgr, sub_addr); +static void free_at_address_lists(SegInterface *self, reg_t sub_addr) { + self->segmgr->free_list(sub_addr); } //-------------------- lists -------------------- -static seg_interface_t seg_interface_lists = { +static SegInterface seg_interface_lists = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1698,11 +1694,11 @@ static seg_interface_t seg_interface_lists = { /* deallocate_self = */ deallocate_self }; -static void list_all_deallocatable_nodes(seg_interface_t *self, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_deallocatable_nodes(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) { LIST_ALL_DEALLOCATABLE(node, nodes); } -static void list_all_outgoing_references_nodes(seg_interface_t *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_outgoing_references_nodes(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) { node_table_t *table = &(self->mobj->data.nodes); node_t *node = &(table->table[addr.offset].entry); @@ -1719,12 +1715,12 @@ static void list_all_outgoing_references_nodes(seg_interface_t *self, EngineStat note(param, node->value); } -static void free_at_address_nodes(seg_interface_t *self, reg_t sub_addr) { - sm_free_node(self->segmgr, sub_addr); +static void free_at_address_nodes(SegInterface *self, reg_t sub_addr) { + self->segmgr->free_node(sub_addr); } //-------------------- nodes -------------------- -static seg_interface_t seg_interface_nodes = { +static SegInterface seg_interface_nodes = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1737,12 +1733,12 @@ static seg_interface_t seg_interface_nodes = { /* deallocate_self = */ deallocate_self }; -static void list_all_deallocatable_hunk(seg_interface_t *self, void *param, void (*note)(void*param, reg_t addr)) { +static void list_all_deallocatable_hunk(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) { LIST_ALL_DEALLOCATABLE(hunk, hunks); } //-------------------- hunk -------------------- -static seg_interface_t seg_interface_hunk = { +static SegInterface seg_interface_hunk = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1756,7 +1752,7 @@ static seg_interface_t seg_interface_hunk = { }; //-------------------- dynamic memory -------------------- -static seg_interface_t seg_interface_dynmem = { +static SegInterface seg_interface_dynmem = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1770,7 +1766,7 @@ static seg_interface_t seg_interface_dynmem = { }; //-------------------- reserved -------------------- -static seg_interface_t seg_interface_reserved = { +static SegInterface seg_interface_reserved = { /* segmgr = */ NULL, /* mobj = */ NULL, /* seg_id = */ 0, @@ -1783,7 +1779,7 @@ static seg_interface_t seg_interface_reserved = { /* deallocate_self = */ deallocate_self }; -static seg_interface_t* seg_interfaces[MEM_OBJ_MAX] = { +static SegInterface* seg_interfaces[MEM_OBJ_MAX] = { &seg_interface_script, &seg_interface_clones, &seg_interface_locals, @@ -1796,22 +1792,22 @@ static seg_interface_t* seg_interfaces[MEM_OBJ_MAX] = { &seg_interface_reserved }; -seg_interface_t *get_seg_interface(SegManager *self, seg_id_t segid) { +SegInterface *SegManager::getSegInterface(seg_id_t segid) { mem_obj_t *mobj; - seg_interface_t *retval; + SegInterface *retval; - if (!sm_check(self, segid)) + if (!check(segid)) return NULL; // Invalid segment - mobj = self->heap[segid]; - retval = (seg_interface_t *)sci_malloc(sizeof(seg_interface_t)); - memcpy(retval, seg_interfaces[mobj->type - 1], sizeof(seg_interface_t)); + mobj = heap[segid]; + retval = (SegInterface *)sci_malloc(sizeof(SegInterface)); + memcpy(retval, seg_interfaces[mobj->type - 1], sizeof(SegInterface)); if (mobj->type != retval->type_id) { error("Improper segment interface for %d", mobj->type); } - retval->segmgr = self; + retval->segmgr = this; retval->mobj = mobj; retval->seg_id = segid; diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 54b6a5ce97..9adf332ea4 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -23,29 +23,21 @@ * */ - #ifndef _SCI_SEG_MANAGER_H #define _SCI_SEG_MANAGER_H #include "sci/engine/int_hashmap.h" -#include "sci/include/sys_strings.h" #include "sci/include/vm.h" namespace Sci { -#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 - // SCRIPT_ID must be 0 -typedef enum { +enum idFlag { SCRIPT_ID, SEG_ID -} id_flag; - -//void dbg_print( const char* msg, void *i ); // for debug only +}; -// verify the the given condition is true, output the message if condition is false, and exit +// 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 @@ -56,21 +48,6 @@ typedef enum { BREAKPOINT(); \ } -#define MEM_OBJ_INVALID 0 -#define MEM_OBJ_SCRIPT 1 -#define MEM_OBJ_CLONES 2 -#define MEM_OBJ_LOCALS 3 -#define MEM_OBJ_STACK 4 -#define MEM_OBJ_SYS_STRINGS 5 -#define MEM_OBJ_LISTS 6 -#define MEM_OBJ_NODES 7 -#define MEM_OBJ_HUNK 8 -#define MEM_OBJ_DYNMEM 9 -#define MEM_OBJ_RESERVED 10 -#define MEM_OBJ_MAX MEM_OBJ_RESERVED // For sanity checking - -typedef int mem_obj_enum; - #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 @@ -81,417 +58,432 @@ typedef int mem_obj_enum; (((mgr).heap[index] && ((mgr).heap[index]->type == MEM_OBJ_SCRIPT || (mgr).heap[index]->type == MEM_OBJ_CLONES))? (mgr).heap[index] \ : NULL): NULL -struct SegManager { - int_hash_map_t *id_seg_map; // id - script id; seg - index of heap - mem_obj_t **heap; - int heap_size; // size of the heap - int reserved_id; - int exports_wide; - int sci1_1; - - int gc_mark_bits; - // 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 - - seg_id_t clones_seg_id; // ID of the (a) clones segment - seg_id_t lists_seg_id; // ID of the (a) list segment - seg_id_t nodes_seg_id; // ID of the (a) node segment - seg_id_t hunks_seg_id; // ID of the (a) hunk segment -}; - -// Toplevel functionality - -void sm_init(SegManager *self, int sci1_1); -// Initialize the segment manager - -void sm_destroy(SegManager *self); -// Deallocate all memory associated with the segment manager - -void sm_gc(SegManager *self, EngineState *s); -// Perform garbage collection -// Parameters: (state_t *) s: The state to operate on -// Effects : Unreachable objects in 's' are deallocated - -// 1. Scripts - -void sm_free_script(mem_obj_t* mem); - -mem_obj_t *sm_allocate_script(SegManager* self, EngineState *s, int script_nr, int* seg_id); -// 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 - -// The script must then be initialised; see section (1b.), below. - -int sm_deallocate_script(SegManager* self, int script_nr); -// Forcefully deallocate a previously allocated script -// Parameters: (int) script_nr: number of the script to deallocate -// Returns : (int) 1 on success, 0 on failure - -int sm_script_is_loaded(SegManager* self, int id, id_flag flag); -// Determines whether a script has been loaded yet -// Parameters: (int) id: number of the script or ID of the script segment to check for -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, -// but less convenient. - -uint16 sm_validate_export_func(SegManager* self, int pubfunct, int seg); -// Validate whether the specified public function is exported by the script in the specified segment -// Parameters: (int) pubfunct: Index of the function to validate -// (int) seg: Segment ID of the script the check is to be performed for -// Returns : (uint16) 0 if the public function is invalid, its offset into the script's segment -// otherwise - -int sm_seg_get(SegManager* self, int script_nr); -// Get the segment ID associated with a script number -// Parameters: (int) script_nr: Number of the script to look up -// Returns : (int) The associated segment ID, or -1 if no matching segment exists -// This function is "pure" (i.e, it doesn't modify anything). - - - -// script lock operations - -void sm_increment_lockers(SegManager *self, int id, id_flag flag); -// Increments the number of lockers of the script in question by one -// Parameters: (int) id: ID of the script or script segment to modify -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, -// but less convenient. - - -void sm_decrement_lockers(SegManager *self, int id, id_flag flag); -// Decrements the number of lockers of the script in question by one -// Parameters: (int) id: ID of the script or script segment to modify -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, -// but less convenient. - -int sm_get_lockers(SegManager *self, int id, id_flag flag); -// Retrieves the number of locks held on this script -// Parameters: (int) id: ID of the script or script segment to read from -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, -// but less convenient. -// Returns : (int) The number of locks held on the previously identified script - - -void sm_set_lockers(SegManager *self, int lockers, int id, id_flag flag); -// Sets the number of locks held on the specified script -// Parameters: (int) id: ID of the script or script segment to modify -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, -// but less convenient. - - -byte *sm_get_synonyms(SegManager *self, int id, id_flag flag); -// Retrieves a pointer to the synonyms associated with the specified script -// Parameters: (int) id: ID of the script or script segment to read from -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, -// but less convenient. -// Returns : (byte *) Pointer to the synonyms, in non-parsed format. -// A dynamic failure is issued if the specified ID does not reference a proper script. - - -int sm_get_synonyms_nr(SegManager *self, int id, id_flag flag); -// Retrieves the number of synonyms associated with the specified script -// Parameters: (int) id: ID of the script or script segment to read from -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, -// but less convenient. -// Returns : (int) The number of synonyms associated with the specified script -// A dynamic failure is issued if the specified ID does not reference a proper script. - - - -// 1b. Script Initialisation - -// The set of functions below are intended -// to be used during script instantiation, -// i.e. loading and linking. - -void sm_script_initialise_locals_zero(SegManager *self, seg_id_t seg, int nr); -// Initializes a script's local variable block -// Parameters: (seg_id_t) seg: Segment containing the script to initialize -// (int) nr: Number of local variables to allocate -// All variables are initialized to zero. - - -void sm_script_initialise_locals(SegManager *self, reg_t location); -// Initializes a script's local variable block according to a prototype -// Parameters: (reg_t) location: Location to initialize from - +struct SegInterface; + +class SegManager { +public: + // Initialize the segment manager + SegManager(bool sci1_1); + + // Deallocate all memory associated with the segment manager + ~SegManager(); + + // 1. Scripts + + void freeScript(mem_obj_t* mem); + + // 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 + mem_obj_t *allocateScript(EngineState *s, int script_nr, int* seg_id); + + // The script must then be initialised; see section (1b.), below. + + // Forcefully deallocate a previously allocated script + // Parameters: (int) script_nr: number of the script to deallocate + // Returns : (int) 1 on success, 0 on failure + int deallocateScript(int script_nr); + + // Determines whether a script has been loaded yet + // Parameters: (int) id: number of the script or ID of the script segment to check for + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, + // but less convenient. + int scriptIsLoaded(int id, idFlag flag); + + // Validate whether the specified public function is exported by the script in the specified segment + // Parameters: (int) pubfunct: Index of the function to validate + // (int) seg: Segment ID of the script the check is to be performed for + // Returns : (uint16) 0 if the public function is invalid, its offset into the script's segment + // otherwise + uint16 validateExportFunc(int pubfunct, int seg); + + // Get the segment ID associated with a script number + // Parameters: (int) script_nr: Number of the script to look up + // Returns : (int) The associated segment ID, or -1 if no matching segment exists + // This function is "pure" (i.e, it doesn't modify anything). + int segGet(int script_nr); + + + // script lock operations + + // Increments the number of lockers of the script in question by one + // Parameters: (int) id: ID of the script or script segment to modify + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, + // but less convenient. + void incrementLockers(int id, idFlag flag); + + // Decrements the number of lockers of the script in question by one + // Parameters: (int) id: ID of the script or script segment to modify + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, + // but less convenient. + void decrementLockers(int id, idFlag flag); + + // Retrieves the number of locks held on this script + // Parameters: (int) id: ID of the script or script segment to read from + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, + // but less convenient. + // Returns : (int) The number of locks held on the previously identified script + int getLockers(int id, idFlag flag); + + // Sets the number of locks held on the specified script + // Parameters: (int) id: ID of the script or script segment to modify + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, + // but less convenient. + void setLockers(int lockers, int id, idFlag flag); + + // Retrieves a pointer to the synonyms associated with the specified script + // Parameters: (int) id: ID of the script or script segment to read from + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, + // but less convenient. + // Returns : (byte *) Pointer to the synonyms, in non-parsed format. + // A dynamic failure is issued if the specified ID does not reference a proper script. + byte *getSynonyms(int id, idFlag flag); + + // Retrieves the number of synonyms associated with the specified script + // Parameters: (int) id: ID of the script or script segment to read from + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // by its segment (SEG_ID). SEG_ID is faster than SCRIPT_ID, + // but less convenient. + // Returns : (int) The number of synonyms associated with the specified script + // A dynamic failure is issued if the specified ID does not reference a proper script. + int getSynonymsNr(int id, idFlag flag); + + + // 1b. Script Initialisation + + // The set of functions below are intended + // to be used during script instantiation, + // i.e. loading and linking. + + // Initializes a script's local variable block + // Parameters: (seg_id_t) seg: Segment containing the script to initialize + // (int) nr: Number of local variables to allocate + // All variables are initialized to zero. + void scriptInitialiseLocalsZero(seg_id_t seg, int nr); + + // Initializes a script's local variable block according to a prototype + // Parameters: (reg_t) location: Location to initialize from + void scriptInitialiseLocals(reg_t location); + + // Initializes an object within the segment manager + // Parameters: (reg_t) obj_pos: Location (segment, offset) of the object + // Returns : (object_t *) A newly created object_t describing the object + // obj_pos must point to the beginning of the script/class block (as opposed + // to what the VM considers to be the object location) + // The corresponding object_t is stored within the relevant script. + object_t *scriptObjInit(EngineState *s, reg_t obj_pos); + + // Informs the segment manager that a code block must be relocated + // Parameters: (reg_t) location: Start of block to relocate + void scriptAddCodeBlock(reg_t location); + + // Tells the segment manager whether exports are wide (32-bit) or not. + // Parameters: (int) flag: 1 if exports are wide, 0 otherwise + void setExportWidth(int flag); + + // Processes a relocation block witin a script + // Parameters: (reg_t) obj_pos: Location (segment, offset) of the block + // Returns : (object_t *) Location of the relocation block + // This function is idempotent, but it must only be called after all + // objects have been instantiated, or a run-time error will occur. + void scriptRelocate(reg_t block); + + // Deallocates all unused but allocated entries for objects + // Parameters: (seg_id_t) segid: segment of the script to prune in this way + // These entries are created during script instantiation; deallocating them + // frees up some additional memory. + void scriptFreeUnusedObjects(seg_id_t segid); + + // Sets the script-relative offset of the exports table + // Parameters: (int) offset: The script-relative exports table offset + // (int) id: ID of the script or script segment to write to + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // 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 setExportTableOffset(int offset, int id, idFlag flag); + + // Sets the script-relative offset of the synonyms associated with the specified script + // Parameters: (int) offset: The script-relative offset of the synonyms block + // (int) id: ID of the script or script segment to write to + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // 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 setSynonymsOffset(int offset, int id, idFlag flag); + + // Sets the number of synonyms associated with the specified script + // Parameters: (int) nr: The number of synonyms, as to be stored within the script + // (int) id: ID of the script or script segment to write to + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // 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 setSynonymsNr(int nr, int id, idFlag flag); + + // Marks the script identified by its script number as deleted + // Parameters: (int) script_nr: Script number to mark as deleted + // This will not actually delete the script. If references remain present on the + // heap or the stack, the script will stay in memory in a quasi-deleted state until + // either unreachable (resulting in its eventual deletion) or reloaded (resulting + // in its data being updated). + void markScriptDeleted(int script_nr); + + // Marks the script identified by its script number as not deleted + // Parameters: (int) script_nr: Script number to mark as not deleted + void unmarkScriptDeleted(int script_nr); + + // Determines whether the script referenced by the indicated segment is marked as being deleted. + // Parameters: (seg_id_t) Segment ID of the script to investigate + // Returns : (int) 1 iff seg points to a script and the segment is deleted, 0 otherwise + // Will return 0 when applied to an invalid or non-script seg. + int scriptIsMarkedAsDeleted(seg_id_t seg); + + + // 2. Clones + + // Allocate a fresh clone + // Returns : (clone_t*): Reference to the memory allocated for the clone + // (reg_t) *addr: The offset of the freshly allocated clone + clone_t *alloc_clone(reg_t *addr); + + // Deallocates a clone + // Parameters: (reg_t) addr: Offset of the clone scheduled for termination + void free_clone(reg_t addr); + + + // 3. Objects (static, from Scripts, and dynmic, from Clones) + + // Not all of these functions are fully operational for clones ATM + + // Retrieves a 16 bit value from within a script's heap representation + // Parameters: (reg_t) reg: The address to read from + // Returns : (int16) The value read from the specified location + int16 getHeap(reg_t reg); + + // Writes a 16 bit value into a script's heap representation + // Parameters: (reg_t) reg: The address to write to + // (int16) value: The value to write + //void putHeap(reg_t reg, int16 value); + + // Copies a byte string into a script's heap representation + // Parameters: (int) dst: The script-relative offset of the destination area + // (const void *) src: Pointer to the data source location + // (size_t) n: Number of bytes to copy + // (int) id: ID of the script or script segment to write to + // (idFlag) flag: Whether to address the script by script number (SCRIPT_ID) or + // 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); + + + // 4. Stack + + // Allocates a data stack + // Parameters: (int) size: Number of stack entries to reserve + // Returns : (dstack_t *): The physical stack + // (seg_id_t) segid: Segment ID of the stack + dstack_t *allocateStack(int size, seg_id_t *segid); + + + // 5. System Strings + + // Allocates a system string table + // Returns : (dstack_t *): The physical stack + // (seg_id_t) segid: Segment ID of the stack + // See also sys_string_acquire(); + sys_strings_t *allocateSysStrings(seg_id_t *segid); + + + // 6, 7. Lists and Nodes -object_t *sm_script_obj_init(SegManager *self, EngineState *s, reg_t obj_pos); -// Initializes an object within the segment manager -// Parameters: (reg_t) obj_pos: Location (segment, offset) of the object -// Returns : (object_t *) A newly created object_t describing the object -// obj_pos must point to the beginning of the script/class block (as opposed -// to what the VM considers to be the object location) -// The corresponding object_t is stored within the relevant script. + // Allocate a fresh list + // Returns : (listY_t*): Reference to the memory allocated for the list + // (reg_t) *addr: The offset of the freshly allocated list + list_t *alloc_list(reg_t *addr); + // Deallocates a list + // Parameters: (reg_t) addr: Offset of the list scheduled for termination + void free_list(reg_t addr); -void sm_script_add_code_block(SegManager *self, reg_t location); -// Informs the segment manager that a code block must be relocated -// Parameters: (reg_t) location: Start of block to relocate + // Allocate a fresh node + // Returns : (node_t*): Reference to the memory allocated for the node + // (reg_t) *addr: The offset of the freshly allocated node + node_t *alloc_node(reg_t *addr); + // Deallocates a list node + // Parameters: (reg_t) addr: Offset of the node scheduled for termination + void free_node(reg_t addr); -void sm_set_export_width(SegManager *self, int flag); -// Tells the segment manager whether exports are wide (32-bit) or not. -// Parameters: (int) flag: 1 if exports are wide, 0 otherwise -void sm_script_relocate(SegManager *self, reg_t block); -// Processes a relocation block witin a script -// Parameters: (reg_t) obj_pos: Location (segment, offset) of the block -// Returns : (object_t *) Location of the relocation block -// This function is idempotent, but it must only be called after all -// objects have been instantiated, or a run-time error will occur. + // 8. Hunk Memory + // Allocate a fresh chunk of the hunk + // Parameters: (int) size: Number of bytes to allocate for the hunk entry + // (const char *) hunk_type: A descriptive string for the hunk entry, + // for debugging purposes + // Returns : (hunk_t*): Reference to the memory allocated for the hunk piece + // (reg_t) *addr: The offset of the freshly allocated hunk entry + hunk_t *alloc_hunk_entry(const char *hunk_type, int size, reg_t *addr); -void sm_script_free_unused_objects(SegManager *self, seg_id_t segid); -// Deallocates all unused but allocated entries for objects -// Parameters: (seg_id_t) segid: segment of the script to prune in this way -// These entries are created during script instantiation; deallocating them -// frees up some additional memory. + // Deallocates a hunk entry + // Parameters: (reg_t) addr: Offset of the hunk entry to delete + void free_hunk_entry(reg_t addr); + // 9. Dynamic Memory -void sm_set_export_table_offset(SegManager *self, int offset, int id, id_flag flag); -// Sets the script-relative offset of the exports table -// Parameters: (int) offset: The script-relative exports table offset -// (int) id: ID of the script or script segment to write to -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// 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. + // Allocate some dynamic memory + // Parameters: (int) size: Number of bytes to allocate + // (const char_ *) description: A descriptive string, + // for debugging purposes + // Returns : (unsigned char*): Raw pointer into the allocated dynamic memory + // (reg_t) *addr: The offset of the freshly allocated X + unsigned char *allocDynmem(int size, const char *description, reg_t *addr); + // Deallocates a piece of dynamic memory + // Parameters: (reg_t) addr: Offset of the dynmem chunk to free + int freeDynmem(reg_t addr); -void sm_set_synonyms_offset(SegManager *self, int offset, int id, id_flag flag); -// Sets the script-relative offset of the synonyms associated with the specified script -// Parameters: (int) offset: The script-relative offset of the synonyms block -// (int) id: ID of the script or script segment to write to -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// 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. + // Gets the description of a dynmem segment + // Parameters: (reg_t) addr: Segment to describe + // Returns : (const char *): Pointer to the descriptive string set in + // allocDynmem + const char *getDescription(reg_t addr); -void sm_set_synonyms_nr(SegManager *self, int nr, int id, id_flag flag); -// Sets the number of synonyms associated with the specified script -// Parameters: (int) nr: The number of synonyms, as to be stored within the script -// (int) id: ID of the script or script segment to write to -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// 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. + // 10. Reserved segments + // Reserves a special-purpose segment + // Parameters: (char *) name: A string name identifying the segment (the string is cloned and retained) + // Returns : A fresh segment ID for the segment in question + // Reserved segments are never used by the segment manager. They can be used to tag special-purpose addresses. + // Segment 0 is implicitly reserved for numbers. + //seg_id_t sm_allocate_reserved_segment(char *name); -void sm_mark_script_deleted(SegManager *self, int script_nr); -// Marks the script identified by its script number as deleted -// Parameters: (int) script_nr: Script number to mark as deleted -// This will not actually delete the script. If references remain present on the -// heap or the stack, the script will stay in memory in a quasi-deleted state until -// either unreachable (resulting in its eventual deletion) or reloaded (resulting -// in its data being updated). + // Generic Operations on Segments and Addresses -void sm_unmark_script_deleted(SegManager *self, int script_nr); -// Marks the script identified by its script number as not deleted -// Parameters: (int) script_nr: Script number to mark as not deleted + // Dereferences a raw memory pointer + // Parameters: (reg_t) reg: The reference to dereference + // Returns : (byte *) The data block referenced + // (int) size: (optionally) the theoretical maximum size of it + byte *dereference(reg_t reg, int *size); -int sm_script_is_marked_as_deleted(SegManager *self, seg_id_t seg); -// Determines whether the script referenced by the indicated segment is marked as being deleted. -// Parameters: (seg_id_t) Segment ID of the script to investigate -// Returns : (int) 1 iff seg points to a script and the segment is deleted, 0 otherwise -// Will return 0 when applied to an invalid or non-script seg. + // Segment Interface + // Retrieves the segment interface to the specified segment + // Parameters: (seg_id_t) segid: ID of the segment to look up + // Returns : (SegInterface *): An interface to the specified segment ID, or NULL on error + // The returned interface 'si' must be freed after use by calling 'si->dealloc_self(si)'; + SegInterface *getSegInterface(seg_id_t segid); -// 2. Clones -clone_t *sm_alloc_clone(SegManager *self, reg_t *addr); -// Allocate a fresh clone -// Returns : (clone_t*): Reference to the memory allocated for the clone -// (reg_t) *addr: The offset of the freshly allocated clone + void heapRelocate(EngineState *s, reg_t block); + void scriptRelocateExportsSci11(int seg); + void scriptInitialiseObjectsSci11(EngineState *s, int seg); + int scriptMarkedDeleted(int script_nr); + int initialiseScript(mem_obj_t *mem, EngineState *s, int script_nr); +public: // TODO: make private + int_hash_map_t *id_seg_map; // id - script id; seg - index of heap + mem_obj_t **heap; + int heap_size; // size of the heap + int reserved_id; + int exports_wide; + bool isSci1_1; -void sm_free_clone(SegManager *self, reg_t addr); -// Deallocates a clone -// Parameters: (reg_t) addr: Offset of the clone scheduled for termination - - -// Objects (static, from Scripts, and dynmic, from Clones) - -// Not all of these functions are fully operational for clones ATM - -int16 sm_get_heap(SegManager* self, reg_t reg); -// Retrieves a 16 bit value from within a script's heap representation -// Parameters: (reg_t) reg: The address to read from -// Returns : (int16) The value read from the specified location - - -void sm_put_heap(SegManager *self, reg_t reg, int16 value); -// Writes a 16 bit value into a script's heap representation -// Parameters: (reg_t) reg: The address to write to -// (int16) value: The value to write - - -void sm_mcpy_in_out(SegManager* self, int dst, const void *src, size_t n, int id, int flag); -// Copies a byte string into a script's heap representation -// Parameters: (int) dst: The script-relative offset of the destination area -// (const void *) src: Pointer to the data source location -// (size_t) n: Number of bytes to copy -// (int) id: ID of the script or script segment to write to -// (id_flag) flag: Whether to address the script by script number (SCRIPT_ID) or -// 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. - - -// 4. Stack - -dstack_t *sm_allocate_stack(SegManager *self, int size, seg_id_t *segid); -// Allocates a data stack -// Parameters: (int) size: Number of stack entries to reserve -// Returns : (dstack_t *): The physical stack -// (seg_id_t) segid: Segment ID of the stack - - -// 5. System Strings - -sys_strings_t *sm_allocate_sys_strings(SegManager *self, seg_id_t *segid); -// Allocates a system string table -// Returns : (dstack_t *): The physical stack -// (seg_id_t) segid: Segment ID of the stack -// See also sys_string_acquire(); - - -// 6, 7. Lists and Nodes - -list_t *sm_alloc_list(SegManager *self, reg_t *addr); -// Allocate a fresh list -// Returns : (listY_t*): Reference to the memory allocated for the list -// (reg_t) *addr: The offset of the freshly allocated list - - -void sm_free_list(SegManager *self, reg_t addr); -// Deallocates a list -// Parameters: (reg_t) addr: Offset of the list scheduled for termination - - -node_t *sm_alloc_node(SegManager *self, reg_t *addr); -// Allocate a fresh node -// Returns : (node_t*): Reference to the memory allocated for the node -// (reg_t) *addr: The offset of the freshly allocated node - -void sm_free_node(SegManager *self, reg_t addr); -// Deallocates a list node -// Parameters: (reg_t) addr: Offset of the node scheduled for termination - - -// 8. Hunk Memory - -hunk_t *sm_alloc_hunk_entry(SegManager *self, const char *hunk_type, int size, reg_t *addr); -// Allocate a fresh chunk of the hunk -// Parameters: (int) size: Number of bytes to allocate for the hunk entry -// (const char *) hunk_type: A descriptive string for the hunk entry, -// for debugging purposes -// Returns : (hunk_t*): Reference to the memory allocated for the hunk piece -// (reg_t) *addr: The offset of the freshly allocated hunk entry - - -void sm_free_hunk_entry(SegManager *self, reg_t addr); -// Deallocates a hunk eentry -// Parameters: (reg_t) addr: Offset of the hunk entry to delete - - -// 9. Dynamic Memory - -unsigned char *sm_alloc_dynmem(SegManager *self, int size, const char *description, reg_t *addr); -// Allocate some dynamic memory -// Parameters: (int) size: Number of bytes to allocate -// (const char_ *) description: A descriptive string, -// for debugging purposes -// Returns : (unsigned char*): Raw pointer into the allocated dynamic memory -// (reg_t) *addr: The offset of the freshly allocated X - -int sm_free_dynmem(SegManager *self, reg_t addr); -// Deallocates a piece of dynamic memory -// Parameters: (reg_t) addr: Offset of the dynmem chunk to free - - -const char *sm_get_description(SegManager *self, reg_t addr); -// Gets the description of a dynmem segment -// Parameters: (reg_t) addr: Segment to describe -// Returns : (const char *): Pointer to the descriptive string set in -// sm_alloc_dynmem - - -// 10. Reserved segments - -seg_id_t sm_allocate_reserved_segment(SegManager *self, char *name); -// Reserves a special-purpose segment -// Parameters: (char *) name: A string name identifying the segment (the string is cloned and retained) -// Returns : A fresh segment ID for the segment in question -// Reserved segments are never used by the segment manager. They can be used to tag special-purpose addresses. -// Segment 0 is implicitly reserved for numbers. + int gc_mark_bits; + // 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 + seg_id_t clones_seg_id; // ID of the (a) clones segment + seg_id_t lists_seg_id; // ID of the (a) list segment + seg_id_t nodes_seg_id; // ID of the (a) node segment + seg_id_t hunks_seg_id; // ID of the (a) hunk segment -// Generic Operations on Segments and Addresses +private: + mem_obj_t *allocNonscriptSegment(memObjType type, seg_id_t *segid); + local_variables_t *allocLocalsSegment(script_t *scr, int count); + mem_obj_t *memObjAllocate(seg_id_t segid, int hash_id, memObjType type); + int deallocate(int seg, bool recursive); + + hunk_t *alloc_hunk(reg_t *); + void free_hunk(reg_t addr); + + inline int relocateLocal(script_t *scr, seg_id_t segment, int location); + inline int relocateBlock(reg_t *block, int block_location, int block_items, seg_id_t segment, int location); + inline int relocateObject(object_t *obj, seg_id_t segment, int location); + + inline int findFreeId(int *id); + static void setScriptSize(mem_obj_t *mem, EngineState *s, int script_nr); + object_t *scriptObjInit0(EngineState *s, reg_t obj_pos); + object_t *scriptObjInit11(EngineState *s, reg_t obj_pos); + + /* Check segment validity + ** Parameters: (int) seg: The segment to validate + ** Returns : (bool) false if 'seg' is an invalid segment + ** true if 'seg' is a valid segment + */ + bool check(int seg); + + void dbgPrint(const char* msg, void *i); // for debug only + + // Perform garbage collection + // Parameters: (EngineState *) s: The state to operate on + // Effects : Unreachable objects in 's' are deallocated + //void sm_gc(EngineState *s); +}; -byte *sm_dereference(SegManager *self, reg_t reg, int *size); -// Dereferences a raw memory pointer -// Parameters: (reg_t) reg: The reference to dereference -// Returns : (byte *) The data block referenced -// (int) size: (optionally) the theoretical maximum size of it // 11. Segment interface, primarily for GC -struct seg_interface_t { +struct SegInterface { SegManager *segmgr; mem_obj_t *mobj; seg_id_t seg_id; - mem_obj_enum type_id; // Segment type + memObjType type_id; // Segment type const char *type; // String description of the segment type - reg_t (*find_canonic_address)(seg_interface_t *self, reg_t sub_addr); + reg_t (*find_canonic_address)(SegInterface *self, reg_t sub_addr); // Finds the canonic address associated with sub_reg // Parameters: (reg_t) sub_addr: The base address whose canonic address is to be found // For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)). // This address "governs" a in the sense that deallocating c(a) will deallocate a. - void (*free_at_address)(seg_interface_t *self, reg_t sub_addr); + void (*free_at_address)(SegInterface *self, reg_t sub_addr); // Deallocates all memory associated with the specified address // Parameters: (reg_t) sub_addr: The address (within the given segment) to deallocate - void (*list_all_deallocatable)(seg_interface_t *self, void *param, void (*note)(void *param, reg_t addr)); + void (*list_all_deallocatable)(SegInterface *self, void *param, void (*note)(void *param, reg_t addr)); // Iterates over and reports all addresses within the current segment // Parameters: note : (voidptr * addr) -> (): Invoked for each address on which free_at_address() // makes sense // (void *) param: Parameter passed to 'note' - void (*list_all_outgoing_references)(seg_interface_t *self, EngineState *s, reg_t object, void *param, void (*note)(void *param, reg_t addr)); + void (*list_all_outgoing_references)(SegInterface *self, EngineState *s, reg_t object, void *param, void (*note)(void *param, reg_t addr)); // Iterates over all references reachable from the specified object // Parameters: (reg_t) object: The object (within the current segment) to analyse // (void *) param: Parameter passed to 'note' // note : (voidptr * addr) -> (): Invoked for each outgoing reference within the object // Note: This function may also choose to report numbers (segment 0) as adresses - void (*deallocate_self)(seg_interface_t *self); + void (*deallocate_self)(SegInterface *self); // Deallocates the segment interface }; -seg_interface_t *get_seg_interface(SegManager *self, seg_id_t segid); -// Retrieves the segment interface to the specified segment -// Parameters: (seg_id_t) segid: ID of the segment to look up -// Returns : (seg_interface_t *): An interface to the specified segment ID, or NULL on error -// The returned interface 'si' must be freed after use by calling 'si->dealloc_self(si)'; - } // End of namespace Sci #endif diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3c5b1f5393..ef57b73214 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -221,7 +221,7 @@ reg_t get_class_address(EngineState *s, int classnr, int lock, reg_t caller) { } } else if (caller.segment != the_class->reg.segment) - sm_increment_lockers(&s->seg_manager, the_class->reg.segment, SEG_ID); + s->seg_manager->incrementLockers(the_class->reg.segment, SEG_ID); return the_class->reg; } @@ -243,7 +243,7 @@ reg_t get_class_address(EngineState *s, int classnr, int lock, reg_t caller) { #define GET_OP_SIGNED_WORD() ((getInt16(code_buf + ((xs->addr.pc.offset) += 2) - 2))) #define GET_OP_SIGNED_FLEX() ((opcode & 1)? GET_OP_SIGNED_BYTE() : GET_OP_SIGNED_WORD()) -#define SEG_GET_HEAP(s, reg) sm_get_heap(&s->seg_manager, reg) +#define SEG_GET_HEAP(s, reg) s->seg_manager->getHeap(reg) #define OBJ_SPECIES(s, reg) SEG_GET_HEAP(s, make_reg(reg.segment, reg.offset + SCRIPT_SPECIES_OFFSET)) // Returns an object's species @@ -254,14 +254,14 @@ inline exec_stack_t *execute_method(EngineState *s, uint16 script, uint16 pubfun int seg; uint16 temp; - if (!sm_script_is_loaded(&s->seg_manager, script, SCRIPT_ID)) // Script not present yet? + if (!s->seg_manager->scriptIsLoaded(script, SCRIPT_ID)) // Script not present yet? script_instantiate(s, script); else - sm_unmark_script_deleted(&s->seg_manager, script); + s->seg_manager->unmarkScriptDeleted(script); - seg = sm_seg_get(&s->seg_manager, script); + seg = s->seg_manager->segGet(script); - temp = sm_validate_export_func(&s->seg_manager, pubfunct, seg); + 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); @@ -533,7 +533,7 @@ void vm_handle_fatal_error(EngineState *s, int line, const char *file) { } static inline script_t *script_locate_by_segment(EngineState *s, seg_id_t seg) { - mem_obj_t *memobj = GET_SEGMENT(s->seg_manager, seg, MEM_OBJ_SCRIPT); + mem_obj_t *memobj = GET_SEGMENT(*s->seg_manager, seg, MEM_OBJ_SCRIPT); if (memobj) return &(memobj->data.script); @@ -541,7 +541,7 @@ static inline script_t *script_locate_by_segment(EngineState *s, seg_id_t seg) { } static reg_t pointer_add(EngineState *s, reg_t base, int offset) { - mem_obj_t *mobj = GET_SEGMENT_ANY(s->seg_manager, base.segment); + mem_obj_t *mobj = GET_SEGMENT_ANY(*s->seg_manager, base.segment); if (!mobj) { script_debug_flag = script_error_flag = 1; @@ -1617,11 +1617,11 @@ seg_id_t script_get_segment(EngineState *s, int script_nr, int load) { if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD) script_instantiate(s, script_nr); - segment = sm_seg_get(&s->seg_manager, script_nr); + segment = s->seg_manager->segGet(script_nr); if (segment > 0) { if ((load & SCRIPT_GET_LOCK) == SCRIPT_GET_LOCK) - sm_increment_lockers(&s->seg_manager, segment, SEG_ID); + s->seg_manager->incrementLockers(segment, SEG_ID); return segment; } else @@ -1642,7 +1642,7 @@ reg_t script_lookup_export(EngineState *s, int script_nr, int export_index) { } #endif - memobj = GET_SEGMENT(s->seg_manager, seg, MEM_OBJ_SCRIPT); + memobj = GET_SEGMENT(*s->seg_manager, seg, MEM_OBJ_SCRIPT); if (memobj) script = &(memobj->data.script); @@ -1668,8 +1668,6 @@ reg_t script_lookup_export(EngineState *s, int script_nr, int export_index) { #define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : get_class_address(s, id, SCRIPT_GET_LOCK, reg)) -int sm_script_marked_deleted(SegManager* self, int script_nr); -int sm_initialise_script(mem_obj_t *mem, EngineState *s, int script_nr); int script_instantiate_common(EngineState *s, int script_nr, resource_t **script, resource_t **heap, int *was_new) { int seg; int seg_id; @@ -1700,33 +1698,33 @@ int script_instantiate_common(EngineState *s, int script_nr, resource_t **script return 0; } - seg = sm_seg_get(&s->seg_manager, script_nr); - if (sm_script_is_loaded(&s->seg_manager, script_nr, SCRIPT_ID)) { - marked_for_deletion = sm_script_marked_deleted(&s->seg_manager, script_nr); + 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); if (!marked_for_deletion) { - sm_increment_lockers(&s->seg_manager, seg, SEG_ID); + s->seg_manager->incrementLockers(seg, SEG_ID); return seg; } else { seg_id = seg; - mem = s->seg_manager.heap[seg]; - sm_free_script(mem); + mem = s->seg_manager->heap[seg]; + s->seg_manager->freeScript(mem); } - } else if (!(mem = sm_allocate_script(&s->seg_manager, s, script_nr, &seg_id))) { // ALL YOUR SCRIPT BASE ARE BELONG TO US + } else if (!(mem = 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; } - sm_initialise_script(mem, s, script_nr); + s->seg_manager->initialiseScript(mem, s, script_nr); reg.segment = seg_id; reg.offset = 0; // Set heap position (beyond the size word) - sm_set_lockers(&s->seg_manager, 1, reg.segment, SEG_ID); - sm_set_export_table_offset(&s->seg_manager, 0, reg.segment, SEG_ID); - sm_set_synonyms_offset(&s->seg_manager, 0, reg.segment, SEG_ID); - sm_set_synonyms_nr(&s->seg_manager, 0, reg.segment, SEG_ID); + s->seg_manager->setLockers(1, reg.segment, SEG_ID); + s->seg_manager->setExportTableOffset(0, reg.segment, SEG_ID); + s->seg_manager->setSynonymsOffset(0, reg.segment, SEG_ID); + s->seg_manager->setSynonymsNr(0, reg.segment, SEG_ID); *was_new = 0; @@ -1760,14 +1758,14 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { // Instead, the script starts with a 16 bit int specifying the // number of locals we need; these are then allocated and zeroed. - sm_mcpy_in_out(&s->seg_manager, 0, script->data, script->size, reg.segment, SEG_ID); + s->seg_manager->mcpyInOut(0, script->data, script->size, reg.segment, SEG_ID); magic_pos_adder = 2; // Step over the funny prefix if (locals_nr) - sm_script_initialise_locals_zero(&s->seg_manager, reg.segment, locals_nr); + s->seg_manager->scriptInitialiseLocalsZero(reg.segment, locals_nr); } else { - sm_mcpy_in_out(&s->seg_manager, 0, script->data, script->size, reg.segment, SEG_ID); + s->seg_manager->mcpyInOut(0, script->data, script->size, reg.segment, SEG_ID); magic_pos_adder = 0; } @@ -1794,17 +1792,17 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { switch (objtype) { case sci_obj_exports: { - sm_set_export_table_offset(&s->seg_manager, data_base.offset, reg.segment, SEG_ID); + s->seg_manager->setExportTableOffset(data_base.offset, reg.segment, SEG_ID); } break; case sci_obj_synonyms: - sm_set_synonyms_offset(&s->seg_manager, addr.offset, reg.segment, SEG_ID); // +4 is to step over the header - sm_set_synonyms_nr(&s->seg_manager, (objlength) / 4, reg.segment, SEG_ID); + s->seg_manager->setSynonymsOffset(addr.offset, reg.segment, SEG_ID); // +4 is to step over the header + s->seg_manager->setSynonymsNr((objlength) / 4, reg.segment, SEG_ID); break; case sci_obj_localvars: - sm_script_initialise_locals(&s->seg_manager, data_base); + s->seg_manager->scriptInitialiseLocals(data_base); break; case sci_obj_class: { @@ -1849,11 +1847,11 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { switch (objtype) { case sci_obj_code: - sm_script_add_code_block(&s->seg_manager, addr); + s->seg_manager->scriptAddCodeBlock(addr); break; case sci_obj_object: case sci_obj_class: { // object or class? - object_t *obj = sm_script_obj_init(&s->seg_manager, s, addr); + object_t *obj = s->seg_manager->scriptObjInit(s, addr); object_t *base_obj; // Instantiate the superclass, if neccessary @@ -1880,17 +1878,13 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { } while ((objtype != 0) && (((unsigned)reg.offset) < script->size - 2)); if (relocation >= 0) - sm_script_relocate(&s->seg_manager, make_reg(reg.segment, relocation)); + s->seg_manager->scriptRelocate(make_reg(reg.segment, relocation)); - sm_script_free_unused_objects(&s->seg_manager, reg.segment); + s->seg_manager->scriptFreeUnusedObjects(reg.segment); return reg.segment; // instantiation successful } -void sm_script_relocate_exports_sci11(SegManager *self, int seg); -void sm_script_initialise_objects_sci11(SegManager *self, EngineState *s, int seg); -void sm_heap_relocate(SegManager *self, EngineState *s, reg_t block); - int script_instantiate_sci11(EngineState *s, int script_nr) { resource_t *script, *heap; int seg_id; @@ -1907,21 +1901,21 @@ int script_instantiate_sci11(EngineState *s, int script_nr) { if (script->size & 2) heap_start ++; - sm_mcpy_in_out(&s->seg_manager, 0, script->data, script->size, seg_id, SEG_ID); - sm_mcpy_in_out(&s->seg_manager, heap_start, heap->data, heap->size, seg_id, SEG_ID); + s->seg_manager->mcpyInOut(0, script->data, script->size, seg_id, SEG_ID); + s->seg_manager->mcpyInOut(heap_start, heap->data, heap->size, seg_id, SEG_ID); if (getUInt16(script->data + 6) > 0) - sm_set_export_table_offset(&s->seg_manager, 6, seg_id, SEG_ID); + s->seg_manager->setExportTableOffset(6, seg_id, SEG_ID); reg.segment = seg_id; reg.offset = heap_start + 4; - sm_script_initialise_locals(&s->seg_manager, reg); + s->seg_manager->scriptInitialiseLocals(reg); - sm_script_relocate_exports_sci11(&s->seg_manager, seg_id); - sm_script_initialise_objects_sci11(&s->seg_manager, s, seg_id); + s->seg_manager->scriptRelocateExportsSci11(seg_id); + s->seg_manager->scriptInitialiseObjectsSci11(s, seg_id); reg.offset = getUInt16(heap->data); - sm_heap_relocate(&s->seg_manager, s, reg); + s->seg_manager->heapRelocate(s, reg); return seg_id; } @@ -1933,8 +1927,6 @@ int script_instantiate(EngineState *s, int script_nr) { return script_instantiate_sci0(s, script_nr); } -void sm_mark_script_deleted(SegManager* self, int script_nr); - void script_uninstantiate_sci0(EngineState *s, int script_nr, seg_id_t seg) { reg_t reg = make_reg(seg, (s->version < SCI_VERSION_FTU_NEW_SCRIPT_HEADER) ? 2 : 0); int objtype, objlength; @@ -1962,8 +1954,8 @@ void script_uninstantiate_sci0(EngineState *s, int script_nr, seg_id_t seg) { int superclass_script = s->classtable[superclass].script; if (superclass_script == script_nr) { - if (sm_get_lockers(&s->seg_manager, reg.segment, SEG_ID)) - sm_decrement_lockers(&s->seg_manager, reg.segment, SEG_ID); // Decrease lockers if this is us ourselves + if (s->seg_manager->getLockers(reg.segment, SEG_ID)) + s->seg_manager->decrementLockers(reg.segment, SEG_ID); // Decrease lockers if this is us ourselves } else script_uninstantiate(s, superclass_script); // Recurse to assure that the superclass lockers number gets decreased @@ -1981,17 +1973,17 @@ void script_uninstantiate(EngineState *s, int script_nr) { reg_t reg = make_reg(0, (s->version < SCI_VERSION_FTU_NEW_SCRIPT_HEADER) ? 2 : 0); int i; - reg.segment = sm_seg_get(&s->seg_manager, script_nr); + reg.segment = s->seg_manager->segGet(script_nr); - if (!sm_script_is_loaded(&s->seg_manager, script_nr, SCRIPT_ID) || reg.segment <= 0) { // Is it already loaded? + if (!s->seg_manager->scriptIsLoaded(script_nr, SCRIPT_ID) || reg.segment <= 0) { // Is it already loaded? //sciprintf("Warning: unloading script 0x%x requested although not loaded\n", script_nr); // This is perfectly valid SCI behaviour return; } - sm_decrement_lockers(&s->seg_manager, reg.segment, SEG_ID); // One less locker + s->seg_manager->decrementLockers(reg.segment, SEG_ID); // One less locker - if (sm_get_lockers(&s->seg_manager, reg.segment, SEG_ID) > 0) + if (s->seg_manager->getLockers(reg.segment, SEG_ID) > 0) return; // Free all classtable references to this script @@ -2004,12 +1996,12 @@ void script_uninstantiate(EngineState *s, int script_nr) { else sciprintf("FIXME: Add proper script uninstantiation for SCI 1.1\n"); - if (sm_get_lockers(&s->seg_manager, reg.segment, SEG_ID)) + if (s->seg_manager->getLockers(reg.segment, SEG_ID)) return; // if xxx.lockers > 0 // Otherwise unload it completely // Explanation: I'm starting to believe that this work is done by SCI itself. - sm_mark_script_deleted(&s->seg_manager, script_nr); + s->seg_manager->markScriptDeleted(script_nr); if (script_checkloads_flag) sciprintf("Unloaded script 0x%x.\n", script_nr); @@ -2130,7 +2122,7 @@ int game_restore(EngineState **_s, char *game_name) { #endif object_t *obj_get(EngineState *s, reg_t offset) { - mem_obj_t *memobj = GET_OBJECT_SEGMENT(s->seg_manager, offset.segment); + mem_obj_t *memobj = GET_OBJECT_SEGMENT(*s->seg_manager, offset.segment); object_t *obj = NULL; int idx; diff --git a/engines/sci/include/engine.h b/engines/sci/include/engine.h index 5c2ace7ee0..8265088b89 100644 --- a/engines/sci/include/engine.h +++ b/engines/sci/include/engine.h @@ -234,7 +234,7 @@ struct EngineState { int classtable_size; /* Number of classes in the table- for debugging */ class_t *classtable; /* Table of all classes */ - SegManager seg_manager; + SegManager *seg_manager; int gc_countdown; /* Number of kernel calls until next gc */ int selector_names_nr; /* Number of selector names */ diff --git a/engines/sci/include/vm.h b/engines/sci/include/vm.h index 05585632e8..6362c2f072 100644 --- a/engines/sci/include/vm.h +++ b/engines/sci/include/vm.h @@ -256,8 +256,23 @@ struct dynmem_t { byte *buf; }; /* Free-style memory */ +enum memObjType { + MEM_OBJ_INVALID = 0, + MEM_OBJ_SCRIPT = 1, + MEM_OBJ_CLONES = 2, + MEM_OBJ_LOCALS = 3, + MEM_OBJ_STACK = 4, + MEM_OBJ_SYS_STRINGS = 5, + MEM_OBJ_LISTS = 6, + MEM_OBJ_NODES = 7, + MEM_OBJ_HUNK = 8, + MEM_OBJ_DYNMEM = 9, + MEM_OBJ_RESERVED = 10, + MEM_OBJ_MAX = MEM_OBJ_RESERVED // For sanity checking +}; + struct mem_obj_t { - int type; + memObjType type; int segmgr_id; /* Internal value used by the seg_manager's hash map */ union { script_t script; |