diff options
author | Filippos Karapetis | 2009-06-01 14:12:43 +0000 |
---|---|---|
committer | Filippos Karapetis | 2009-06-01 14:12:43 +0000 |
commit | 99c687463030254c5489cd3d47d876970ab7c080 (patch) | |
tree | 3491eba1a935eaea0a653fd173d5fad60fd72d1d /engines | |
parent | 660aa716625866ae3a9db2a001ed3af6e108caaf (diff) | |
download | scummvm-rg350-99c687463030254c5489cd3d47d876970ab7c080.tar.gz scummvm-rg350-99c687463030254c5489cd3d47d876970ab7c080.tar.bz2 scummvm-rg350-99c687463030254c5489cd3d47d876970ab7c080.zip |
Split the kernel functions away from the vocabulary functions (WIP, saving/loading is broken)
svn-id: r41101
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/console.cpp | 14 | ||||
-rw-r--r-- | engines/sci/engine/game.cpp | 4 | ||||
-rw-r--r-- | engines/sci/engine/kernel.cpp | 87 | ||||
-rw-r--r-- | engines/sci/engine/kernel.h | 86 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 20 | ||||
-rw-r--r-- | engines/sci/engine/kmisc.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/kmovement.cpp | 4 | ||||
-rw-r--r-- | engines/sci/engine/kscripts.cpp | 6 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 9 | ||||
-rw-r--r-- | engines/sci/engine/script.cpp | 10 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 34 | ||||
-rw-r--r-- | engines/sci/engine/state.cpp | 1 | ||||
-rw-r--r-- | engines/sci/engine/state.h | 3 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 8 | ||||
-rw-r--r-- | engines/sci/vocabulary.cpp | 73 | ||||
-rw-r--r-- | engines/sci/vocabulary.h | 73 |
16 files changed, 226 insertions, 208 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index a8883b549c..56605e1d17 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -134,8 +134,8 @@ bool Console::cmdGetVersion(int argc, const char **argv) { bool Console::cmdOpcodes(int argc, const char **argv) { DebugPrintf("Opcode names in numeric order [index: type name]:\n"); - for (uint seeker = 0; seeker < g_EngineState->_vocabulary->getOpcodesSize(); seeker++) { - opcode op = g_EngineState->_vocabulary->getOpcode(seeker); + for (uint seeker = 0; seeker < g_EngineState->_kernel->getOpcodesSize(); seeker++) { + opcode op = g_EngineState->_kernel->getOpcode(seeker); DebugPrintf("%03x: %03x %20s | ", seeker, op.type, op.name.c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); @@ -148,8 +148,8 @@ bool Console::cmdOpcodes(int argc, const char **argv) { bool Console::cmdSelectors(int argc, const char **argv) { DebugPrintf("Selector names in numeric order:\n"); - for (uint seeker = 0; seeker < g_EngineState->_vocabulary->getSelectorNamesSize(); seeker++) { - DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_vocabulary->getSelectorName(seeker).c_str()); + for (uint seeker = 0; seeker < g_EngineState->_kernel->getSelectorNamesSize(); seeker++) { + DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_kernel->getSelectorName(seeker).c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); } @@ -161,8 +161,8 @@ bool Console::cmdSelectors(int argc, const char **argv) { bool Console::cmdKernelNames(int argc, const char **argv) { DebugPrintf("Selector names in numeric order:\n"); - for (uint seeker = 0; seeker < g_EngineState->_vocabulary->getKernelNamesSize(); seeker++) { - DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_vocabulary->getKernelName(seeker).c_str()); + for (uint seeker = 0; seeker < g_EngineState->_kernel->getKernelNamesSize(); seeker++) { + DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_kernel->getKernelName(seeker).c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); } @@ -221,7 +221,7 @@ bool Console::cmdDissectScript(int argc, const char **argv) { return true; } - g_EngineState->_vocabulary->dissectScript(atoi(argv[1])); + g_EngineState->_kernel->dissectScript(atoi(argv[1]), g_EngineState->_vocabulary); return true; } diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 0355bb3966..192aa66367 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -372,7 +372,8 @@ int script_init_engine(EngineState *s, sci_version_t version) { s->parser_lastmatch_word = SAID_NO_MATCH; - s->_vocabulary = new Vocabulary(s->resmgr, (s->flags & GF_SCI0_OLD)); + s->_kernel = new Kernel(s->resmgr, (s->flags & GF_SCI0_OLD)); + s->_vocabulary = new Vocabulary(s->resmgr); script_map_kernel(s); // Maps the kernel functions @@ -423,6 +424,7 @@ void script_free_engine(EngineState *s) { s->_kfuncTable.clear(); delete s->_vocabulary; + delete s->_kernel; } void script_free_breakpoints(EngineState *s) { diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 23f1fc911d..740673afab 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -469,7 +469,80 @@ SciKernelFunction kfunct_mappers[] = { {KF_TERMINATOR, NULL, NULL, NULL} // Terminator }; -static const char *argtype_description[] = { "Undetermined (WTF?)", "List", "Node", "Object", "Reference", "Arithmetic" }; +static const char *argtype_description[] = { "Undetermined", "List", "Node", "Object", "Reference", "Arithmetic" }; + +Kernel::Kernel(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr) { + memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t + + loadKernelNames(); + + loadOpcodes(); + + if (!loadSelectorNames(isOldSci0)) { + error("Kernel: Could not retrieve selector names"); + } + + // Map a few special selectors for later use + mapSelectors(); +} + +Kernel::~Kernel() { + _selectorNames.clear(); + _opcodes.clear(); + _kernelNames.clear(); +} + +bool Kernel::loadSelectorNames(bool isOldSci0) { + int count; + + Resource *r = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES, 0); + + if (!r) // No such resource? + return false; + + count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off + + for (int i = 0; i < count; i++) { + int offset = READ_LE_UINT16(r->data + 2 + i * 2); + int len = READ_LE_UINT16(r->data + offset); + + Common::String tmp((const char *)r->data + offset + 2, len); + _selectorNames.push_back(tmp); + + // Early SCI versions used the LSB in the selector ID as a read/write + // toggle. To compensate for that, we add every selector name twice. + if (isOldSci0) + _selectorNames.push_back(tmp); + } + + return true; +} + +bool Kernel::loadOpcodes() { + int count, i = 0; + Resource* r = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_OPCODES, 0); + + _opcodes.clear(); + + // if the resource couldn't be loaded, leave + if (r == NULL) { + warning("unable to load vocab.%03d", VOCAB_RESOURCE_OPCODES); + return false; + } + + count = READ_LE_UINT16(r->data); + + _opcodes.resize(count); + for (i = 0; i < count; i++) { + int offset = READ_LE_UINT16(r->data + 2 + i * 2); + int len = READ_LE_UINT16(r->data + offset) - 2; + _opcodes[i].type = READ_LE_UINT16(r->data + offset + 2); + // QFG3 has empty opcodes + _opcodes[i].name = len > 0 ? Common::String((char *)r->data + offset + 4, len) : "Dummy"; + } + + return true; +} // Allocates a set amount of memory for a specified use and returns a handle to it. reg_t kalloc(EngineState *s, const char *type, int space) { @@ -582,7 +655,7 @@ void kernel_compile_signature(const char **s) { int script_map_kernel(EngineState *s) { int mapped = 0; int ignored = 0; - uint functions_nr = s->_vocabulary->getKernelNamesSize(); + uint functions_nr = s->_kernel->getKernelNamesSize(); uint max_functions_nr = (s->resmgr->_sciVersion == SCI_VERSION_0) ? 0x72 : 0x7b; if (functions_nr < max_functions_nr) { @@ -599,8 +672,8 @@ int script_map_kernel(EngineState *s) { int seeker, found = -1; Common::String sought_name; - if (functnr < s->_vocabulary->getKernelNamesSize()) - sought_name = s->_vocabulary->getKernelName(functnr); + if (functnr < s->_kernel->getKernelNamesSize()) + sought_name = s->_kernel->getKernelName(functnr); if (!sought_name.empty()) for (seeker = 0; (found == -1) && kfunct_mappers[seeker].type != KF_TERMINATOR; seeker++) @@ -609,7 +682,7 @@ int script_map_kernel(EngineState *s) { if (found == -1) { if (!sought_name.empty()) { - warning("Kernel function %s[%x] unmapped", s->_vocabulary->getKernelName(functnr).c_str(), functnr); + warning("Kernel function %s[%x] unmapped", s->_kernel->getKernelName(functnr).c_str(), functnr); s->_kfuncTable[functnr].fun = kNOP; } else { warning("Flagging kernel function %x as unknown", functnr); @@ -639,7 +712,7 @@ int script_map_kernel(EngineState *s) { } // for all functions requesting to be mapped - sciprintf("Handled %d/%d kernel functions, mapping %d", mapped + ignored, s->_vocabulary->getKernelNamesSize(), mapped); + sciprintf("Handled %d/%d kernel functions, mapping %d", mapped + ignored, s->_kernel->getKernelNamesSize(), mapped); if (ignored) sciprintf(" and ignoring %d", ignored); sciprintf(".\n"); @@ -885,7 +958,7 @@ static void vocab_get_knames11(ResourceManager *resmgr, Common::StringList &name } #endif -bool Vocabulary::loadKernelNames() { +bool Kernel::loadKernelNames() { _kernelNames.clear(); switch (_resmgr->_sciVersion) { diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 557b308506..1ef1e918d9 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -31,6 +31,7 @@ #include "common/rect.h" #include "sci/uinput.h" +#include "sci/vocabulary.h" namespace Sci { @@ -45,7 +46,82 @@ extern int _debug_step_running; #define AVOIDPATH_DYNMEM_STRING "AvoidPath polyline" //#define DEBUG_PARSER // enable for parser debugging -/* Formerly, the heap macros were here; they have been deprecated, however. */ +struct opcode { + int type; + Common::String name; +}; + +class Kernel { +public: + Kernel(ResourceManager *resmgr, bool isOldSci0); + ~Kernel(); + + uint getOpcodesSize() const { return _opcodes.size(); } + const opcode &getOpcode(uint opcode) const { return _opcodes[opcode]; } + + uint getSelectorNamesSize() const { return _selectorNames.size(); } + const Common::String &getSelectorName(uint selector) const { return _selectorNames[selector]; } + + uint getKernelNamesSize() const { return _kernelNames.size(); } + const Common::String &getKernelName(uint number) const { return _kernelNames[number]; } + + /* Determines the selector ID of a selector by its name + ** (const char *) selectorName: Name of the selector to look up + ** Returns : (int) The appropriate selector ID, or -1 on error + */ + int findSelector(const char *selectorName) const; + + /* Detects whether a particular kernel function is required in the game + ** (const char *) functionName: The name of the desired kernel function + ** Returns : (bool) true if the kernel function is listed in the kernel table, + ** false otherwise + */ + bool hasKernelFunction(const char *functionName) const; + + // Script dissection/dumping functions + void dissectScript(int scriptNumber, Vocabulary *vocab); + void dumpScriptObject(char *data, int seeker, int objsize); + void dumpScriptClass(char *data, int seeker, int objsize); + + selector_map_t _selectorMap; /**< Shortcut list for important selectors */ +private: + /** + * Loads the kernel function names. + * + * This function reads the kernel function name table from resource_map, + * and fills the _kernelNames array with them. + * The resulting list has the same format regardless of the format of the + * name table of the resource (the format changed between version 0 and 1). + * @return true on success, false on failure + */ + bool loadKernelNames(); + + /** + * Loads the kernel selector names. + * Returns true upon success, false otherwise. + */ + bool loadSelectorNames(bool isOldSci0); + + /* Maps special selectors + ** Returns : (void) + */ + void mapSelectors(); + + /** + * Loads the opcode names (only used for debugging). + * @return true on success, false on failure + */ + bool loadOpcodes(); + + ResourceManager *_resmgr; + + // Kernel-related lists + // List of opcodes, loaded from vocab.998. This list is only used for debugging + // purposes, as we hardcode the list of opcodes in the sci_opcodes enum (script.h) + Common::Array<opcode> _opcodes; + Common::StringList _selectorNames; + Common::StringList _kernelNames; +}; /******************** Selector functionality ********************/ @@ -54,7 +130,7 @@ enum SelectorInvocation { kContinueOnInvalidSelector = 1 }; -#define GET_SEL32(_o_, _slc_) read_selector(s, _o_, s->_vocabulary->_selectorMap._slc_, __FILE__, __LINE__) +#define GET_SEL32(_o_, _slc_) read_selector(s, _o_, s->_kernel->_selectorMap._slc_, __FILE__, __LINE__) #define GET_SEL32V(_o_, _slc_) (GET_SEL32(_o_, _slc_).offset) #define GET_SEL32SV(_o_, _slc_) ((int16)(GET_SEL32(_o_, _slc_).offset)) /* Retrieves a selector from an object @@ -65,8 +141,8 @@ enum SelectorInvocation { ** selector_map_t and mapped in script.c. */ -#define PUT_SEL32(_o_, _slc_, _val_) write_selector(s, _o_, s->_vocabulary->_selectorMap._slc_, _val_, __FILE__, __LINE__) -#define PUT_SEL32V(_o_, _slc_, _val_) write_selector(s, _o_, s->_vocabulary->_selectorMap._slc_, make_reg(0, _val_), __FILE__, __LINE__) +#define PUT_SEL32(_o_, _slc_, _val_) write_selector(s, _o_, s->_kernel->_selectorMap._slc_, _val_, __FILE__, __LINE__) +#define PUT_SEL32V(_o_, _slc_, _val_) write_selector(s, _o_, s->_kernel->_selectorMap._slc_, make_reg(0, _val_), __FILE__, __LINE__) /* Writes a selector value to an object ** Parameters: (reg_t) object: The address of the object which the selector should be written to ** (selector_name) selector: The selector to read @@ -78,7 +154,7 @@ enum SelectorInvocation { #define INV_SEL(_object_, _selector_, _noinvalid_) \ - s, _object_, s->_vocabulary->_selectorMap._selector_, _noinvalid_, funct_nr, argv, argc, __FILE__, __LINE__ + s, _object_, s->_kernel->_selectorMap._selector_, _noinvalid_, funct_nr, argv, argc, __FILE__, __LINE__ /* Kludge for use with invoke_selector(). Used for compatibility with compilers that can't ** handle vararg macros. */ diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index b381d7dd51..2ce71c911d 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1076,7 +1076,7 @@ Common::Rect set_base(EngineState *s, reg_t object) { x = GET_SEL32SV(object, x); original_y = y = GET_SEL32SV(object, y); - if (s->_vocabulary->_selectorMap.z > -1) + if (s->_kernel->_selectorMap.z > -1) z = GET_SEL32SV(object, z); else z = 0; @@ -1130,7 +1130,7 @@ Common::Rect set_base(EngineState *s, reg_t object) { void _k_base_setter(EngineState *s, reg_t object) { Common::Rect absrect = set_base(s, object); - if (lookup_selector(s, object, s->_vocabulary->_selectorMap.brLeft, NULL, NULL) != kSelectorVariable) + if (lookup_selector(s, object, s->_kernel->_selectorMap.brLeft, NULL, NULL) != kSelectorVariable) return; // non-fatal // Note: there was a check here for a very old version of SCI, which supposedly needed @@ -1211,7 +1211,7 @@ Common::Rect get_nsrect(EngineState *s, reg_t object, byte clip) { x = GET_SEL32SV(object, x); y = GET_SEL32SV(object, y); - if (s->_vocabulary->_selectorMap.z > -1) + if (s->_kernel->_selectorMap.z > -1) z = GET_SEL32SV(object, z); else z = 0; @@ -1235,7 +1235,7 @@ Common::Rect get_nsrect(EngineState *s, reg_t object, byte clip) { static void _k_set_now_seen(EngineState *s, reg_t object) { Common::Rect absrect = get_nsrect(s, object, 0); - if (lookup_selector(s, object, s->_vocabulary->_selectorMap.nsTop, NULL, NULL) != kSelectorVariable) { + if (lookup_selector(s, object, s->_kernel->_selectorMap.nsTop, NULL, NULL) != kSelectorVariable) { return; } // This isn't fatal @@ -1720,7 +1720,7 @@ static void _k_view_list_do_postdraw(EngineState *s, GfxList *list) { * if ((widget->signal & (_K_VIEW_SIG_FLAG_PRIVATE | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE)) == _K_VIEW_SIG_FLAG_PRIVATE) { */ if ((widget->signal & (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE)) == 0) { - int has_nsrect = lookup_selector(s, obj, s->_vocabulary->_selectorMap.nsBottom, NULL, NULL) == kSelectorVariable; + int has_nsrect = lookup_selector(s, obj, s->_kernel->_selectorMap.nsBottom, NULL, NULL) == kSelectorVariable; if (has_nsrect) { int temp; @@ -1742,7 +1742,7 @@ static void _k_view_list_do_postdraw(EngineState *s, GfxList *list) { } #ifdef DEBUG_LSRECT else - fprintf(stderr, "Not lsRecting %04x:%04x because %d\n", PRINT_REG(obj), lookup_selector(s, obj, s->_vocabulary->_selectorMap.nsBottom, NULL, NULL)); + fprintf(stderr, "Not lsRecting %04x:%04x because %d\n", PRINT_REG(obj), lookup_selector(s, obj, s->_kernel->_selectorMap.nsBottom, NULL, NULL)); #endif if (widget->signal & _K_VIEW_SIG_FLAG_HIDDEN) @@ -1894,7 +1894,7 @@ static GfxDynView *_k_make_dynview_obj(EngineState *s, reg_t obj, int options, i loop = oldloop = sign_extend_byte(GET_SEL32V(obj, loop)); cel = oldcel = sign_extend_byte(GET_SEL32V(obj, cel)); - if (s->_vocabulary->_selectorMap.palette) + if (s->_kernel->_selectorMap.palette) palette = GET_SEL32V(obj, palette); else palette = 0; @@ -1916,14 +1916,14 @@ static GfxDynView *_k_make_dynview_obj(EngineState *s, reg_t obj, int options, i PUT_SEL32V(obj, cel, cel); } - if (lookup_selector(s, obj, s->_vocabulary->_selectorMap.underBits, &(under_bitsp), NULL) != kSelectorVariable) { + if (lookup_selector(s, obj, s->_kernel->_selectorMap.underBits, &(under_bitsp), NULL) != kSelectorVariable) { under_bitsp = NULL; under_bits = NULL_REG; debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no underBits\n", PRINT_REG(obj)); } else under_bits = *((reg_t *)under_bitsp); - if (lookup_selector(s, obj, s->_vocabulary->_selectorMap.signal, &(signalp), NULL) != kSelectorVariable) { + if (lookup_selector(s, obj, s->_kernel->_selectorMap.signal, &(signalp), NULL) != kSelectorVariable) { signalp = NULL; signal = 0; debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no signal selector\n", PRINT_REG(obj)); @@ -2015,7 +2015,7 @@ static void _k_prepare_view_list(EngineState *s, GfxList *list, int options) { while (view) { reg_t obj = make_reg(view->_ID, view->_subID); int priority, _priority; - int has_nsrect = (view->_ID <= 0) ? 0 : lookup_selector(s, obj, s->_vocabulary->_selectorMap.nsBottom, NULL, NULL) == kSelectorVariable; + int has_nsrect = (view->_ID <= 0) ? 0 : lookup_selector(s, obj, s->_kernel->_selectorMap.nsBottom, NULL, NULL) == kSelectorVariable; int oldsignal = view->signal; _k_set_now_seen(s, obj); diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 278c5c4b27..df5b3ffba9 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -236,7 +236,7 @@ reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kstub(EngineState *s, int funct_nr, int argc, reg_t *argv) { - sciprintf("Unimplemented syscall: %s[%x](", s->_vocabulary->getKernelName(funct_nr).c_str(), funct_nr); + sciprintf("Unimplemented syscall: %s[%x](", s->_kernel->getKernelName(funct_nr).c_str(), funct_nr); for (int i = 0; i < argc; i++) { sciprintf("%04x:%04x", PRINT_REG(argv[i])); diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 402f040304..4f7d770d0f 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -462,7 +462,7 @@ static void bresenham_autodetect(EngineState *s) { return; } - if (lookup_selector(s, motion_class, s->_vocabulary->_selectorMap.doit, NULL, &fptr) != kSelectorMethod) { + if (lookup_selector(s, motion_class, s->_kernel->_selectorMap.doit, NULL, &fptr) != kSelectorMethod) { warning("bresenham_autodetect failed"); handle_movecnt = INCREMENT_MOVECNT; // Most games do this, so best guess return; @@ -557,7 +557,7 @@ reg_t kDoBresen(EngineState *s, int funct_nr, int argc, reg_t *argv) { debugC(2, kDebugLevelBresen, "New data: (x,y)=(%d,%d), di=%d\n", x, y, bdi); - if (s->_vocabulary->_selectorMap.cantBeHere != -1) + if (s->_kernel->_selectorMap.cantBeHere != -1) invoke_selector(INV_SEL(client, cantBeHere, kStopOnInvalidSelector), 0); else invoke_selector(INV_SEL(client, canBeHere, kStopOnInvalidSelector), 0); diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 6aa773a469..abdf2b0447 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -43,7 +43,7 @@ reg_t read_selector(EngineState *s, reg_t object, Selector selector_id, const ch void write_selector(EngineState *s, reg_t object, Selector selector_id, reg_t value, const char *fname, int line) { reg_t *address; - if ((selector_id < 0) || (selector_id > (int)s->_vocabulary->getSelectorNamesSize())) { + if ((selector_id < 0) || (selector_id > (int)s->_kernel->getSelectorNamesSize())) { warning("Attempt to write to invalid selector %d of" " object at %04x:%04x (%s L%d).", selector_id, PRINT_REG(object), fname, line); return; @@ -51,7 +51,7 @@ void write_selector(EngineState *s, reg_t object, Selector selector_id, reg_t va if (lookup_selector(s, object, selector_id, &address, NULL) != kSelectorVariable) warning("Selector '%s' of object at %04x:%04x could not be" - " written to (%s L%d)", s->_vocabulary->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line); + " written to (%s L%d)", s->_kernel->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line); else *address = value; } @@ -72,7 +72,7 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvoc if (slc_type == kSelectorNone) { warning("Selector '%s' of object at %04x:%04x could not be invoked (%s L%d)", - s->_vocabulary->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line); + s->_kernel->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line); if (noinvalid == kStopOnInvalidSelector) error("[Kernel] Not recoverable: VM was halted\n"); return 1; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index e817b798ec..704051d627 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -827,13 +827,16 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { retval->_vocabulary = s->_vocabulary; // s->_vocabulary = 0; // FIXME: We should set s->_vocabulary to 0 here, // else it could be freed when the old EngineState is freed. Luckily, this freeing currently -// never happens, so we don't need to. This is lucky, because the fact that the kernel function -// and selector tables are stored in the Vocabulary (????) makes it impossible for us to -// free the vocabulary here. +// never happens, so we don't need to. retval->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE); // static VM/Kernel information: + retval->_kernel = s->_kernel; + assert(0 == retval->_kernel); +// s->_kernel = 0; // FIXME: We should set s->_kernel to 0 here, +// else it could be freed when the old EngineState is freed. Luckily, this freeing currently +// never happens, so we don't need to. retval->_kfuncTable = s->_kfuncTable; // Copy breakpoint information from current game instance diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index a111c7e84a..74bbaa8854 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -111,7 +111,7 @@ void script_adjust_opcode_formats(int res_version) { #define FIND_SELECTOR(_slc_) _selectorMap._slc_ = findSelector(#_slc_) #define FIND_SELECTOR2(_slc_, _slcstr_) _selectorMap._slc_ = findSelector(_slcstr_) -void Vocabulary::mapSelectors() { +void Kernel::mapSelectors() { FIND_SELECTOR(init); FIND_SELECTOR(play); FIND_SELECTOR(replay); @@ -202,7 +202,7 @@ void Vocabulary::mapSelectors() { FIND_SELECTOR(syncTime); } -void Vocabulary::dumpScriptObject(char *data, int seeker, int objsize) { +void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { int selectors, overloads, selectorsize; int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker); int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker); @@ -245,7 +245,7 @@ void Vocabulary::dumpScriptObject(char *data, int seeker, int objsize) { } } -void Vocabulary::dumpScriptClass(char *data, int seeker, int objsize) { +void Kernel::dumpScriptClass(char *data, int seeker, int objsize) { int selectors, overloads, selectorsize; int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker); int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker); @@ -292,7 +292,7 @@ void Vocabulary::dumpScriptClass(char *data, int seeker, int objsize) { } } -void Vocabulary::dissectScript(int scriptNumber) { +void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { int objectctr[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned int _seeker = 0; Resource *script = _resmgr->findResource(kResourceTypeScript, scriptNumber, 0); @@ -385,7 +385,7 @@ void Vocabulary::dissectScript(int scriptNumber) { } } else { nextitem = nextitem << 8 | script->data [seeker++]; - sciprintf("%s[%03x] ", getAnyWordFromGroup(nextitem), nextitem); + sciprintf("%s[%03x] ", vocab->getAnyWordFromGroup(nextitem), nextitem); } } sciprintf("\n"); diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 80c876e9f1..1f7fe73e51 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -699,8 +699,8 @@ int c_stack(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { } const char *selector_name(EngineState *s, int selector) { - if (selector >= 0 && selector < (int)s->_vocabulary->getSelectorNamesSize()) - return s->_vocabulary->getSelectorName(selector).c_str(); + if (selector >= 0 && selector < (int)s->_kernel->getSelectorNamesSize()) + return s->_kernel->getSelectorName(selector).c_str(); else return "--INVALID--"; } @@ -822,7 +822,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (print_bw_tag) sciprintf("[%c] ", opsize ? 'B' : 'W'); - sciprintf("%s", s->_vocabulary->getOpcode(opcode).name.c_str()); + sciprintf("%s", s->_kernel->getOpcode(opcode).name.c_str()); i = 0; while (g_opcode_formats[opcode][i]) { @@ -858,7 +858,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (opcode == op_callk) sciprintf(" %s[%x]", (param_value < s->_kfuncTable.size()) ? - ((param_value < s->_vocabulary->getKernelNamesSize()) ? s->_vocabulary->getKernelName(param_value).c_str() : "[Unknown(postulated)]") + ((param_value < s->_kernel->getKernelNamesSize()) ? s->_kernel->getKernelName(param_value).c_str() : "[Unknown(postulated)]") : "<invalid>", param_value); else sciprintf(opsize ? " %02x" : " %04x", param_value); @@ -948,7 +948,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (!name) name = "<invalid>"; - sciprintf(" %s::%s[", name, (selector > s->_vocabulary->getSelectorNamesSize()) ? "<invalid>" : selector_name(s, selector)); + sciprintf(" %s::%s[", name, (selector > s->_kernel->getSelectorNamesSize()) ? "<invalid>" : selector_name(s, selector)); switch (lookup_selector(s, called_obj_addr, selector, &val_ref, &fun_ref)) { case kSelectorMethod: @@ -1058,12 +1058,12 @@ static int c_backtrace(EngineState *s, const Common::Array<cmd_param_t> &cmdPara break; case EXEC_STACK_TYPE_KERNEL: // Kernel function - sciprintf(" %x:[%x] k%s(", i, call.origin, s->_vocabulary->getKernelName(-(call.selector) - 42).c_str()); + sciprintf(" %x:[%x] k%s(", i, call.origin, s->_kernel->getKernelName(-(call.selector) - 42).c_str()); break; case EXEC_STACK_TYPE_VARSELECTOR: sciprintf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read", - objname,s->_vocabulary->getSelectorName(call.selector).c_str()); + objname,s->_kernel->getSelectorName(call.selector).c_str()); break; } @@ -1232,10 +1232,10 @@ static int c_gfx_draw_viewobj(EngineState *s, const Common::Array<cmd_param_t> & } - is_view = (lookup_selector(s, pos, s->_vocabulary->_selectorMap.x, NULL) == kSelectorVariable) && - (lookup_selector(s, pos, s->_vocabulary->_selectorMap.brLeft, NULL) == kSelectorVariable) && - (lookup_selector(s, pos, s->_vocabulary->_selectorMap.signal, NULL) == kSelectorVariable) && - (lookup_selector(s, pos, s->_vocabulary->_selectorMap.nsTop, NULL) == kSelectorVariable); + is_view = (lookup_selector(s, pos, s->_kernel->_selectorMap.x, NULL) == kSelectorVariable) && + (lookup_selector(s, pos, s->_kernel->_selectorMap.brLeft, NULL) == kSelectorVariable) && + (lookup_selector(s, pos, s->_kernel->_selectorMap.signal, NULL) == kSelectorVariable) && + (lookup_selector(s, pos, s->_kernel->_selectorMap.nsTop, NULL) == kSelectorVariable); if (!is_view) { sciprintf("Not a dynamic View object.\n"); @@ -1318,7 +1318,7 @@ static int c_disasm_addr(EngineState *s, const Common::Array<cmd_param_t> &cmdPa static int c_disasm(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { Object *obj = obj_get(s, cmdParams[0].reg); - int selector_id = s->_vocabulary->findSelector(cmdParams[1].str); + int selector_id = s->_kernel->findSelector(cmdParams[1].str); reg_t addr; if (!obj) { @@ -1367,8 +1367,8 @@ static int c_snk(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { callk_index = strtoul(cmdParams [0].str, &endptr, 0); if (*endptr != '\0') { callk_index = -1; - for (uint i = 0; i < s->_vocabulary->getKernelNamesSize(); i++) - if (cmdParams [0].str == s->_vocabulary->getKernelName(i)) { + for (uint i = 0; i < s->_kernel->getKernelNamesSize(); i++) + if (cmdParams [0].str == s->_kernel->getKernelName(i)) { callk_index = i; break; } @@ -1419,7 +1419,7 @@ static int c_send(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { reg_t *vptr; reg_t fptr; - selector_id = s->_vocabulary->findSelector(selector_name); + selector_id = s->_kernel->findSelector(selector_name); if (selector_id < 0) { sciprintf("Unknown selector: \"%s\"\n", selector_name); @@ -1566,7 +1566,7 @@ static void viewobjinfo(EngineState *s, HeapPtr pos) { int have_rects = 0; Common::Rect nsrect, nsrect_clipped, brrect; - if (lookup_selector(s, pos, s->_vocabulary->_selectorMap.nsBottom, NULL) == kSelectorVariable) { + if (lookup_selector(s, pos, s->_kernel->_selectorMap.nsBottom, NULL) == kSelectorVariable) { GETRECT(nsLeft, nsRight, nsBottom, nsTop); GETRECT(lsLeft, lsRight, lsBottom, lsTop); GETRECT(brLeft, brRight, brBottom, brTop); @@ -1580,7 +1580,7 @@ static void viewobjinfo(EngineState *s, HeapPtr pos) { x = GET_SELECTOR(pos, x); y = GET_SELECTOR(pos, y); priority = GET_SELECTOR(pos, priority); - if (s->_vocabulary->_selectorMap.z > 0) { + if (s->_kernel->_selectorMap.z > 0) { z = GET_SELECTOR(pos, z); sciprintf("(%d,%d,%d)\n", x, y, z); } else diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index b8853706ab..c6797edfff 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -121,6 +121,7 @@ EngineState::EngineState() : _dirseeker(this) { gc_countdown = 0; _vocabulary = 0; + _kernel = 0; successor = 0; } diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 79b753b1be..6f22527f28 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -244,6 +244,7 @@ public: MessageState _msgState; Vocabulary *_vocabulary; + Kernel *_kernel; EngineState *successor; /**< Successor of this state: Used for restoring */ }; @@ -257,7 +258,7 @@ public: PaletteEntry get_pic_color(EngineState *s, int color); static inline reg_t not_register(EngineState *s, reg_t r) { - if (s->_vocabulary->_selectorMap.cantBeHere != -1) + if (s->_kernel->_selectorMap.cantBeHere != -1) return make_reg(0, !r.offset); else return r; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 9e070a5e4f..e796d0ae30 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -315,7 +315,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt Breakpoint *bp; char method_name [256]; - sprintf(method_name, "%s::%s", obj_get_name(s, send_obj), s->_vocabulary->getSelectorName(selector).c_str()); + sprintf(method_name, "%s::%s", obj_get_name(s, send_obj), s->_kernel->getSelectorName(selector).c_str()); bp = s->bp_list; while (bp) { @@ -1959,7 +1959,7 @@ static EngineState *_game_run(EngineState *s, int restoring) { script_init_engine(s, s->version); game_init(s); sfx_reset_player(); - _init_stack_base_with_selector(s, s->_vocabulary->_selectorMap.play); + _init_stack_base_with_selector(s, s->_kernel->_selectorMap.play); send_selector(s, s->game_obj, s->game_obj, s->stack_base, 2, s->stack_base); @@ -1979,7 +1979,7 @@ static EngineState *_game_run(EngineState *s, int restoring) { sciprintf("Restarting with replay()\n"); s->_executionStack.clear(); // Restart with replay - _init_stack_base_with_selector(s, s->_vocabulary->_selectorMap.replay); + _init_stack_base_with_selector(s, s->_kernel->_selectorMap.replay); send_selector(s, s->game_obj, s->game_obj, s->stack_base, 2, s->stack_base); } @@ -2000,7 +2000,7 @@ int game_run(EngineState **_s) { EngineState *s = *_s; sciprintf(" Calling %s::play()\n", s->_gameName.c_str()); - _init_stack_base_with_selector(s, s->_vocabulary->_selectorMap.play); // Call the play selector + _init_stack_base_with_selector(s, s->_kernel->_selectorMap.play); // Call the play selector // Now: Register the first element on the execution stack- if (!send_selector(s, s->game_obj, s->game_obj, s->stack_base, 2, s->stack_base)) { diff --git a/engines/sci/vocabulary.cpp b/engines/sci/vocabulary.cpp index 20b319bbdf..537f24974c 100644 --- a/engines/sci/vocabulary.cpp +++ b/engines/sci/vocabulary.cpp @@ -85,10 +85,9 @@ int vocab_get_class_count(ResourceManager *resmgr) { #endif -Vocabulary::Vocabulary(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr), _isOldSci0(isOldSci0) { +Vocabulary::Vocabulary(ResourceManager *resmgr) : _resmgr(resmgr) { _parserRules = NULL; _vocabVersion = kVocabularySCI0; - memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t debug(2, "Initializing vocabulary"); @@ -101,81 +100,15 @@ Vocabulary::Vocabulary(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr debug(2, "Assuming that this game does not use a parser."); _parserRules = NULL; } - - loadOpcodes(); - - if (!loadSelectorNames()) { - error("Vocabulary: Could not retrieve selector names"); - } - - // Map a few special selectors for later use - mapSelectors(); - - loadKernelNames(); } Vocabulary::~Vocabulary() { freeRuleList(_parserRules); _parserWords.clear(); - _selectorNames.clear(); - _opcodes.clear(); - _kernelNames.clear(); _parserBranches.clear(); freeSuffixes(); } -bool Vocabulary::loadSelectorNames() { - int count; - - Resource *r = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES, 0); - - if (!r) // No such resource? - return false; - - count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off - - for (int i = 0; i < count; i++) { - int offset = READ_LE_UINT16(r->data + 2 + i * 2); - int len = READ_LE_UINT16(r->data + offset); - - Common::String tmp((const char *)r->data + offset + 2, len); - _selectorNames.push_back(tmp); - - // Early SCI versions used the LSB in the selector ID as a read/write - // toggle. To compensate for that, we add every selector name twice. - if (_isOldSci0) - _selectorNames.push_back(tmp); - } - - return true; -} - -bool Vocabulary::loadOpcodes() { - int count, i = 0; - Resource* r = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_OPCODES, 0); - - _opcodes.clear(); - - // if the resource couldn't be loaded, leave - if (r == NULL) { - warning("unable to load vocab.%03d", VOCAB_RESOURCE_OPCODES); - return false; - } - - count = READ_LE_UINT16(r->data); - - _opcodes.resize(count); - for (i = 0; i < count; i++) { - int offset = READ_LE_UINT16(r->data + 2 + i * 2); - int len = READ_LE_UINT16(r->data + offset) - 2; - _opcodes[i].type = READ_LE_UINT16(r->data + offset + 2); - // QFG3 has empty opcodes - _opcodes[i].name = len > 0 ? Common::String((char *)r->data + offset + 4, len) : "Dummy"; - } - - return true; -} - bool Vocabulary::loadParserWords() { char currentword[256] = ""; // They're not going to use words longer than 255 ;-) @@ -533,7 +466,7 @@ void Vocabulary::printParserWords() const { con->DebugPrintf("\n"); } -int Vocabulary::findSelector(const char *selectorName) const { +int Kernel::findSelector(const char *selectorName) const { for (uint pos = 0; pos < _selectorNames.size(); ++pos) { if (_selectorNames[pos] == selectorName) return pos; @@ -544,7 +477,7 @@ int Vocabulary::findSelector(const char *selectorName) const { return -1; } -bool Vocabulary::hasKernelFunction(const char *functionName) const { +bool Kernel::hasKernelFunction(const char *functionName) const { Common::StringList::const_iterator it = Common::find(_kernelNames.begin(), _kernelNames.end(), functionName); return (it != _kernelNames.end()); } diff --git a/engines/sci/vocabulary.h b/engines/sci/vocabulary.h index 9382b79809..c8ed146917 100644 --- a/engines/sci/vocabulary.h +++ b/engines/sci/vocabulary.h @@ -42,12 +42,6 @@ class ResourceManager; /** Number of bytes allocated on the heap to store bad words if parsing fails */ #define PARSE_HEAP_SIZE 64 - -struct opcode { - int type; - Common::String name; -}; - enum { VOCAB_RESOURCE_CLASSES = 996, VOCAB_RESOURCE_SNAMES = 997, @@ -185,7 +179,7 @@ enum VocabularyVersions { class Vocabulary { public: - Vocabulary(ResourceManager *resmgr, bool isOldSci0); + Vocabulary(ResourceManager *resmgr); ~Vocabulary(); /** @@ -260,65 +254,8 @@ public: uint getParserBranchesSize() const { return _parserBranches.size(); } const parse_tree_branch_t &getParseTreeBranch(int number) const { return _parserBranches[number]; } - uint getOpcodesSize() const { return _opcodes.size(); } - const opcode &getOpcode(uint opcode) const { return _opcodes[opcode]; } - - uint getSelectorNamesSize() const { return _selectorNames.size(); } - const Common::String &getSelectorName(uint selector) const { return _selectorNames[selector]; } - - /* Determines the selector ID of a selector by its name - ** (const char *) selectorName: Name of the selector to look up - ** Returns : (int) The appropriate selector ID, or -1 on error - */ - int findSelector(const char *selectorName) const; - - /* Detects whether a particular kernel function is required in the game - ** (const char *) functionName: The name of the desired kernel function - ** Returns : (bool) true if the kernel function is listed in the kernel table, - ** false otherwise - */ - bool hasKernelFunction(const char *functionName) const; - - uint getKernelNamesSize() const { return _kernelNames.size(); } - const Common::String &getKernelName(uint number) const { return _kernelNames[number]; } - - // Script dissection/dumping functions - void dissectScript(int scriptNumber); - void dumpScriptObject(char *data, int seeker, int objsize); - void dumpScriptClass(char *data, int seeker, int objsize); - - selector_map_t _selectorMap; /**< Shortcut list for important selectors */ - private: /** - * Loads the vocabulary selector names. - * Returns true upon success, false otherwise. - */ - bool loadSelectorNames(); - - /* Maps special selectors - ** Returns : (void) - */ - void mapSelectors(); - - /** - * Loads the opcode names (only used for debugging). - * @return true on success, false on failure - */ - bool loadOpcodes(); - - /** - * Loads the kernel function names. - * - * This function reads the kernel function name table from resource_map, - * and fills the _kernelNames array with them. - * The resulting list has the same format regardless of the format of the - * name table of the resource (the format changed between version 0 and 1). - * @return true on success, false on failure - */ - bool loadKernelNames(); - - /** * Loads all words from the main vocabulary. * @return true on success, false on failure */ @@ -349,16 +286,8 @@ private: void freeRuleList(parse_rule_list_t *rule_list); ResourceManager *_resmgr; - bool _isOldSci0; VocabularyVersions _vocabVersion; - // Kernel-related lists - // List of opcodes, loaded from vocab.998. This list is only used for debugging - // purposes, as we hardcode the list of opcodes in the sci_opcodes enum (script.h) - Common::Array<opcode> _opcodes; - Common::StringList _selectorNames; - Common::StringList _kernelNames; - // Parser-related lists SuffixList _parserSuffixes; parse_rule_list_t *_parserRules; /**< GNF rules used in the parser algorithm */ |