diff options
author | Filippos Karapetis | 2009-05-30 10:22:53 +0000 |
---|---|---|
committer | Filippos Karapetis | 2009-05-30 10:22:53 +0000 |
commit | 56c0a41b71256118eda1ffa08f2317aba673faf9 (patch) | |
tree | 90a119557e31581489fe4b368ff3cc8883959287 /engines/sci/engine/kmovement.cpp | |
parent | 4960b64b484d3e80258feedea3f711704d7e0743 (diff) | |
download | scummvm-rg350-56c0a41b71256118eda1ffa08f2317aba673faf9.tar.gz scummvm-rg350-56c0a41b71256118eda1ffa08f2317aba673faf9.tar.bz2 scummvm-rg350-56c0a41b71256118eda1ffa08f2317aba673faf9.zip |
SCI: Moved the rest of the console code out of sciconsole.cpp and into console.cpp. "list" and "hexgrep" have been added to the console commands. parse_reg_t() has been moved to kmovement.cpp (as it's the only code using it). Note that the debug commands in scriptdebug.cpp have not been converted yet, so they don't work at the moment
svn-id: r41024
Diffstat (limited to 'engines/sci/engine/kmovement.cpp')
-rw-r--r-- | engines/sci/engine/kmovement.cpp | 197 |
1 files changed, 196 insertions, 1 deletions
diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 5e3da6403b..9a80b3c99f 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -239,7 +239,202 @@ enum Movecnt { static Movecnt handle_movecnt = UNINITIALIZED; // FIXME: Avoid static vars -int parse_reg_t(EngineState *s, const char *str, reg_t *dest); +/** + * Address parameters may be passed in one of three forms: + * - ssss:oooo -- where 'ssss' denotes a segment and 'oooo' an offset. + * Example: "a:c5" would address something in segment 0xa at offset 0xc5. + * - &scr:oooo -- where 'scr' is a script number and oooo an offset within that script; will + * fail if the script is not currently loaded + * - $REG -- where 'REG' is one of 'PC', 'ACC', 'PREV' or 'OBJ': References the address + * indicated by the register of this name. + * - $REG+n (or -n) -- Like $REG, but modifies the offset part by a specific amount (which + * is specified in hexadecimal). + * - ?obj -- Looks up an object with the specified name, uses its address. This will abort if + * the object name is ambiguous; in that case, a list of addresses and indices is provided. + * ?obj.idx may be used to disambiguate 'obj' by the index 'idx'. +**/ +int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on success + int rel_offsetting = 0; + const char *offsetting = NULL; + // Non-NULL: Parse end of string for relative offsets + char *endptr; + + if (*str == '$') { // Register + rel_offsetting = 1; + + if (!scumm_strnicmp(str + 1, "PC", 2)) { + *dest = s->_executionStack.back().addr.pc; + offsetting = str + 3; + } else if (!scumm_strnicmp(str + 1, "P", 1)) { + *dest = s->_executionStack.back().addr.pc; + offsetting = str + 2; + } else if (!scumm_strnicmp(str + 1, "PREV", 4)) { + *dest = s->r_prev; + offsetting = str + 5; + } else if (!scumm_strnicmp(str + 1, "ACC", 3)) { + *dest = s->r_acc; + offsetting = str + 4; + } else if (!scumm_strnicmp(str + 1, "A", 1)) { + *dest = s->r_acc; + offsetting = str + 2; + } else if (!scumm_strnicmp(str + 1, "OBJ", 3)) { + *dest = s->_executionStack.back().objp; + offsetting = str + 4; + } else if (!scumm_strnicmp(str + 1, "O", 1)) { + *dest = s->_executionStack.back().objp; + offsetting = str + 2; + } else + return 1; // No matching register + + if (!*offsetting) + offsetting = NULL; + else if (*offsetting != '+' && *offsetting != '-') + return 1; + } else if (*str == '&') { + int script_nr; + // Look up by script ID + char *colon = (char *)strchr(str, ':'); + + if (!colon) + return 1; + *colon = 0; + offsetting = colon + 1; + + script_nr = strtol(str + 1, &endptr, 10); + + if (*endptr) + return 1; + + dest->segment = s->seg_manager->segGet(script_nr); + + if (!dest->segment) { + return 1; + } + } else if (*str == '?') { + int index = -1; + int times_found = 0; + char *tmp; + const char *str_objname; + char *str_suffix; + char suffchar = 0; + uint i; + // Parse obj by name + + tmp = (char *)strchr(str, '+'); + str_suffix = (char *)strchr(str, '-'); + if (tmp < str_suffix) + str_suffix = tmp; + if (str_suffix) { + suffchar = (*str_suffix); + *str_suffix = 0; + } + + tmp = (char *)strchr(str, '.'); + + if (tmp) { + *tmp = 0; + index = strtol(tmp + 1, &endptr, 16); + if (*endptr) + return -1; + } + + str_objname = str + 1; + + // Now all values are available; iterate over all objects. + for (i = 0; i < s->seg_manager->_heap.size(); i++) { + MemObject *mobj = s->seg_manager->_heap[i]; + int idx = 0; + int max_index = 0; + + if (mobj) { + if (mobj->getType() == MEM_OBJ_SCRIPT) + max_index = (*(Script *)mobj)._objects.size(); + else if (mobj->getType() == MEM_OBJ_CLONES) + max_index = (*(CloneTable *)mobj)._table.size(); + } + + while (idx < max_index) { + int valid = 1; + Object *obj = NULL; + reg_t objpos; + objpos.offset = 0; + objpos.segment = i; + + if (mobj->getType() == MEM_OBJ_SCRIPT) { + obj = &(*(Script *)mobj)._objects[idx]; + objpos.offset = obj->pos.offset; + } else if (mobj->getType() == MEM_OBJ_CLONES) { + obj = &((*(CloneTable *)mobj)._table[idx]); + objpos.offset = idx; + valid = ((CloneTable *)mobj)->isValidEntry(idx); + } + + if (valid) { + const char *objname = obj_get_name(s, objpos); + if (!strcmp(objname, str_objname)) { + // Found a match! + if ((index < 0) && (times_found > 0)) { + if (times_found == 1) { + // First time we realized the ambiguity + sciprintf("Ambiguous:\n"); + sciprintf(" %3x: [%04x:%04x] %s\n", 0, PRINT_REG(*dest), str_objname); + } + sciprintf(" %3x: [%04x:%04x] %s\n", times_found, PRINT_REG(objpos), str_objname); + } + if (index < 0 || times_found == index) + *dest = objpos; + ++times_found; + } + } + ++idx; + } + + } + + if (!times_found) + return 1; + + if (times_found > 1 && index < 0) { + sciprintf("Ambiguous: Aborting.\n"); + return 1; // Ambiguous + } + + if (times_found <= index) + return 1; // Not found + + offsetting = str_suffix; + if (offsetting) + *str_suffix = suffchar; + rel_offsetting = 1; + } else { + char *colon = (char *)strchr(str, ':'); + + if (!colon) { + offsetting = str; + dest->segment = 0; + } else { + *colon = 0; + offsetting = colon + 1; + + dest->segment = strtol(str, &endptr, 16); + if (*endptr) + return 1; + } + } + if (offsetting) { + int val = strtol(offsetting, &endptr, 16); + + if (rel_offsetting) + dest->offset += val; + else + dest->offset = val; + + if (*endptr) + return 1; + } + + return 0; +} static int checksum_bytes(byte *data, int size) { int result = 0; |