diff options
-rw-r--r-- | engines/sci/engine/gc.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/kernel.cpp | 16 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 65 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 60 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.cpp | 240 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.h | 10 | ||||
-rw-r--r-- | engines/sci/engine/vm.h | 42 |
7 files changed, 229 insertions, 206 deletions
diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index b6703e1679..f8be73f26a 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -123,7 +123,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { for (i = 1; i < sm->_heap.size(); i++) if (interfaces[i] && interfaces[i]->getType() == MEM_OBJ_SCRIPT) { - Script *script = &(interfaces[i]->getMobj()->data.script); + Script *script = (Script *)(interfaces[i]->getMobj()); if (script->lockers) { // Explicitly loaded? int obj_nr; diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 226481cbcd..4da9b62348 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -674,10 +674,10 @@ int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) { switch (mobj->getType()) { case MEM_OBJ_SCRIPT: - if (reg.offset <= mobj->data.script.buf_size && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET - && RAW_IS_OBJECT(mobj->data.script.buf + reg.offset)) { - int idx = RAW_GET_CLASS_INDEX(&(mobj->data.script), reg); - if (idx >= 0 && idx < mobj->data.script.objects_nr) + if (reg.offset <= (*(Script *)mobj).buf_size && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET + && RAW_IS_OBJECT((*(Script *)mobj).buf + reg.offset)) { + int idx = RAW_GET_CLASS_INDEX((Script *)mobj, reg); + if (idx >= 0 && idx < (*(Script *)mobj).objects_nr) return KSIG_OBJECT; else return KSIG_REF; @@ -691,20 +691,20 @@ int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) { return KSIG_OBJECT | KSIG_INVALID; case MEM_OBJ_LOCALS: - if (allow_invalid || reg.offset < mobj->data.locals.nr * sizeof(reg_t)) + if (allow_invalid || reg.offset < (*(LocalVariables *)mobj).nr * sizeof(reg_t)) return KSIG_REF; else return KSIG_REF | KSIG_INVALID; case MEM_OBJ_STACK: - if (allow_invalid || reg.offset < mobj->data.stack.nr * sizeof(reg_t)) + if (allow_invalid || reg.offset < (*(dstack_t *)mobj).nr * sizeof(reg_t)) return KSIG_REF; else return KSIG_REF | KSIG_INVALID; case MEM_OBJ_SYS_STRINGS: if (allow_invalid || (reg.offset < SYS_STRINGS_MAX - && mobj->data.sys_strings.strings[reg.offset].name)) + && (*(SystemStrings *)mobj).strings[reg.offset].name)) return KSIG_REF; else return KSIG_REF | KSIG_INVALID; @@ -722,7 +722,7 @@ int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) { return KSIG_NODE | KSIG_INVALID; case MEM_OBJ_DYNMEM: - if (allow_invalid || reg.offset < mobj->data.dynmem.size) + if (allow_invalid || reg.offset < (*(DynMem *)mobj).size) return KSIG_REF; else return KSIG_REF | KSIG_INVALID; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 74bffa6770..800774f01c 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -428,63 +428,62 @@ static void sync_songlib_t(Common::Serializer &s, songlib_t &obj) { } } -static void sync_MemObjPtr(Common::Serializer &s, MemObject *&obj) { +static void sync_MemObjPtr(Common::Serializer &s, MemObject *&mobj) { // Sync the memobj type - memObjType type = (s.isSaving() && obj) ? obj->getType() : MEM_OBJ_INVALID; + MemObjectType type = (s.isSaving() && mobj) ? mobj->getType() : MEM_OBJ_INVALID; s.syncAsUint32LE(type); - // If we were saving and obj == 0, or if we are loading and this is an + // If we were saving and mobj == 0, or if we are loading and this is an // entry marked as empty -> we are done. if (type == MEM_OBJ_INVALID) { - obj = 0; + mobj = 0; return; } if (s.isLoading()) { - //assert(!obj); - obj = (MemObject *)sci_calloc(1, sizeof(MemObject)); - obj->data.tmp_dummy._type = type; + //assert(!mobj); + mobj = MemObject::createMemObject(type); } else { - assert(obj); + assert(mobj); } - s.syncAsSint32LE(obj->data.tmp_dummy._segmgrId); + s.syncAsSint32LE(mobj->_segmgrId); switch (type) { case MEM_OBJ_SCRIPT: - sync_Script(s, obj->data.script); + sync_Script(s, *(Script *)mobj); break; case MEM_OBJ_CLONES: - sync_CloneTable(s, obj->data.clones); + sync_CloneTable(s, *(CloneTable *)mobj); break; case MEM_OBJ_LOCALS: - sync_LocalVariables(s, obj->data.locals); + sync_LocalVariables(s, *(LocalVariables *)mobj); break; case MEM_OBJ_SYS_STRINGS: - sync_SystemStrings(s, obj->data.sys_strings); + sync_SystemStrings(s, *(SystemStrings *)mobj); break; case MEM_OBJ_STACK: // TODO: Switch this stack to use class Common::Stack? - s.syncAsUint32LE(obj->data.stack.nr); + s.syncAsUint32LE((*(dstack_t *)mobj).nr); if (s.isLoading()) { - //free(obj->data.stack.entries); - obj->data.stack.entries = (reg_t *)sci_calloc(obj->data.stack.nr, sizeof(reg_t)); + //free((*(dstack_t *)mobj).entries); + (*(dstack_t *)mobj).entries = (reg_t *)sci_calloc((*(dstack_t *)mobj).nr, sizeof(reg_t)); } break; case MEM_OBJ_HUNK: if (s.isLoading()) { - obj->data.hunks.initTable(); + (*(HunkTable *)mobj).initTable(); } break; case MEM_OBJ_STRING_FRAG: break; case MEM_OBJ_LISTS: - sync_ListTable(s, obj->data.lists); + sync_ListTable(s, *(ListTable *)mobj); break; case MEM_OBJ_NODES: - sync_NodeTable(s, obj->data.nodes); + sync_NodeTable(s, *(NodeTable *)mobj); break; case MEM_OBJ_DYNMEM: - sync_DynMem(s, obj->data.dynmem); + sync_DynMem(s, *(DynMem *)mobj); break; default: error("Unknown MemObject type %d", type); @@ -564,7 +563,7 @@ static byte *find_unique_script_block(EngineState *s, byte *buf, int type) { // FIXME: This should probably be turned into an EngineState method static void reconstruct_stack(EngineState *retval) { SegmentId stack_seg = find_unique_seg_by_type(retval->seg_manager, MEM_OBJ_STACK); - dstack_t *stack = &(retval->seg_manager->_heap[stack_seg]->data.stack); + dstack_t *stack = (dstack_t *)(retval->seg_manager->_heap[stack_seg]); retval->stack_segment = stack_seg; retval->stack_base = stack->entries; @@ -589,7 +588,7 @@ static int clone_entry_used(CloneTable *table, int n) { static void load_script(EngineState *s, SegmentId seg) { Resource *script, *heap = NULL; - Script *scr = &(s->seg_manager->_heap[seg]->data.script); + Script *scr = (Script *)(s->seg_manager->_heap[seg]); scr->buf = (byte *)malloc(scr->buf_size); @@ -618,10 +617,10 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { switch (mobj->getType()) { case MEM_OBJ_SCRIPT: { int j; - Script *scr = &mobj->data.script; + Script *scr = (Script *)mobj; 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 : (LocalVariables *)(s->seg_manager->_heap[scr->locals_segment]); 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; @@ -650,7 +649,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { switch (mobj->getType()) { case MEM_OBJ_SCRIPT: { int j; - Script *scr = &mobj->data.script; + Script *scr = (Script *)mobj; for (j = 0; j < scr->objects_nr; j++) { byte *data = scr->buf + scr->objects[j].pos.offset; @@ -699,27 +698,27 @@ static void reconstruct_clones(EngineState *s, SegManager *self) { switch (mobj->getType()) { case MEM_OBJ_CLONES: { int j; - CloneTable::Entry *seeker = mobj->data.clones.table; + CloneTable::Entry *seeker = (*(CloneTable *)mobj).table; /* sciprintf("Free list: "); - for (j = mobj->data.clones.first_free; j != HEAPENTRY_INVALID; j = mobj->data.clones.table[j].next_free) { + for (j = (*(CloneTable *)mobj).first_free; j != HEAPENTRY_INVALID; j = (*(CloneTable *)mobj).table[j].next_free) { sciprintf("%d ", j); } sciprintf("\n"); sciprintf("Entries w/zero vars: "); - for (j = 0; j < mobj->data.clones.max_entry; j++) { - if (mobj->data.clones.table[j].variables == NULL) + for (j = 0; j < (*(CloneTable *)mobj).max_entry; j++) { + if ((*(CloneTable *)mobj).table[j].variables == NULL) sciprintf("%d ", j); } sciprintf("\n"); */ - for (j = 0; j < mobj->data.clones.max_entry; j++) { + for (j = 0; j < (*(CloneTable *)mobj).max_entry; j++) { Object *base_obj; - if (!clone_entry_used(&mobj->data.clones, j)) { + if (!clone_entry_used(&(*(CloneTable *)mobj), j)) { seeker++; continue; } @@ -858,12 +857,12 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { 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->getScript(script_get_segment(s, 0, SCRIPT_GET_DONT_LOAD), SEG_ID); 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 = &(((MemObject *)(GET_SEGMENT(*retval->seg_manager, retval->sys_strings_segment, MEM_OBJ_SYS_STRINGS)))->data.sys_strings); + retval->sys_strings = (SystemStrings *)GET_SEGMENT(*retval->seg_manager, retval->sys_strings_segment, MEM_OBJ_SYS_STRINGS); // Restore system strings SystemString *str; diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 97a1d18236..82d6461ebe 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -293,19 +293,19 @@ int c_segtable(EngineState *s) { switch (mobj->getType()) { case MEM_OBJ_SCRIPT: - sciprintf("S script.%03d l:%d ", mobj->data.script.nr, mobj->data.script.lockers); + sciprintf("S script.%03d l:%d ", (*(Script *)mobj).nr, (*(Script *)mobj).lockers); break; case MEM_OBJ_CLONES: - sciprintf("C clones (%d allocd)", mobj->data.clones.entries_used); + sciprintf("C clones (%d allocd)", (*(CloneTable *)mobj).entries_used); break; case MEM_OBJ_LOCALS: - sciprintf("V locals %03d", mobj->data.locals.script_id); + sciprintf("V locals %03d", (*(LocalVariables *)mobj).script_id); break; case MEM_OBJ_STACK: - sciprintf("D data stack (%d)", mobj->data.stack.nr); + sciprintf("D data stack (%d)", (*(dstack_t *)mobj).nr); break; case MEM_OBJ_SYS_STRINGS: @@ -313,19 +313,19 @@ int c_segtable(EngineState *s) { break; case MEM_OBJ_LISTS: - sciprintf("L lists (%d)", mobj->data.lists.entries_used); + sciprintf("L lists (%d)", (*(ListTable *)mobj).entries_used); break; case MEM_OBJ_NODES: - sciprintf("N nodes (%d)", mobj->data.nodes.entries_used); + sciprintf("N nodes (%d)", (*(NodeTable *)mobj).entries_used); break; case MEM_OBJ_HUNK: - sciprintf("H hunk (%d)", mobj->data.hunks.entries_used); + sciprintf("H hunk (%d)", (*(HunkTable *)mobj).entries_used); break; case MEM_OBJ_DYNMEM: - sciprintf("M dynmem: %d bytes", mobj->data.dynmem.size); + sciprintf("M dynmem: %d bytes", (*(DynMem *)mobj).size); break; case MEM_OBJ_STRING_FRAG: @@ -360,13 +360,13 @@ static void print_list(EngineState *s, List *l) { Node *node; MemObject *mobj = GET_SEGMENT(*s->seg_manager, pos.segment, MEM_OBJ_NODES); - if (!mobj || !ENTRY_IS_VALID(&(mobj->data.nodes), pos.offset)) { + if (!mobj || !ENTRY_IS_VALID((NodeTable *)mobj, pos.offset)) { sciprintf(" WARNING: "PREG": Doesn't contain list node!\n", PRINT_REG(pos)); return; } - node = &(mobj->data.nodes.table[pos.offset]); + node = &((*(NodeTable *)mobj).table[pos.offset]); sciprintf("\t"PREG" : "PREG" -> "PREG"\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value)); @@ -389,7 +389,7 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) { case MEM_OBJ_SCRIPT: { int i; - Script *scr = &(mobj->data.script); + Script *scr = (Script *)mobj; sciprintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->nr, scr->lockers, (uint)scr->buf_size, (uint)scr->buf_size); if (scr->export_table) sciprintf(" Exports: %4d at %d\n", scr->exports_nr, (int)(((byte *)scr->export_table) - ((byte *)scr->buf))); @@ -412,14 +412,14 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) { break; case MEM_OBJ_LOCALS: { - LocalVariables *locals = &(mobj->data.locals); + LocalVariables *locals = (LocalVariables *)mobj; sciprintf("locals for script.%03d\n", locals->script_id); sciprintf(" %d (0x%x) locals\n", locals->nr, locals->nr); } break; case MEM_OBJ_STACK: { - dstack_t *stack = &(mobj->data.stack); + dstack_t *stack = (dstack_t *)mobj; sciprintf("stack\n"); sciprintf(" %d (0x%x) entries\n", stack->nr, stack->nr); } @@ -439,7 +439,7 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) { case MEM_OBJ_CLONES: { int i = 0; - CloneTable *ct = &(mobj->data.clones); + CloneTable *ct = (CloneTable *)mobj; sciprintf("clones\n"); @@ -453,7 +453,7 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) { case MEM_OBJ_LISTS: { int i = 0; - ListTable *lt = &(mobj->data.lists); + ListTable *lt = (ListTable *)mobj; sciprintf("lists\n"); for (i = 0; i < lt->max_entry; i++) @@ -465,15 +465,15 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) { break; case MEM_OBJ_NODES: { - sciprintf("nodes (total %d)\n", mobj->data.nodes.entries_used); + sciprintf("nodes (total %d)\n", (*(NodeTable *)mobj).entries_used); break; } case MEM_OBJ_HUNK: { int i; - HunkTable *ht = &(mobj->data.hunks); + HunkTable *ht = (HunkTable *)mobj; - sciprintf("hunk (total %d)\n", mobj->data.hunks.entries_used); + sciprintf("hunk (total %d)\n", ht->entries_used); for (i = 0; i < ht->max_entry; i++) if (ENTRY_IS_VALID(ht, i)) { sciprintf(" [%04x] %d bytes at %p, type=%s\n", @@ -483,9 +483,9 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) { case MEM_OBJ_DYNMEM: { sciprintf("dynmem (%s): %d bytes\n", - mobj->data.dynmem.description ? mobj->data.dynmem.description : "no description", mobj->data.dynmem.size); + (*(DynMem *)mobj).description ? (*(DynMem *)mobj).description : "no description", (*(DynMem *)mobj).size); - sci_hexdump(mobj->data.dynmem.buf, mobj->data.dynmem.size, 0); + sci_hexdump((*(DynMem *)mobj).buf, (*(DynMem *)mobj).size, 0); } break; @@ -504,7 +504,7 @@ static int show_node(EngineState *s, reg_t addr) { MemObject *mobj = GET_SEGMENT(*s->seg_manager, addr.segment, MEM_OBJ_LISTS); if (mobj) { - ListTable *lt = &(mobj->data.lists); + ListTable *lt = (ListTable *)mobj; List *list; if (!ENTRY_IS_VALID(lt, addr.offset)) { @@ -525,7 +525,7 @@ static int show_node(EngineState *s, reg_t addr) { return 1; } - nt = &(mobj->data.nodes); + nt = (NodeTable *)mobj; if (!ENTRY_IS_VALID(nt, addr.offset)) { sciprintf("Address does not contain a node\n"); @@ -1212,7 +1212,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. - MemObject *memobj = GET_SEGMENT(*s->seg_manager, pos.segment, MEM_OBJ_SCRIPT); + MemObject *mobj = GET_SEGMENT(*s->seg_manager, pos.segment, MEM_OBJ_SCRIPT); Script *script_entity = NULL; byte *scr; int scr_size; @@ -1223,11 +1223,11 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod int bytecount = 1; int i = 0; - if (!memobj) { + if (!mobj) { sciprintf("Disassembly failed: Segment %04x non-existant or not a script\n", pos.segment); return retval; } else - script_entity = &(memobj->data.script); + script_entity = (Script *)mobj; scr = script_entity->buf; scr_size = script_entity->buf_size; @@ -1590,7 +1590,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", (*(Script *)s->seg_manager->_heap[call.addr.pc.segment]).nr); sciprintf("\n"); } @@ -2558,7 +2558,7 @@ int objinfo(EngineState *s, reg_t pos) { 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]->getType() == MEM_OBJ_SCRIPT) - sciprintf("\nOwner script:\t%d\n", s->seg_manager->_heap[pos.segment]->data.script.nr); + sciprintf("\nOwner script:\t%d\n", s->seg_manager->getScript(pos.segment, SEG_ID)->nr); return 0; } @@ -2887,10 +2887,10 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * } if (_debug_seeking && !bp) { // Are we looking for something special? - MemObject *memobj = GET_SEGMENT(*s->seg_manager, pc->segment, MEM_OBJ_SCRIPT); + MemObject *mobj = GET_SEGMENT(*s->seg_manager, pc->segment, MEM_OBJ_SCRIPT); - if (memobj) { - Script *scr = &(memobj->data.script); + if (mobj) { + Script *scr = (Script *)mobj; byte *code_buf = scr->buf; int code_buf_size = scr->buf_size; int opcode = pc->offset >= code_buf_size ? 0 : code_buf[pc->offset]; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 55257c8265..773969514b 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -66,7 +66,7 @@ int SegManager::findFreeId(int *id) { return retval; } -MemObject *SegManager::allocNonscriptSegment(memObjType type, SegmentId *segid) { +MemObject *SegManager::allocNonscriptSegment(MemObjectType type, SegmentId *segid) { // Allocates a non-script segment int id; @@ -222,27 +222,27 @@ int SegManager::deallocate(int seg, bool recursive) { switch (mobj->getType()) { case MEM_OBJ_SCRIPT: - freeScript(mobj->data.script); + freeScript((*(Script *)mobj)); - mobj->data.script.buf = NULL; - if (recursive && mobj->data.script.locals_segment) - deallocate(mobj->data.script.locals_segment, recursive); + (*(Script *)mobj).buf = NULL; + if (recursive && (*(Script *)mobj).locals_segment) + deallocate((*(Script *)mobj).locals_segment, recursive); break; case MEM_OBJ_LOCALS: - free(mobj->data.locals.locals); - mobj->data.locals.locals = NULL; + free((*(LocalVariables *)mobj).locals); + (*(LocalVariables *)mobj).locals = NULL; break; case MEM_OBJ_DYNMEM: - free(mobj->data.dynmem.description); - mobj->data.dynmem.description = NULL; - free(mobj->data.dynmem.buf); - mobj->data.dynmem.buf = NULL; + free((*(DynMem *)mobj).description); + (*(DynMem *)mobj).description = NULL; + free((*(DynMem *)mobj).buf); + (*(DynMem *)mobj).buf = NULL; break; case MEM_OBJ_SYS_STRINGS: for (i = 0; i < SYS_STRINGS_MAX; i++) { - SystemString *str = &mobj->data.sys_strings.strings[i]; + SystemString *str = &(*(SystemStrings *)mobj).strings[i]; if (str->name) { free(str->name); str->name = NULL; @@ -255,28 +255,28 @@ int SegManager::deallocate(int seg, bool recursive) { } break; case MEM_OBJ_STACK: - free(mobj->data.stack.entries); - mobj->data.stack.entries = NULL; + free((*(dstack_t *)mobj).entries); + (*(dstack_t *)mobj).entries = NULL; break; case MEM_OBJ_LISTS: - free(mobj->data.lists.table); - mobj->data.lists.table = NULL; - mobj->data.lists.entries_nr = mobj->data.lists.max_entry = 0; + free((*(ListTable *)mobj).table); + (*(ListTable *)mobj).table = NULL; + (*(ListTable *)mobj).entries_nr = (*(ListTable *)mobj).max_entry = 0; break; case MEM_OBJ_NODES: - free(mobj->data.nodes.table); - mobj->data.nodes.table = NULL; - mobj->data.nodes.entries_nr = mobj->data.nodes.max_entry = 0; + free((*(NodeTable *)mobj).table); + (*(NodeTable *)mobj).table = NULL; + (*(NodeTable *)mobj).entries_nr = (*(NodeTable *)mobj).max_entry = 0; break; case MEM_OBJ_CLONES: - free(mobj->data.clones.table); - mobj->data.clones.table = NULL; - mobj->data.clones.entries_nr = mobj->data.clones.max_entry = 0; + free((*(CloneTable *)mobj).table); + (*(CloneTable *)mobj).table = NULL; + (*(CloneTable *)mobj).entries_nr = (*(CloneTable *)mobj).max_entry = 0; break; case MEM_OBJ_HUNK: - free(mobj->data.hunks.table); - mobj->data.hunks.table = NULL; - mobj->data.hunks.entries_nr = mobj->data.hunks.max_entry = 0; + free((*(HunkTable *)mobj).table); + (*(HunkTable *)mobj).table = NULL; + (*(HunkTable *)mobj).entries_nr = (*(HunkTable *)mobj).max_entry = 0; break; case MEM_OBJ_STRING_FRAG: break; @@ -284,7 +284,7 @@ int SegManager::deallocate(int seg, bool recursive) { error("Deallocating segment type %d not supported", mobj->getType()); } - free(mobj); + delete mobj; _heap[seg] = NULL; return 1; @@ -314,7 +314,7 @@ int SegManager::scriptIsMarkedAsDeleted(SegmentId seg) { if (_heap[seg]->getType() != MEM_OBJ_SCRIPT) return 0; - scr = &(_heap[seg]->data.script); + scr = (Script *)_heap[seg]; return scr->marked_as_deleted; } @@ -328,10 +328,53 @@ int SegManager::deallocateScript(int script_nr) { return 1; } -MemObject *SegManager::memObjAllocate(SegmentId segid, int hash_id, memObjType type) { - MemObject *mem = (MemObject *)sci_calloc(1, sizeof(MemObject)); +MemObject *MemObject::createMemObject(MemObjectType type) { + MemObject *mem = 0; + switch (type) { + case MEM_OBJ_SCRIPT: + mem = new Script(); + break; + case MEM_OBJ_CLONES: + mem = new CloneTable(); + break; + case MEM_OBJ_LOCALS: + mem = new LocalVariables(); + break; + case MEM_OBJ_SYS_STRINGS: + mem = new SystemStrings(); + break; + case MEM_OBJ_STACK: + mem = new dstack_t(); + break; + case MEM_OBJ_HUNK: + mem = new HunkTable(); + break; + case MEM_OBJ_STRING_FRAG: + mem = new MemObject(); // FIXME: This is a temporary hack until MEM_OBJ_STRING_FRAG is implemented + break; + case MEM_OBJ_LISTS: + mem = new ListTable(); + break; + case MEM_OBJ_NODES: + mem = new NodeTable(); + break; + case MEM_OBJ_DYNMEM: + mem = new DynMem(); + break; + default: + error("Unknown MemObject type %d", type); + break; + } + + assert(mem); + mem->_type = type; + return mem; +} + +MemObject *SegManager::memObjAllocate(SegmentId segid, int hash_id, MemObjectType type) { + MemObject *mem = MemObject::createMemObject(type); if (!mem) { - sciprintf("SegManager: invalid mem_obj "); + sciprintf("SegManager: invalid mobj "); return NULL; } @@ -343,22 +386,13 @@ MemObject *SegManager::memObjAllocate(SegmentId segid, int hash_id, memObjType t _heap.resize(_heap.size() * 2); } - mem->data.tmp_dummy._segmgrId = hash_id; - mem->data.tmp_dummy._type = type; + mem->_segmgrId = hash_id; // hook it to the heap _heap[segid] = mem; return mem; } -/* No longer in use? -void SegManager::sm_object_init(Object *object) { - if (!object) - return; - object->variables_nr = 0; - object->variables = NULL; -};*/ - void SegManager::freeScript(Script &scr) { if (scr.buf) { free(scr.buf); @@ -395,17 +429,19 @@ void SegManager::mcpyInOut(int dst, const void *src, size_t n, int id, idFlag fl } int16 SegManager::getHeap(reg_t reg) { - MemObject *mem_obj; + MemObject *mobj; + Script *scr; VERIFY(check(reg.segment), "Invalid seg id"); - mem_obj = _heap[reg.segment]; + mobj = _heap[reg.segment]; - switch (mem_obj->getType()) { + switch (mobj->getType()) { case MEM_OBJ_SCRIPT: - VERIFY(reg.offset + 1 < (uint16)mem_obj->data.script.buf_size, "invalid offset\n"); - return (mem_obj->data.script.buf[reg.offset] | (mem_obj->data.script.buf[reg.offset+1]) << 8); + scr = (Script *)mobj; + VERIFY(reg.offset + 1 < (uint16)scr->buf_size, "invalid offset\n"); + return (scr->buf[reg.offset] | (scr->buf[reg.offset+1]) << 8); default: - error("SegManager::getHeap: unsupported mem obj type %d", mem_obj->getType()); + error("SegManager::getHeap: unsupported mem obj type %d", mobj->getType()); break; } return 0; // never get here @@ -428,7 +464,7 @@ Script *SegManager::getScript(const int id, idFlag flag) { if (_heap[seg]->getType() != MEM_OBJ_SCRIPT) { error("SegManager::getScript(%d,%d): seg id %x refers to type %d != MEM_OBJ_SCRIPT", id, flag, seg, _heap[seg]->getType()); } - return &(_heap[seg]->data.script); + return (Script *)_heap[seg]; } // validate the seg @@ -528,7 +564,7 @@ int SegManager::relocateBlock(reg_t *block, int block_location, int block_items, } block[index].segment = segment; // Perform relocation if (isSci1_1) - block[index].offset += _heap[segment]->data.script.script_size; + block[index].offset += getScript(segment, SEG_ID)->script_size; return 1; } @@ -791,11 +827,11 @@ LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) { mobj = _heap[scr->locals_segment]; VERIFY(mobj != NULL, "Re-used locals segment was NULL'd out"); VERIFY(mobj->getType() == 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"); + VERIFY((*(LocalVariables *)mobj).script_id == scr->nr, "Re-used locals segment belonged to other script"); } else mobj = allocNonscriptSegment(MEM_OBJ_LOCALS, &scr->locals_segment); - locals = scr->locals_block = &(mobj->data.locals); + locals = scr->locals_block = (LocalVariables *)mobj; locals->script_id = scr->nr; locals->locals = (reg_t *)sci_calloc(count, sizeof(reg_t)); locals->nr = count; @@ -933,8 +969,8 @@ static char *SegManager::dynprintf(char *msg, ...) { */ dstack_t *SegManager::allocateStack(int size, SegmentId *segid) { - MemObject *memobj = allocNonscriptSegment(MEM_OBJ_STACK, segid); - dstack_t *retval = &(memobj->data.stack); + MemObject *mobj = allocNonscriptSegment(MEM_OBJ_STACK, segid); + dstack_t *retval = (dstack_t *)mobj; retval->entries = (reg_t *)sci_calloc(size, sizeof(reg_t)); retval->nr = size; @@ -943,8 +979,8 @@ dstack_t *SegManager::allocateStack(int size, SegmentId *segid) { } SystemStrings *SegManager::allocateSysStrings(SegmentId *segid) { - MemObject *memobj = allocNonscriptSegment(MEM_OBJ_SYS_STRINGS, segid); - SystemStrings *retval = &(memobj->data.sys_strings); + MemObject *mobj = allocNonscriptSegment(MEM_OBJ_SYS_STRINGS, segid); + SystemStrings *retval = (SystemStrings *)mobj; memset(retval->strings, 0, sizeof(retval->strings)); @@ -982,7 +1018,7 @@ void SegManager::free_hunk_entry(reg_t addr) { return; } - Sci::free_Hunk_entry(&(mobj->data.hunks), addr.offset); + Sci::free_Hunk_entry((HunkTable *)mobj, addr.offset); } Hunk *SegManager::alloc_hunk_entry(const char *hunk_type, int size, reg_t *reg) { @@ -1052,11 +1088,11 @@ Clone *SegManager::alloc_Clone(reg_t *addr) { if (!Clones_seg_id) { mobj = allocNonscriptSegment(MEM_OBJ_CLONES, &(Clones_seg_id)); - mobj->data.clones.initTable(); + (*(CloneTable *)mobj).initTable(); } else mobj = _heap[Clones_seg_id]; - table = &(mobj->data.clones); + table = (CloneTable *)mobj; offset = table->allocEntry(); *addr = make_reg(Clones_seg_id, offset); @@ -1070,11 +1106,11 @@ List *SegManager::alloc_List(reg_t *addr) { if (!Lists_seg_id) { mobj = allocNonscriptSegment(MEM_OBJ_LISTS, &(Lists_seg_id)); - mobj->data.lists.initTable(); + (*(ListTable *)mobj).initTable(); } else mobj = _heap[Lists_seg_id]; - table = &(mobj->data.lists); + table = (ListTable *)mobj; offset = table->allocEntry(); *addr = make_reg(Lists_seg_id, offset); @@ -1088,11 +1124,11 @@ Node *SegManager::alloc_Node(reg_t *addr) { if (!Nodes_seg_id) { mobj = allocNonscriptSegment(MEM_OBJ_NODES, &(Nodes_seg_id)); - mobj->data.nodes.initTable(); + (*(NodeTable *)mobj).initTable(); } else mobj = _heap[Nodes_seg_id]; - table = &(mobj->data.nodes); + table = (NodeTable *)mobj; offset = table->allocEntry(); *addr = make_reg(Nodes_seg_id, offset); @@ -1106,11 +1142,11 @@ Hunk *SegManager::alloc_Hunk(reg_t *addr) { if (!Hunks_seg_id) { mobj = allocNonscriptSegment(MEM_OBJ_HUNK, &(Hunks_seg_id)); - mobj->data.hunks.initTable(); + (*(HunkTable *)mobj).initTable(); } else mobj = _heap[Hunks_seg_id]; - table = &(mobj->data.hunks); + table = (HunkTable *)mobj; offset = table->allocEntry(); *addr = make_reg(Hunks_seg_id, offset); @@ -1134,36 +1170,36 @@ byte *SegManager::dereference(reg_t pointer, int *size) { switch (mobj->getType()) { case MEM_OBJ_SCRIPT: - if (pointer.offset > mobj->data.script.buf_size) { + if (pointer.offset > (*(Script *)mobj).buf_size) { sciprintf("Error: Attempt to dereference invalid pointer "PREG" into script segment (script size=%d)\n", - PRINT_REG(pointer), (uint)mobj->data.script.buf_size); + PRINT_REG(pointer), (uint)(*(Script *)mobj).buf_size); return NULL; } if (size) - *size = mobj->data.script.buf_size - pointer.offset; - return (byte *)(mobj->data.script.buf + pointer.offset); + *size = (*(Script *)mobj).buf_size - pointer.offset; + return (byte *)((*(Script *)mobj).buf + pointer.offset); break; case MEM_OBJ_LOCALS: - count = mobj->data.locals.nr * sizeof(reg_t); - base = (byte *)mobj->data.locals.locals; + count = (*(LocalVariables *)mobj).nr * sizeof(reg_t); + base = (byte *)(*(LocalVariables *)mobj).locals; break; case MEM_OBJ_STACK: - count = mobj->data.stack.nr * sizeof(reg_t); - base = (byte *)mobj->data.stack.entries; + count = (*(dstack_t *)mobj).nr * sizeof(reg_t); + base = (byte *)(*(dstack_t *)mobj).entries; break; case MEM_OBJ_DYNMEM: - count = mobj->data.dynmem.size; - base = (byte *)mobj->data.dynmem.buf; + count = (*(DynMem *)mobj).size; + base = (byte *)(*(DynMem *)mobj).buf; break; case MEM_OBJ_SYS_STRINGS: if (size) - *size = mobj->data.sys_strings.strings[pointer.offset].max_size; - if (pointer.offset < SYS_STRINGS_MAX && mobj->data.sys_strings.strings[pointer.offset].name) - return (byte *)(mobj->data.sys_strings.strings[pointer.offset].value); + *size = (*(SystemStrings *)mobj).strings[pointer.offset].max_size; + if (pointer.offset < SYS_STRINGS_MAX && (*(SystemStrings *)mobj).strings[pointer.offset].name) + return (byte *)((*(SystemStrings *)mobj).strings[pointer.offset].value); else { sciprintf("Error: Attempt to dereference invalid pointer "PREG"!\n", PRINT_REG(pointer)); @@ -1188,16 +1224,18 @@ unsigned char *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) MemObject *mobj = allocNonscriptSegment(MEM_OBJ_DYNMEM, &seg); *addr = make_reg(seg, 0); - mobj->data.dynmem.size = size; + DynMem &d = *(DynMem *)mobj; + + d.size = size; if (size == 0) - mobj->data.dynmem.buf = NULL; + d.buf = NULL; else - mobj->data.dynmem.buf = (byte*) sci_malloc(size); + d.buf = (byte *)sci_malloc(size); - mobj->data.dynmem.description = sci_strdup(descr); + d.description = sci_strdup(descr); - return (unsigned char *)(mobj->data.dynmem.buf); + return (unsigned char *)(d.buf); } const char *SegManager::getDescription(reg_t addr) { @@ -1208,7 +1246,7 @@ const char *SegManager::getDescription(reg_t addr) { switch (mobj->getType()) { case MEM_OBJ_DYNMEM: - return mobj->data.dynmem.description; + return (*(DynMem *)mobj).description; default: return ""; } @@ -1233,7 +1271,7 @@ void SegManager::dbgPrint(const char* msg, void *i) { // ------------------- Segment interface ------------------ -SegInterface::SegInterface(SegManager *segmgr, MemObject *mobj, SegmentId segId, memObjType typeId) : +SegInterface::SegInterface(SegManager *segmgr, MemObject *mobj, SegmentId segId, MemObjectType typeId) : _segmgr(segmgr), _mobj(mobj), _segId(segId), _typeId(typeId) { VERIFY(_mobj->getType() == _typeId, "Invalid MemObject type"); } @@ -1255,7 +1293,7 @@ void SegInterface::listAllOutgoingReferences(EngineState *s, reg_t object, void //-------------------- base -------------------- class SegInterfaceBase : public SegInterface { protected: - SegInterfaceBase(SegManager *segmgr, MemObject *mobj, SegmentId segId, memObjType typeId) : + SegInterfaceBase(SegManager *segmgr, MemObject *mobj, SegmentId segId, MemObjectType typeId) : SegInterface(segmgr, mobj, segId, typeId) {} public: reg_t findCanonicAddress(reg_t addr); @@ -1282,7 +1320,7 @@ public: }; void SegInterfaceScript::freeAtAddress(reg_t addr) { - Script *script = &(_mobj->data.script); + Script *script = (Script *)_mobj; /* sciprintf("[GC] Freeing script "PREG"\n", PRINT_REG(addr)); if (script->locals_segment) @@ -1294,7 +1332,7 @@ void SegInterfaceScript::freeAtAddress(reg_t addr) { } void SegInterfaceScript::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - Script *script = &(_mobj->data.script); + Script *script = (Script *)_mobj; if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) { int idx = RAW_GET_CLASS_INDEX(script, addr); @@ -1338,7 +1376,7 @@ void SegInterfaceClones::listAllDeallocatable(void *param, NoteCallback note) { } void SegInterfaceClones::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - CloneTable *clone_table = &(_mobj->data.clones); + CloneTable *clone_table = (CloneTable *)_mobj; Clone *clone; int i; @@ -1366,7 +1404,7 @@ void SegInterfaceClones::freeAtAddress(reg_t addr) { assert(addr.segment == _segId); - victim_obj = &(_mobj->data.clones.table[addr.offset]); + victim_obj = &((*(CloneTable *)_mobj).table[addr.offset]); #ifdef GC_DEBUG if (!(victim_obj->flags & OBJECT_FLAG_FREED)) @@ -1382,7 +1420,7 @@ void SegInterfaceClones::freeAtAddress(reg_t addr) { */ free(victim_obj->variables); victim_obj->variables = NULL; - Sci::free_Clone_entry(&(_mobj->data.clones), addr.offset); + Sci::free_Clone_entry((CloneTable *)_mobj, addr.offset); } @@ -1397,7 +1435,7 @@ public: }; reg_t SegInterfaceLocals::findCanonicAddress(reg_t addr) { - LocalVariables *locals = &(_mobj->data.locals); + LocalVariables *locals = (LocalVariables *)_mobj; // Reference the owning script SegmentId owner_seg = _segmgr->segGet(locals->script_id); @@ -1412,12 +1450,11 @@ void SegInterfaceLocals::freeAtAddress(reg_t sub_addr) { } void SegInterfaceLocals::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - LocalVariables *locals = &(_mobj->data.locals); - int i; + LocalVariables *locals = (LocalVariables *)_mobj; assert(addr.segment == _segId); - for (i = 0; i < locals->nr; i++) + for (int i = 0; i < locals->nr; i++) (*note)(param, locals->locals[i]); } @@ -1438,9 +1475,10 @@ reg_t SegInterfaceStack::findCanonicAddress(reg_t addr) { void SegInterfaceStack::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { int i; - fprintf(stderr, "Emitting %d stack entries\n", _mobj->data.stack.nr); - for (i = 0; i < _mobj->data.stack.nr; i++) - (*note)(param, _mobj->data.stack.entries[i]); + dstack_t &d = *(dstack_t *)_mobj; + fprintf(stderr, "Emitting %d stack entries\n", d.nr); + for (i = 0; i < d.nr; i++) + (*note)(param, d.entries[i]); fprintf(stderr, "DONE"); } @@ -1471,7 +1509,7 @@ public: }; void SegInterfaceLists::freeAtAddress(reg_t sub_addr) { - Sci::free_List_entry(&(_mobj->data.lists), sub_addr.offset); + Sci::free_List_entry((ListTable *)_mobj, sub_addr.offset); } void SegInterfaceLists::listAllDeallocatable(void *param, NoteCallback note) { @@ -1484,7 +1522,7 @@ void SegInterfaceLists::listAllDeallocatable(void *param, NoteCallback note) { } void SegInterfaceLists::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - ListTable *table = &(_mobj->data.lists); + ListTable *table = (ListTable *)_mobj; List *list = &(table->table[addr.offset]); if (!ENTRY_IS_VALID(table, addr.offset)) { @@ -1510,7 +1548,7 @@ public: }; void SegInterfaceNodes::freeAtAddress(reg_t sub_addr) { - Sci::free_Node_entry(&(_mobj->data.nodes), sub_addr.offset); + Sci::free_Node_entry((NodeTable *)_mobj, sub_addr.offset); } void SegInterfaceNodes::listAllDeallocatable(void *param, NoteCallback note) { @@ -1523,7 +1561,7 @@ void SegInterfaceNodes::listAllDeallocatable(void *param, NoteCallback note) { } void SegInterfaceNodes::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { - NodeTable *table = &(_mobj->data.nodes); + NodeTable *table = (NodeTable *)_mobj; Node *node = &(table->table[addr.offset]); if (!ENTRY_IS_VALID(table, addr.offset)) { diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 937485c737..6a2cc14e65 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -405,9 +405,9 @@ public: // TODO: make private SegmentId Hunks_seg_id; // ID of the (a) hunk segment private: - MemObject *allocNonscriptSegment(memObjType type, SegmentId *segid); + MemObject *allocNonscriptSegment(MemObjectType type, SegmentId *segid); LocalVariables *allocLocalsSegment(Script *scr, int count); - MemObject *memObjAllocate(SegmentId segid, int hash_id, memObjType type); + MemObject *memObjAllocate(SegmentId segid, int hash_id, MemObjectType type); int deallocate(int seg, bool recursive); Hunk *alloc_Hunk(reg_t *); @@ -446,7 +446,7 @@ private: // But note that _mobj->segmgr_id != _segId ! class SegInterface { protected: - SegInterface(SegManager *segmgr, MemObject *mobj, SegmentId segId, memObjType typeId); + SegInterface(SegManager *segmgr, MemObject *mobj, SegmentId segId, MemObjectType typeId); public: typedef void (*NoteCallback)(void *param, reg_t addr); @@ -481,7 +481,7 @@ public: MemObject *getMobj() { return _mobj; } // Get the segment type - memObjType getType() { return _typeId; } + MemObjectType getType() { return _typeId; } protected: SegManager *_segmgr; @@ -489,7 +489,7 @@ protected: SegmentId _segId; private: - memObjType _typeId; // Segment type + MemObjectType _typeId; // Segment type }; } // End of namespace Sci diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 6d9c1f2b8b..f036ccb496 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -34,7 +34,7 @@ namespace Sci { -enum memObjType { +enum MemObjectType { MEM_OBJ_INVALID = 0, MEM_OBJ_SCRIPT = 1, MEM_OBJ_CLONES = 2, @@ -50,9 +50,14 @@ enum memObjType { MEM_OBJ_MAX // For sanity checking }; -struct MemObjectNEW { - memObjType _type; +struct MemObject { + MemObjectType _type; int _segmgrId; /**< Internal value used by the seg_manager's hash map */ + + inline MemObjectType getType() const { return _type; } + inline int getSegMgrId() const { return _segmgrId; } + + static MemObject *createMemObject(MemObjectType type); }; @@ -73,7 +78,7 @@ struct SystemString { reg_t *value; }; -struct SystemStrings : public MemObjectNEW { +struct SystemStrings : public MemObject { SystemString strings[SYS_STRINGS_MAX]; }; @@ -171,7 +176,7 @@ struct CallsStruct { int type; /**< Same as ExecStack.type */ }; -struct LocalVariables : public MemObjectNEW { +struct LocalVariables : public MemObject { int script_id; /**< Script ID this local variable block belongs to */ reg_t *locals; int nr; @@ -220,7 +225,7 @@ struct CodeBlock { -struct Script : public MemObjectNEW { +struct Script : public MemObject { int nr; /**< Script number */ byte* buf; /**< Static data buffer, or NULL if not used */ size_t buf_size; @@ -255,7 +260,7 @@ struct Script : public MemObjectNEW { }; /** Data stack */ -struct dstack_t : MemObjectNEW { +struct dstack_t : MemObject { int nr; /**< Number of stack entries */ reg_t *entries; }; @@ -284,7 +289,7 @@ struct Hunk { }; template<typename T, int INITIAL, int INCREMENT> -struct Table : public MemObjectNEW { +struct Table : public MemObject { struct Entry : public T { int next_free; /* Only used for free entries */ }; @@ -346,31 +351,12 @@ void free_Hunk_entry(HunkTable *table, int index); // Free-style memory -struct DynMem : public MemObjectNEW { +struct DynMem : public MemObject { int size; char *description; byte *buf; }; -struct MemObject { - union { - MemObjectNEW tmp_dummy; - Script script; - CloneTable clones; - LocalVariables locals; - dstack_t stack; - SystemStrings sys_strings; - ListTable lists; - NodeTable nodes; - HunkTable hunks; - DynMem dynmem; - } data; - - inline memObjType getType() const { return data.tmp_dummy._type; } - inline int getSegMgrId() const { return data.tmp_dummy._segmgrId; } -}; - - /** Contains selector IDs for a few selected selectors */ struct selector_map_t { Selector init; /**< Init function */ |