diff options
-rw-r--r-- | engines/sci/console.cpp | 83 | ||||
-rw-r--r-- | engines/sci/console.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/kmovement.cpp | 9 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.cpp | 77 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.h | 13 | ||||
-rw-r--r-- | engines/sci/engine/state.cpp | 9 |
6 files changed, 110 insertions, 83 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 7537d29549..a7eaa69118 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -50,6 +50,9 @@ int g_debug_sleeptime_factor = 1; int g_debug_simulated_key = 0; bool g_debug_track_mouse_clicks = false; +// Refer to the "addresses" command on how to pass address parameters +static int parse_reg_t(EngineState *s, const char *str, reg_t *dest); + Console::Console(SciEngine *vm) : GUI::Debugger() { _vm = vm; @@ -2720,7 +2723,7 @@ bool Console::cmdAddresses(int argc, const char **argv) { } // Returns 0 on success -int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { +static int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Pointer to the part of str which contains a numeric offset (if any) const char *offsetStr = NULL; @@ -2787,6 +2790,9 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // The (optional) index can be used to distinguish multiple object with the same name. int index = -1; + // Skip over the leading question mark '?' + str++; + // Look for an offset. It starts with + or - relativeOffset = true; offsetStr = strchr(str, '+'); @@ -2795,10 +2801,10 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Strip away the offset and the leading '?' Common::String str_objname; - if (offsetStr) { - str_objname = Common::String(str + 1, offsetStr); - } else - str_objname = str + 1; + if (offsetStr) + str_objname = Common::String(str, offsetStr); + else + str_objname = str; // Scan for a period, after which (if present) we'll find an index @@ -2812,74 +2818,11 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { } // Now all values are available; iterate over all objects. - int times_found = 0; - for (uint i = 0; i < s->segMan->_heap.size(); i++) { - SegmentObj *mobj = s->segMan->_heap[i]; - int idx = 0; - int max_index = 0; - ObjMap::iterator it; - Script *scr = 0; - CloneTable *ct = 0; - - if (mobj) { - if (mobj->getType() == SEG_TYPE_SCRIPT) { - scr = (Script *)mobj; - max_index = scr->_objects.size(); - it = scr->_objects.begin(); - } else if (mobj->getType() == SEG_TYPE_CLONES) { - ct = (CloneTable *)mobj; - max_index = ct->_table.size(); - } - } - // It's a script or a clone table, scan all objects in it - for (; idx < max_index; ++idx) { - Object *obj = NULL; - reg_t objpos; - objpos.offset = 0; - objpos.segment = i; - - if (mobj->getType() == SEG_TYPE_SCRIPT) { - obj = &(it->_value); - objpos.offset = obj->_pos.offset; - ++it; - } else if (mobj->getType() == SEG_TYPE_CLONES) { - if (!ct->isValidEntry(idx)) - continue; - obj = &(ct->_table[idx]); - objpos.offset = idx; - } - - const char *objname = s->segMan->getObjectName(objpos); - if (str_objname == objname) { - // Found a match! - if ((index < 0) && (times_found > 0)) { - if (times_found == 1) { - // First time we realized the ambiguity - printf("Ambiguous:\n"); - printf(" %3x: [%04x:%04x] %s\n", 0, PRINT_REG(*dest), str_objname.c_str()); - } - printf(" %3x: [%04x:%04x] %s\n", times_found, PRINT_REG(objpos), str_objname.c_str()); - } - if (index < 0 || times_found == index) - *dest = objpos; - ++times_found; - } - } - - } - - if (!times_found) + *dest = s->segMan->findObjectByName(str_objname, index); + if (dest->isNull()) return 1; - if (times_found > 1 && index < 0) { - printf("Ambiguous: Aborting.\n"); - return 1; // Ambiguous - } - - if (times_found <= index) - return 1; // Not found - } else { // Finally, check for "SEGMENT:OFFSET" or just "OFFSET" const char *colon = strchr(str, ':'); diff --git a/engines/sci/console.h b/engines/sci/console.h index 70eeb08f16..f330a05a77 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -36,8 +36,6 @@ namespace Sci { class SciEngine; struct List; -// Refer to the "addresses" command on how to pass address parameters -int parse_reg_t(EngineState *s, const char *str, reg_t *dest); reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode); class Console : public GUI::Debugger { diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 3a21704469..43cba3eb4d 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -24,7 +24,6 @@ */ #include "sci/sci.h" -#include "sci/console.h" // for parse_reg_t #include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" @@ -256,10 +255,10 @@ static int checksum_bytes(byte *data, int size) { } static void bresenham_autodetect(EngineState *s) { - reg_t motion_class; + reg_t motionClass = s->segMan->findObjectByName("Motion"); - if (!parse_reg_t(s, "?Motion", &motion_class)) { - Object *obj = s->segMan->getObject(motion_class); + if (!motionClass.isNull()) { + Object *obj = s->segMan->getObject(motionClass); reg_t fptr; byte *buf; @@ -269,7 +268,7 @@ static void bresenham_autodetect(EngineState *s) { return; } - if (lookup_selector(s->segMan, motion_class, s->_kernel->_selectorCache.doit, NULL, &fptr) != kSelectorMethod) { + if (lookup_selector(s->segMan, motionClass, s->_kernel->_selectorCache.doit, NULL, &fptr) != kSelectorMethod) { warning("bresenham_autodetect failed"); handle_movecnt = INCREMENT_MOVECNT; // Most games do this, so best guess return; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 43c48e3988..b8412da8fb 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -272,6 +272,81 @@ const char *SegManager::getObjectName(reg_t pos) { return name; } +reg_t SegManager::findObjectByName(const Common::String &name, int index) { + reg_t retVal = NULL_REG; + + // Now all values are available; iterate over all objects. + int timesFound = 0; + for (uint i = 0; i < _heap.size(); i++) { + SegmentObj *mobj = _heap[i]; + int idx = 0; + int max_index = 0; + ObjMap::iterator it; + Script *scr = 0; + CloneTable *ct = 0; + + if (mobj) { + if (mobj->getType() == SEG_TYPE_SCRIPT) { + scr = (Script *)mobj; + max_index = scr->_objects.size(); + it = scr->_objects.begin(); + } else if (mobj->getType() == SEG_TYPE_CLONES) { + ct = (CloneTable *)mobj; + max_index = ct->_table.size(); + } + } + + // It's a script or a clone table, scan all objects in it + for (; idx < max_index; ++idx) { + Object *obj = NULL; + reg_t objpos; + objpos.offset = 0; + objpos.segment = i; + + if (mobj->getType() == SEG_TYPE_SCRIPT) { + obj = &(it->_value); + objpos.offset = obj->_pos.offset; + ++it; + } else if (mobj->getType() == SEG_TYPE_CLONES) { + if (!ct->isValidEntry(idx)) + continue; + obj = &(ct->_table[idx]); + objpos.offset = idx; + } + + const char *objname = getObjectName(objpos); + if (name == objname) { + // Found a match! + if ((index < 0) && (timesFound > 0)) { + if (timesFound == 1) { + // First time we realized the ambiguity + printf("Ambiguous:\n"); + printf(" %3x: [%04x:%04x] %s\n", 0, PRINT_REG(retVal), name.c_str()); + } + printf(" %3x: [%04x:%04x] %s\n", timesFound, PRINT_REG(objpos), name.c_str()); + } + if (index < 0 || timesFound == index) + retVal = objpos; + ++timesFound; + } + } + + } + + if (!timesFound) + return NULL_REG; + + if (timesFound > 1 && index < 0) { + printf("Ambiguous: Aborting.\n"); + return NULL_REG; // Ambiguous + } + + if (timesFound <= index) + return NULL_REG; // Not found + + return retVal; +} + // validate the seg // return: // false - invalid seg @@ -623,7 +698,7 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { #if 0 if (obj->_variables[5].offset != 0xffff) { obj->_variables[5] = INST_LOOKUP_CLASS(obj->_variables[5].offset); - base_obj = s->segMan->getObject(obj->_variables[5]); + base_obj = getObject(obj->_variables[5]); obj->variable_names_nr = base_obj->variables_nr; obj->base_obj = base_obj->base_obj; } diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index c8b99764bf..6226d1ce76 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -419,6 +419,19 @@ public: */ const char *getObjectName(reg_t pos); + /** + * Find the address of an object by its name. In case multiple objects + * with the same name occur, the optional index parameter can be used + * to distinguish between them. If index is -1, then if there is a + * unique object with the specified name, its address is returned; + * if there are multiple matches, or none, then NULL_REG is returned. + * + * @param name the name of the object we are looking for + * @param index the index of the object in case there are multiple + * @return the address of the object, or NULL_REG + */ + reg_t findObjectByName(const Common::String &name, int index = -1); + void scriptRelocateExportsSci11(SegmentId seg); void scriptInitialiseObjectsSci11(SegmentId seg); diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index effaac0ca5..d9671239dc 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -26,7 +26,6 @@ #include "sci/engine/state.h" #include "sci/engine/vm.h" #include "sci/engine/script.h" -#include "sci/console.h" // For parse_reg_t namespace Sci { @@ -266,9 +265,9 @@ int EngineState::methodChecksum(reg_t objAddress, Selector sel, int offset, uint SciVersion EngineState::detectDoSoundType() { if (_doSoundType == SCI_VERSION_AUTODETECT) { - reg_t soundClass; + reg_t soundClass = segMan->findObjectByName("Sound"); - if (!parse_reg_t(this, "?Sound", &soundClass)) { + if (!soundClass.isNull()) { int sum = methodChecksum(soundClass, _kernel->_selectorCache.play, -6, 6); switch (sum) { @@ -337,10 +336,10 @@ SciVersion EngineState::detectLofsType() { return _lofsType; } - reg_t gameClass; Object *obj = NULL; + reg_t gameClass = segMan->findObjectByName("Game"); - if (!parse_reg_t(this, "?Game", &gameClass)) + if (!gameClass.isNull()) obj = segMan->getObject(gameClass); bool couldBeAbs = true; |