SCI: Add SegManager::findObjectByName() method, make parse_reg_t() local to console.cpp, and switch other code using it to use findObjectByName() instead.
svn-id: r44628
This commit is contained in:
parent
07353be65a
commit
0da9ad5ff5
6 changed files with 110 additions and 83 deletions
|
@ -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, ':');
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue