aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorFilippos Karapetis2009-06-02 21:07:34 +0000
committerFilippos Karapetis2009-06-02 21:07:34 +0000
commitac544e73e96fee97bbb8f0231392a6efdf279b92 (patch)
treefafa61f123931bd47acfe861b73ca5b770b418bd /engines/sci
parent780926991e369cefd2409a1149f3bcee4aa9a5c9 (diff)
downloadscummvm-rg350-ac544e73e96fee97bbb8f0231392a6efdf279b92.tar.gz
scummvm-rg350-ac544e73e96fee97bbb8f0231392a6efdf279b92.tar.bz2
scummvm-rg350-ac544e73e96fee97bbb8f0231392a6efdf279b92.zip
Moved some more console commands to ScummVM's debug console
svn-id: r41127
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/console.cpp421
-rw-r--r--engines/sci/console.h10
-rw-r--r--engines/sci/engine/kmovement.cpp198
-rw-r--r--engines/sci/engine/scriptdebug.cpp138
4 files changed, 422 insertions, 345 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index df8ca8f1ce..a62101d0a3 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -32,6 +32,7 @@
#include "sci/engine/savegame.h"
#include "sci/engine/state.h"
#include "sci/engine/gc.h"
+#include "sci/engine/kernel_types.h" // for determine_reg_type
#include "sci/gfx/gfx_gui.h" // for sciw_set_status_bar
#include "sci/gfx/gfx_state_internal.h"
#include "sci/gfx/gfx_widgets.h" // for getPort
@@ -51,6 +52,190 @@ int _kdebug_cheap_event_hack = 0;
bool _kdebug_track_mouse_clicks = false;
int _weak_validations = 1; // Some validation errors are reduced to warnings if non-0
+
+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
+ printf("Ambiguous:\n");
+ printf(" %3x: [%04x:%04x] %s\n", 0, PRINT_REG(*dest), str_objname);
+ }
+ printf(" %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) {
+ printf("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;
+}
+
Console::Console(SciEngine *vm) : GUI::Debugger() {
_vm = vm;
@@ -60,7 +245,6 @@ Console::Console(SciEngine *vm) : GUI::Debugger() {
DCmd_Register("selectors", WRAP_METHOD(Console, cmdSelectors));
DCmd_Register("kernel_names", WRAP_METHOD(Console, cmdKernelNames));
DCmd_Register("registers", WRAP_METHOD(Console, cmdRegisters));
- DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript));
DCmd_Register("weak_validations", WRAP_METHOD(Console, cmdWeakValidations));
// Parser
DCmd_Register("suffixes", WRAP_METHOD(Console, cmdSuffixes));
@@ -113,17 +297,26 @@ Console::Console(SciEngine *vm) : GUI::Debugger() {
DCmd_Register("gc", WRAP_METHOD(Console, cmdGCInvoke));
DCmd_Register("gc_objects", WRAP_METHOD(Console, cmdGCObjects));
DCmd_Register("gc_interval", WRAP_METHOD(Console, cmdGCInterval));
- // VM
- DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist));
- DCmd_Register("stack", WRAP_METHOD(Console, cmdStack));
- DCmd_Register("sleep_factor", WRAP_METHOD(Console, cmdSleepFactor));
- DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps));
- DCmd_Register("exit", WRAP_METHOD(Console, cmdExit));
+ DCmd_Register("gc_reachable", WRAP_METHOD(Console, cmdGCShowReachable));
+ DCmd_Register("gc_freeable", WRAP_METHOD(Console, cmdGCShowFreeable));
+ DCmd_Register("gc_normalize", WRAP_METHOD(Console, cmdGCNormalize));
// Music/SFX
DCmd_Register("songlib", WRAP_METHOD(Console, cmdSongLib));
DCmd_Register("is_sample", WRAP_METHOD(Console, cmdIsSample));
DCmd_Register("sfx01_header", WRAP_METHOD(Console, cmdSfx01Header));
DCmd_Register("sfx01_track", WRAP_METHOD(Console, cmdSfx01Track));
+ DCmd_Register("stop_sfx", WRAP_METHOD(Console, cmdStopSfx));
+ // Script
+ DCmd_Register("addresses", WRAP_METHOD(Console, cmdAddresses));
+ DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript));
+ DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps));
+ DCmd_Register("set_acc", WRAP_METHOD(Console, cmdSetAccumulator));
+ // VM
+ DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist));
+ DCmd_Register("stack", WRAP_METHOD(Console, cmdStack));
+ DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType));
+ DCmd_Register("sleep_factor", WRAP_METHOD(Console, cmdSleepFactor));
+ DCmd_Register("exit", WRAP_METHOD(Console, cmdExit));
// These were in sci.cpp
/*
@@ -219,16 +412,16 @@ bool Console::cmdRegisters(int argc, const char **argv) {
DebugPrintf("Current register values:\n");
#if 0
// TODO: p_restadjust
- sciprintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(g_EngineState->r_acc), PRINT_REG(g_EngineState->r_prev), *p_restadjust);
+ DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(g_EngineState->r_acc), PRINT_REG(g_EngineState->r_prev), *p_restadjust);
#endif
if (!g_EngineState->_executionStack.empty()) {
#if 0
// TODO: p_pc, p_objp, p_pp, p_sp
- sciprintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", PRINT_REG(*p_pc), PRINT_REG(*p_objp), PRINT_STK(*p_pp), PRINT_STK(*p_sp));
+ DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", PRINT_REG(*p_pc), PRINT_REG(*p_objp), PRINT_STK(*p_pp), PRINT_STK(*p_sp));
#endif
} else
- sciprintf("<no execution stack: pc,obj,fp omitted>\n");
+ DebugPrintf("<no execution stack: pc,obj,fp omitted>\n");
return true;
}
@@ -1324,6 +1517,99 @@ bool Console::cmdGCInterval(int argc, const char **argv) {
return true;
}
+// TODO/FIXME: This should be using DebugPrintf
+void _print_address(void * _, reg_t addr) {
+ if (addr.segment)
+ sciprintf(" %04x:%04x\n", PRINT_REG(addr));
+}
+
+bool Console::cmdGCShowReachable(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n");
+ DebugPrintf("Usage: %s <address>\n", argv[0]);
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ reg_t addr;
+
+ if (parse_reg_t(g_EngineState, argv[1], &addr)) {
+ DebugPrintf("Invalid address passed.\n");
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ MemObject *mobj = GET_SEGMENT_ANY(*g_EngineState->seg_manager, addr.segment);
+ if (!mobj) {
+ DebugPrintf("Unknown segment : %x\n", addr.segment);
+ return 1;
+ }
+
+ DebugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr));
+ mobj->listAllOutgoingReferences(g_EngineState, addr, NULL, _print_address);
+
+ return true;
+}
+
+bool Console::cmdGCShowFreeable(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Prints all addresses freeable in the segment associated with the\n");
+ DebugPrintf("given address (offset is ignored).\n");
+ DebugPrintf("Usage: %s <address>\n", argv[0]);
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ reg_t addr;
+
+ if (parse_reg_t(g_EngineState, argv[1], &addr)) {
+ DebugPrintf("Invalid address passed.\n");
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ MemObject *mobj = GET_SEGMENT_ANY(*g_EngineState->seg_manager, addr.segment);
+ if (!mobj) {
+ DebugPrintf("Unknown segment : %x\n", addr.segment);
+ return true;
+ }
+
+ DebugPrintf("Freeable in segment %04x:\n", addr.segment);
+ mobj->listAllDeallocatable(addr.segment, NULL, _print_address);
+
+ return true;
+}
+
+bool Console::cmdGCNormalize(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Prints the \"normal\" address of a given address,\n");
+ DebugPrintf("i.e. the address we would free in order to free\n");
+ DebugPrintf("the object associated with the original address.\n");
+ DebugPrintf("Usage: %s <address>\n", argv[0]);
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ reg_t addr;
+
+ if (parse_reg_t(g_EngineState, argv[1], &addr)) {
+ DebugPrintf("Invalid address passed.\n");
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ MemObject *mobj = GET_SEGMENT_ANY(*g_EngineState->seg_manager, addr.segment);
+ if (!mobj) {
+ DebugPrintf("Unknown segment : %x\n", addr.segment);
+ return true;
+ }
+
+ addr = mobj->findCanonicAddress(g_EngineState->seg_manager, addr);
+ DebugPrintf(" %04x:%04x\n", PRINT_REG(addr));
+
+ return true;
+}
+
bool Console::cmdVMVarlist(int argc, const char **argv) {
const char *varnames[] = {"global", "local", "temp", "param"};
@@ -1368,6 +1654,52 @@ bool Console::cmdStack(int argc, const char **argv) {
return true;
}
+bool Console::cmdValueType(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Determines the type of a value.\n");
+ DebugPrintf("The type can be one of the following:\n");
+ DebugPrintf("Invalid, list, object, reference or arithmetic\n");
+ DebugPrintf("Usage: %s <address>\n", argv[0]);
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ reg_t val;
+
+ if (parse_reg_t(g_EngineState, argv[1], &val)) {
+ DebugPrintf("Invalid address passed.\n");
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ int t = determine_reg_type(g_EngineState, val, 1);
+ int invalid = t & KSIG_INVALID;
+
+ switch (t & ~KSIG_INVALID) {
+ case 0:
+ DebugPrintf("Invalid");
+ break;
+ case KSIG_LIST:
+ DebugPrintf("List");
+ break;
+ case KSIG_OBJECT:
+ DebugPrintf("Object");
+ break;
+ case KSIG_REF:
+ DebugPrintf("Reference");
+ break;
+ case KSIG_ARITHMETIC:
+ DebugPrintf("Arithmetic");
+ break;
+ default:
+ DebugPrintf("Erroneous unknown type %02x(%d decimal)\n", t, t);
+ }
+
+ DebugPrintf("%s\n", invalid ? " (invalid)" : "");
+
+ return true;
+}
+
bool Console::cmdSleepFactor(int argc, const char **argv) {
if (argc != 2) {
DebugPrintf("Factor to multiply with wait times in kWait().\n");
@@ -1388,6 +1720,27 @@ bool Console::cmdScriptSteps(int argc, const char **argv) {
return true;
}
+bool Console::cmdSetAccumulator(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Sets the accumulator.\n");
+ DebugPrintf("Usage: %s <address>\n", argv[0]);
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ reg_t val;
+
+ if (parse_reg_t(g_EngineState, argv[1], &val)) {
+ DebugPrintf("Invalid address passed.\n");
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ g_EngineState->r_acc = val;
+
+ return true;
+}
+
bool Console::cmdIsSample(int argc, const char **argv) {
if (argc != 2) {
DebugPrintf("Tests whether a given sound resource is a PCM sample, \n");
@@ -1613,6 +1966,37 @@ bool Console::cmdSfx01Track(int argc, const char **argv) {
return true;
}
+bool Console::cmdStopSfx(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Stops a playing sound\n");
+ DebugPrintf("Usage: %s <address>\n", argv[0]);
+ DebugPrintf("Where <address> is the address of the sound to stop.\n");
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ reg_t id;
+
+ if (parse_reg_t(g_EngineState, argv[1], &id)) {
+ DebugPrintf("Invalid address passed.\n");
+ DebugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ int handle = id.segment << 16 | id.offset; // frobnicate handle
+ EngineState* s = g_EngineState; // for PUT_SEL32V
+
+ if (id.segment) {
+ g_EngineState->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
+ g_EngineState->_sound.sfx_remove_song(handle);
+ PUT_SEL32V(id, signal, -1);
+ PUT_SEL32V(id, nodePtr, 0);
+ PUT_SEL32V(id, handle, 0);
+ }
+
+ return true;
+}
+
bool Console::cmdExit(int argc, const char **argv) {
if (argc != 2) {
DebugPrintf("%s game - exit gracefully\n", argv[0]);
@@ -1635,4 +2019,21 @@ bool Console::cmdExit(int argc, const char **argv) {
return false;
}
+bool Console::cmdAddresses(int argc, const char **argv) {
+ DebugPrintf("Address parameters may be passed in one of three forms:\n");
+ DebugPrintf(" - ssss:oooo -- where 'ssss' denotes a segment and 'oooo' an offset.\n");
+ DebugPrintf(" Example: \"a:c5\" would address something in segment 0xa at offset 0xc5.\n");
+ DebugPrintf(" - &scr:oooo -- where 'scr' is a script number and oooo an offset within that script; will\n");
+ DebugPrintf(" fail if the script is not currently loaded\n");
+ DebugPrintf(" - $REG -- where 'REG' is one of 'PC', 'ACC', 'PREV' or 'OBJ': References the address\n");
+ DebugPrintf(" indicated by the register of this name.\n");
+ DebugPrintf(" - $REG+n (or -n) -- Like $REG, but modifies the offset part by a specific amount (which\n");
+ DebugPrintf(" is specified in hexadecimal).\n");
+ DebugPrintf(" - ?obj -- Looks up an object with the specified name, uses its address. This will abort if\n");
+ DebugPrintf(" the object name is ambiguous; in that case, a list of addresses and indices is provided.\n");
+ DebugPrintf(" ?obj.idx may be used to disambiguate 'obj' by the index 'idx'.\n");
+
+ return true;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/console.h b/engines/sci/console.h
index 652079556e..c7c0d0fb22 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -34,6 +34,9 @@ namespace Sci {
class SciEngine;
+// Refer to the "addresses" command on how to pass address parameters
+int parse_reg_t(EngineState *s, const char *str, reg_t *dest);
+
class Console : public GUI::Debugger {
public:
Console(SciEngine *vm);
@@ -92,14 +95,21 @@ private:
bool cmdGCInvoke(int argc, const char **argv);
bool cmdGCObjects(int argc, const char **argv);
bool cmdGCInterval(int argc, const char **argv);
+ bool cmdGCShowReachable(int argc, const char **argv);
+ bool cmdGCShowFreeable(int argc, const char **argv);
+ bool cmdGCNormalize(int argc, const char **argv);
bool cmdVMVarlist(int argc, const char **argv);
bool cmdStack(int argc, const char **argv);
+ bool cmdValueType(int argc, const char **argv);
bool cmdSleepFactor(int argc, const char **argv);
bool cmdIsSample(int argc, const char **argv);
bool cmdSfx01Header(int argc, const char **argv);
bool cmdSfx01Track(int argc, const char **argv);
bool cmdScriptSteps(int argc, const char **argv);
+ bool cmdSetAccumulator(int argc, const char **argv);
bool cmdExit(int argc, const char **argv);
+ bool cmdAddresses(int argc, const char **argv);
+ bool cmdStopSfx(int argc, const char **argv);
bool segmentInfo(int nr);
void printList(List *l);
diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp
index 4f7d770d0f..cd4307678b 100644
--- a/engines/sci/engine/kmovement.cpp
+++ b/engines/sci/engine/kmovement.cpp
@@ -24,6 +24,7 @@
*/
#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"
@@ -239,203 +240,6 @@ enum Movecnt {
static Movecnt handle_movecnt = UNINITIALIZED; // FIXME: Avoid non-const global vars
-/**
- * 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;
int i;
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 5d353eab48..86d05989fb 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -1069,11 +1069,6 @@ static int c_go(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
return 0;
}
-static int c_set_acc(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- s->r_acc = cmdParams[0].reg;
- return 0;
-}
-
static int c_send(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
reg_t object = cmdParams[0].reg;
const char *selector_name = cmdParams[1].str;
@@ -1131,30 +1126,6 @@ static int c_send(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
}
-struct generic_config_flag_t {
- const char *name;
- const char option;
- unsigned int flag;
-};
-
-#define SFX_DEBUG_MODES 2
-#define FROBNICATE_HANDLE(reg) ((reg).segment << 16 | (reg).offset)
-
-static int c_sfx_remove(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- reg_t id = cmdParams[0].reg;
- int handle = FROBNICATE_HANDLE(id);
-
- if (id.segment) {
- s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- s->_sound.sfx_remove_song(handle);
- PUT_SEL32V(id, signal, -1);
- PUT_SEL32V(id, nodePtr, 0);
- PUT_SEL32V(id, handle, 0);
- }
-
- return 0;
-}
-
#define GETRECT(ll, rr, tt, bb) \
ll = GET_SELECTOR(pos, ll); \
rr = GET_SELECTOR(pos, rr); \
@@ -1427,90 +1398,6 @@ int c_se(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
return 0;
}
-int c_type(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- int t = determine_reg_type(s, cmdParams[0].reg, 1);
- int invalid = t & KSIG_INVALID;
-
- switch (t & ~KSIG_INVALID) {
- case 0:
- sciprintf("Invalid");
- break;
-
- case KSIG_LIST:
- sciprintf("List");
- break;
-
- case KSIG_OBJECT:
- sciprintf("Object");
- break;
-
- case KSIG_REF:
- sciprintf("Reference");
- break;
-
- case KSIG_ARITHMETIC:
- sciprintf("Arithmetic");
- break;
-
- default:
- sciprintf("Erroneous unknown type %02x(%d decimal)\n", t, t);
- }
-
- sciprintf("%s\n", invalid ? " (invalid)" : "");
-
- return 0;
-}
-
-static void _print_address(void * _, reg_t addr) {
- if (addr.segment)
- sciprintf(" %04x:%04x\n", PRINT_REG(addr));
-}
-
-static int c_gc_show_reachable(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- reg_t addr = cmdParams[0].reg;
-
- MemObject *mobj = GET_SEGMENT_ANY(*s->seg_manager, addr.segment);
- if (!mobj) {
- sciprintf("Unknown segment : %x\n", addr.segment);
- return 1;
- }
-
- sciprintf("Reachable from %04x:%04x:\n", PRINT_REG(addr));
- mobj->listAllOutgoingReferences(s, addr, NULL, _print_address);
-
- return 0;
-}
-
-static int c_gc_show_freeable(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- reg_t addr = cmdParams[0].reg;
-
- MemObject *mobj = GET_SEGMENT_ANY(*s->seg_manager, addr.segment);
- if (!mobj) {
- sciprintf("Unknown segment : %x\n", addr.segment);
- return 1;
- }
-
- sciprintf("Freeable in segment %04x:\n", addr.segment);
- mobj->listAllDeallocatable(addr.segment, NULL, _print_address);
-
- return 0;
-}
-
-static int c_gc_normalise(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- reg_t addr = cmdParams[0].reg;
-
- MemObject *mobj = GET_SEGMENT_ANY(*s->seg_manager, addr.segment);
- if (!mobj) {
- sciprintf("Unknown segment : %x\n", addr.segment);
- return 1;
- }
-
- addr = mobj->findCanonicAddress(s->seg_manager, addr);
- sciprintf(" %04x:%04x\n", PRINT_REG(addr));
-
- return 0;
-}
-
void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *objp, int *restadjust,
SegmentId *segids, reg_t **variables, reg_t **variables_base, int *variables_nr, int bp) {
// Do we support a separate console?
@@ -1608,7 +1495,6 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
if (_debug_commands_not_hooked) {
_debug_commands_not_hooked = 0;
- con_hook_command(c_sfx_remove, "sfx_remove", "!a", "Kills a playing sound.");
con_hook_command(c_vmvars, "vmvars", "!sia*", "Displays or changes variables in the VM\n\nFirst parameter is either g(lobal), l(ocal), t(emp) or p(aram).\nSecond parameter is the var number\nThird parameter (if specified) is the value to set the variable to");
con_hook_command(c_step, "s", "i*", "Executes one or several operations\n\nEXAMPLES\n\n"
" s 4\n\n Execute 4 commands\n\n s\n\n Execute next command");
@@ -1631,7 +1517,6 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
con_hook_command(c_snk, "snk", "s*", "Steps forward until it hits the next\n callk operation.\n"
" If invoked with a parameter, it will\n look for that specific callk.\n");
con_hook_command(c_se, "se", "", "Steps forward until an SCI event is received.\n");
- con_hook_command(c_set_acc, "set_acc", "!a", "Sets the accumulator");
con_hook_command(c_send, "send", "!asa*", "Sends a message to an object\nExample: send ?fooScript cue");
con_hook_command(c_sret, "sret", "", "Steps forward until ret is called\n on the current execution stack\n level.");
con_hook_command(c_bpx, "bpx", "s", "Sets a breakpoint on the execution of\n the specified method.\n\n EXAMPLE:\n"
@@ -1666,32 +1551,9 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
"Steps until the global variable with the\n"
"specified index is modified.\n\nSEE ALSO\n\n"
" s.1, snk.1, so.1, bpx.1");
- con_hook_command(c_type, "type", "!a",
- "Determines the type of a value\n\n"
- "SEE ALSO\n\n addresses.3, vo.1");
con_hook_command(c_shownode, "shownode", "!a",
"Prints information about a list node\n"
" or list base.\n\n");
- con_hook_command(c_gc_show_reachable, "gc-list-reachable", "!a",
- "Prints all addresses directly reachable from\n"
- " the memory object specified as parameter.\n\n"
- "SEE ALSO\n\n"
- " gc-list-freeable.1, gc-normalise.1, gc.1,\n"
- " gc-all-reachable.1");
- con_hook_command(c_gc_show_freeable, "gc-list-freeable", "!a",
- "Prints all addresses freeable in the segment\n"
- " associated with the address (offset is ignored).\n\n"
- "SEE ALSO\n\n"
- " gc-list-freeable.1, gc-normalise.1, gc.1,\n"
- " gc-all-reachable.1");
- con_hook_command(c_gc_normalise, "gc-normalise", "!a",
- "Prints the \"normal\" address of a given address,\n"
- " i.e. the address we would free in order to free\n"
- " the object associated with the original address.\n\n"
- "SEE ALSO\n\n"
- " gc-list-freeable.1, gc-list-reachable.1, gc.1,\n"
- " gc-all-reachable.1");
-
/*
con_hook_int(&script_abort_flag, "script_abort_flag", "Set != 0 to abort execution\n");
*/