diff options
-rw-r--r-- | engines/sci/console.cpp | 204 | ||||
-rw-r--r-- | engines/sci/console.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 174 |
3 files changed, 198 insertions, 182 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 59477ce710..32111a064c 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -135,6 +135,7 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { DCmd_Register("registers", WRAP_METHOD(Console, cmdRegisters)); DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript)); DCmd_Register("set_acc", WRAP_METHOD(Console, cmdSetAccumulator)); + DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace)); // Breakpoints DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); @@ -147,6 +148,7 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { DCmd_Register("stack", WRAP_METHOD(Console, cmdStack)); DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType)); DCmd_Register("view_listnode", WRAP_METHOD(Console, cmdViewListNode)); + DCmd_Register("view_reference", WRAP_METHOD(Console, cmdViewReference)); DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject)); DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); @@ -270,6 +272,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" registers - Shows the current register values\n"); DebugPrintf(" dissect_script - Examines a script\n"); DebugPrintf(" set_acc - Sets the accumulator\n"); + DebugPrintf(" backtrace - Dumps the send/self/super/call/calle/callb stack\n"); DebugPrintf("\n"); DebugPrintf("Breakpoints:\n"); DebugPrintf(" bp_list - Lists the current breakpoints\n"); @@ -284,6 +287,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" stack - Lists the specified number of stack elements\n"); DebugPrintf(" value_type - Determines the type of a value\n"); DebugPrintf(" view_listnode - Examines the list node at the given address\n"); + DebugPrintf(" view_reference - Examines an arbitrary reference\n"); DebugPrintf(" view_object - Examines the object at the given address\n"); DebugPrintf(" active_object - Shows information on the currently active object or class\n"); DebugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n"); @@ -302,6 +306,13 @@ ResourceType parseResourceType(const char *resid) { return res; } +const char *selector_name(EngineState *s, int selector) { + if (selector >= 0 && selector < (int)s->_kernel->getSelectorNamesSize()) + return s->_kernel->getSelectorName(selector).c_str(); + else + return "--INVALID--"; +} + bool Console::cmdGetVersion(int argc, const char **argv) { int ver = _vm->getVersion(); @@ -1576,7 +1587,12 @@ bool Console::cmdVMVars(int argc, const char **argv) { case 3: #if 0 // TODO: p_vars - p_vars[vartype][idx] = parse_reg_t(argv[3]); + + if (parse_reg_t(g_EngineState, argv[3], &p_vars[vartype][idx])) { + DebugPrintf("Invalid address passed.\n"); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } #endif break; default: @@ -1677,6 +1693,117 @@ bool Console::cmdViewListNode(int argc, const char **argv) { return true; } +bool Console::cmdViewReference(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Examines an arbitrary reference.\n"); + DebugPrintf("Usage: %s <start address> [<end address>]\n", argv[0]); + DebugPrintf("Where <start address> is the starting address to examine\n"); + DebugPrintf("<end address>, if provided, is the address where examining ends at\n"); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + + reg_t reg = NULL_REG; + reg_t reg_end = NULL_REG; + + if (parse_reg_t(g_EngineState, argv[1], ®)) { + DebugPrintf("Invalid address passed.\n"); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + + if (argc > 2) { + if (parse_reg_t(g_EngineState, argv[2], ®_end)) { + DebugPrintf("Invalid address passed.\n"); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + } + + int type_mask = determine_reg_type(g_EngineState, reg, 1); + int filter; + int found = 0; + + DebugPrintf("%04x:%04x is of type 0x%x%s: ", PRINT_REG(reg), type_mask & ~KSIG_INVALID, type_mask & KSIG_INVALID ? " (invalid)" : ""); + + type_mask &= ~KSIG_INVALID; + + if (reg.segment == 0 && reg.offset == 0) { + DebugPrintf("Null.\n"); + return true; + } + + if (reg_end.segment != reg.segment) { + DebugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n"); + reg_end = NULL_REG; + } + + for (filter = 1; filter < 0xf000; filter <<= 1) { + int type = type_mask & filter; + + if (found && type) { + DebugPrintf("--- Alternatively, it could be a "); + } + + + switch (type) { + case 0: + break; + case KSIG_LIST: { + List *l = lookup_list(g_EngineState, reg); + + DebugPrintf("list\n"); + + if (l) + printList(l); + else + DebugPrintf("Invalid list.\n"); + } + break; + case KSIG_NODE: + DebugPrintf("list node\n"); + printNode(reg); + break; + case KSIG_OBJECT: + DebugPrintf("object\n"); + printObject(g_EngineState, reg); + break; + case KSIG_REF: { + int size; + unsigned char *block = g_EngineState->seg_manager->dereference(reg, &size); + + DebugPrintf("raw data\n"); + + if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) { + DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); + reg_end = NULL_REG; + } + + if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset)) + size = reg_end.offset - reg.offset; + + if (reg_end.segment != 0) + DebugPrintf("Block size less than or equal to %d\n", size); + + Common::hexdump(block, size, 16, 0); + } + break; + case KSIG_ARITHMETIC: + DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.offset, reg.offset); + break; + default: + DebugPrintf("unknown type %d.\n", type); + } + + if (type) { + DebugPrintf("\n"); + found = 1; + } + } + + return true; +} + bool Console::cmdViewObject(int argc, const char **argv) { if (argc != 2) { DebugPrintf("Examines the object at the given address.\n"); @@ -1743,6 +1870,74 @@ bool Console::cmdSetAccumulator(int argc, const char **argv) { return true; } +bool Console::cmdBacktrace(int argc, const char **argv) { + DebugPrintf("Dumping the send/self/super/call/calle/callb stack:\n"); + + DebugPrintf("Call stack (current base: 0x%x):\n", g_EngineState->execution_stack_base); + Common::List<ExecStack>::iterator iter; + uint i = 0; + + for (iter = g_EngineState->_executionStack.begin(); + iter != g_EngineState->_executionStack.end(); ++iter, ++i) { + ExecStack &call = *iter; + const char *objname = obj_get_name(g_EngineState, call.sendp); + int paramc, totalparamc; + + switch (call.type) { + + case EXEC_STACK_TYPE_CALL: {// Normal function + sciprintf(" %x:[%x] %s::%s(", i, call.origin, objname, (call.selector == -1) ? "<call[be]?>" : + selector_name(g_EngineState, call.selector)); + } + break; + + case EXEC_STACK_TYPE_KERNEL: // Kernel function + sciprintf(" %x:[%x] k%s(", i, call.origin, g_EngineState->_kernel->getKernelName(-(call.selector) - 42).c_str()); + break; + + case EXEC_STACK_TYPE_VARSELECTOR: + sciprintf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read", + objname, g_EngineState->_kernel->getSelectorName(call.selector).c_str()); + break; + } + + totalparamc = call.argc; + + if (totalparamc > 16) + totalparamc = 16; + + for (paramc = 1; paramc <= totalparamc; paramc++) { + sciprintf("%04x:%04x", PRINT_REG(call.variables_argp[paramc])); + + if (paramc < call.argc) + sciprintf(", "); + } + + if (call.argc > 16) + sciprintf("..."); + + sciprintf(")\n obj@%04x:%04x", PRINT_REG(call.objp)); + if (call.type == EXEC_STACK_TYPE_CALL) { + sciprintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); + if (call.sp == CALL_SP_CARRY) + sciprintf(" sp,fp:carry"); + else { + sciprintf(" sp=ST:%04x", (unsigned)(call.sp - g_EngineState->stack_base)); + sciprintf(" fp=ST:%04x", (unsigned)(call.fp - g_EngineState->stack_base)); + } + } else + sciprintf(" pc:none"); + + sciprintf(" argp:ST:%04x", (unsigned)(call.variables_argp - g_EngineState->stack_base)); + if (call.type == EXEC_STACK_TYPE_CALL) + sciprintf(" script: %d", (*(Script *)g_EngineState->seg_manager->_heap[call.addr.pc.segment]).nr); + sciprintf("\n"); + } + + return 0; + return true; +} + bool Console::cmdBreakpointList(int argc, const char **argv) { Breakpoint *bp = g_EngineState->bp_list; int i = 0; @@ -2364,13 +2559,6 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on return 0; } -const char *selector_name(EngineState *s, int selector) { - if (selector >= 0 && selector < (int)s->_kernel->getSelectorNamesSize()) - return s->_kernel->getSelectorName(selector).c_str(); - else - return "--INVALID--"; -} - void Console::printList(List *l) { reg_t pos = l->first; reg_t my_prev = NULL_REG; diff --git a/engines/sci/console.h b/engines/sci/console.h index edd58f1f90..f0975837df 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -118,6 +118,7 @@ private: bool cmdRegisters(int argc, const char **argv); bool cmdDissectScript(int argc, const char **argv); bool cmdSetAccumulator(int argc, const char **argv); + bool cmdBacktrace(int argc, const char **argv); // Breakpoints bool cmdBreakpointList(int argc, const char **argv); bool cmdBreakpointDelete(int argc, const char **argv); @@ -130,6 +131,7 @@ private: bool cmdStack(int argc, const char **argv); bool cmdValueType(int argc, const char **argv); bool cmdViewListNode(int argc, const char **argv); + bool cmdViewReference(int argc, const char **argv); bool cmdViewObject(int argc, const char **argv); bool cmdViewActiveObject(int argc, const char **argv); bool cmdViewAccumulatorObject(int argc, const char **argv); diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 28821523cd..1f750abe58 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -120,108 +120,6 @@ static const char *_debug_get_input() { return inputbuf; } -extern int printObject(EngineState *s, reg_t pos); - -static int c_vr(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - reg_t reg = cmdParams[0].reg; - reg_t reg_end = cmdParams.size() > 1 ? cmdParams[1].reg : NULL_REG; - int type_mask = determine_reg_type(s, reg, 1); - int filter; - int found = 0; - - sciprintf("%04x:%04x is of type 0x%x%s: ", PRINT_REG(reg), type_mask & ~KSIG_INVALID, type_mask & KSIG_INVALID ? " (invalid)" : ""); - - type_mask &= ~KSIG_INVALID; - - if (reg.segment == 0 && reg.offset == 0) { - sciprintf("Null.\n"); - return 0; - } - - if (reg_end.segment != reg.segment) { - sciprintf("Ending segment different from starting segment. Assuming no bound on dump.\n"); - reg_end = NULL_REG; - } - - for (filter = 1; filter < 0xf000; filter <<= 1) { - int type = type_mask & filter; - - if (found && type) { - sciprintf("--- Alternatively, it could be a "); - } - - - switch (type) { - case 0: - break; - - case KSIG_LIST: { - //List *l = lookup_list(s, reg); - - sciprintf("list\n"); - - // TODO: printList has been moved to console.cpp - /* - if (l) - printList(l); - else - sciprintf("Invalid list.\n"); - */ - } - break; - - case KSIG_NODE: - sciprintf("list node\n"); - // TODO: printNode has been moved to console.cpp - /* - printNode(s, reg); - */ - break; - - case KSIG_OBJECT: - sciprintf("object\n"); - printObject(s, reg); - break; - - case KSIG_REF: { - int size; - unsigned char *block = s->seg_manager->dereference(reg, &size); - - sciprintf("raw data\n"); - - if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) { - sciprintf("Block end out of bounds (size %d). Resetting.\n", size); - reg_end = NULL_REG; - } - - if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset)) - size = reg_end.offset - reg.offset; - - if (reg_end.segment != 0) - sciprintf("Block size less than or equal to %d\n", size); - - Common::hexdump(block, size, 16, 0); - } - break; - - case KSIG_ARITHMETIC: - sciprintf("arithmetic value\n %d (%04x)\n", (int16) reg.offset, reg.offset); - break; - - default: - sciprintf("unknown type %d.\n", type); - - } - - if (type) { - sciprintf("\n"); - found = 1; - } - } - - return 0; -} - int c_step(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { _debugstate_valid = 0; if (cmdParams.size() && (cmdParams[0].val > 0)) @@ -637,75 +535,6 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod return retval; } -static int c_backtrace(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - if (!_debugstate_valid) { - sciprintf("Not in debug state\n"); - return 1; - } - - sciprintf("Call stack (current base: 0x%x):\n", s->execution_stack_base); - Common::List<ExecStack>::iterator iter; - uint i = 0; - for (iter = s->_executionStack.begin(); - iter != s->_executionStack.end(); ++iter, ++i) { - ExecStack &call = *iter; - const char *objname = obj_get_name(s, call.sendp); - int paramc, totalparamc; - - switch (call.type) { - - case EXEC_STACK_TYPE_CALL: {// Normal function - sciprintf(" %x:[%x] %s::%s(", i, call.origin, objname, (call.selector == -1) ? "<call[be]?>" : - selector_name(s, call.selector)); - } - break; - - case EXEC_STACK_TYPE_KERNEL: // Kernel function - sciprintf(" %x:[%x] k%s(", i, call.origin, s->_kernel->getKernelName(-(call.selector) - 42).c_str()); - break; - - case EXEC_STACK_TYPE_VARSELECTOR: - sciprintf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read", - objname,s->_kernel->getSelectorName(call.selector).c_str()); - break; - } - - totalparamc = call.argc; - - if (totalparamc > 16) - totalparamc = 16; - - for (paramc = 1; paramc <= totalparamc; paramc++) { - sciprintf("%04x:%04x", PRINT_REG(call.variables_argp[paramc])); - - if (paramc < call.argc) - sciprintf(", "); - } - - if (call.argc > 16) - sciprintf("..."); - - sciprintf(")\n obj@%04x:%04x", PRINT_REG(call.objp)); - if (call.type == EXEC_STACK_TYPE_CALL) { - sciprintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); - if (call.sp == CALL_SP_CARRY) - sciprintf(" sp,fp:carry"); - else { - sciprintf(" sp=ST:%04x", PRINT_STK(call.sp)); - sciprintf(" fp=ST:%04x", PRINT_STK(call.fp)); - } - } else - sciprintf(" pc:none"); - - sciprintf(" argp:ST:%04x", PRINT_STK(call.variables_argp)); - if (call.type == EXEC_STACK_TYPE_CALL) - sciprintf(" script: %d", (*(Script *)s->seg_manager->_heap[call.addr.pc.segment]).nr); - sciprintf("\n"); - } - - return 0; -} - #ifdef GFXW_DEBUG_WIDGETS extern GfxWidget *debug_widgets[]; extern int debug_widget_pos; @@ -1185,7 +1014,6 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * " c<x> : Disassemble <x> bytes\n" " bc : Print bytecode\n\n"); con_hook_command(c_disasm, "disasm", "!as", "Disassembles a method by name\n\nUSAGE\n\n disasm <obj> <method>\n\n"); - con_hook_command(c_backtrace, "bt", "", "Dumps the send/self/super/call/calle/callb stack"); 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"); @@ -1205,8 +1033,6 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * con_hook_command(c_gfx_draw_viewobj, "draw_viewobj", "i", "Draws the nsRect and brRect of a\n dynview object.\n\n nsRect is green, brRect\n" " is blue.\n"); #endif - con_hook_command(c_vr, "vr", "!aa*", - "Examines an arbitrary reference\n\n"); con_hook_command(c_sg, "sg", "!i", "Steps until the global variable with the\n" "specified index is modified.\n\nSEE ALSO\n\n" |