aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/console.cpp83
-rw-r--r--engines/sci/console.h2
-rw-r--r--engines/sci/engine/kmovement.cpp9
-rw-r--r--engines/sci/engine/seg_manager.cpp77
-rw-r--r--engines/sci/engine/seg_manager.h13
-rw-r--r--engines/sci/engine/state.cpp9
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;