From 9380b541204e2ec446d75627b8fad1b78850f356 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Sat, 5 Nov 2016 17:56:15 -0500 Subject: SCI: Add code-address breakpoints to debugger --- engines/sci/console.cpp | 30 ++++++++++++++++++++++++++++++ engines/sci/console.h | 1 + engines/sci/debug.h | 8 ++++++-- engines/sci/engine/scriptdebug.cpp | 16 ++++++++++++++++ engines/sci/engine/vm.cpp | 2 ++ engines/sci/sci.h | 1 + 6 files changed, 56 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 83f1271252..4028974c83 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -201,6 +201,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), registerCmd("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); registerCmd("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias registerCmd("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias + registerCmd("bp_address", WRAP_METHOD(Console, cmdBreakpointAddress)); + registerCmd("bpa", WRAP_METHOD(Console, cmdBreakpointAddress)); // alias registerCmd("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod)); registerCmd("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias registerCmd("bp_read", WRAP_METHOD(Console, cmdBreakpointRead)); @@ -435,6 +437,7 @@ bool Console::cmdHelp(int argc, const char **argv) { debugPrintf("Breakpoints:\n"); debugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n"); debugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n"); + debugPrintf(" bp_address / bpa - Sets a breakpoint on a script address\n"); debugPrintf(" bp_method / bpx - Sets a breakpoint on the execution of a specified method/selector\n"); debugPrintf(" bp_read / bpr - Sets a breakpoint on reading of a specified selector\n"); debugPrintf(" bp_write / bpw - Sets a breakpoint on writing to a specified selector\n"); @@ -3738,6 +3741,8 @@ bool Console::cmdBreakpointList(int argc, const char **argv) { bpdata = bp->address; debugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF); break; + case BREAK_ADDRESS: + debugPrintf("Execute address %04x:%04x\n", PRINT_REG(bp->regAddress)); } i++; @@ -3894,6 +3899,31 @@ bool Console::cmdBreakpointFunction(int argc, const char **argv) { return true; } +bool Console::cmdBreakpointAddress(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Sets a breakpoint on the execution of the specified code address.\n"); + debugPrintf("Usage: %s
\n", argv[0]); + return true; + } + + reg_t addr; + + if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + + Breakpoint bp; + bp.type = BREAK_ADDRESS; + bp.regAddress = make_reg32(addr.getSegment(), addr.getOffset()); + + _debugState._breakpoints.push_back(bp); + _debugState._activeBreakpointTypes |= BREAK_ADDRESS; + + return true; +} + bool Console::cmdSfx01Header(int argc, const char **argv) { if (argc != 2) { debugPrintf("Dumps the header of a SCI01 song\n"); diff --git a/engines/sci/console.h b/engines/sci/console.h index d4b17ee802..7dd1572340 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -152,6 +152,7 @@ private: bool cmdBreakpointWrite(int argc, const char **argv); bool cmdBreakpointKernel(int argc, const char **argv); bool cmdBreakpointFunction(int argc, const char **argv); + bool cmdBreakpointAddress(int argc, const char **argv); // VM bool cmdScriptSteps(int argc, const char **argv); bool cmdScriptObjects(int argc, const char **argv); diff --git a/engines/sci/debug.h b/engines/sci/debug.h index 4fcb757c10..60fad26671 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -42,12 +42,16 @@ enum BreakpointType { * Break when an exported function is called. Data contains * script_no << 16 | export_no. */ - BREAK_EXPORT = 1 << 3 + BREAK_EXPORT = 1 << 3, + BREAK_ADDRESS = 1 << 4 // break when pc is at this address }; struct Breakpoint { BreakpointType type; - uint32 address; ///< Breakpoints on exports + union { + uint32 address; ///< Breakpoints on exports + reg32_t regAddress; ///< Breakpoints on addresses + }; Common::String name; ///< Breakpoints on selector names }; diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index b017e62df7..47b360d13b 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -631,6 +631,22 @@ bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) { return false; } +bool SciEngine::checkAddressBreakpoint(const reg32_t &address) { + if (_debugState._activeBreakpointTypes & BREAK_ADDRESS) { + Common::List::const_iterator bp; + for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { + if (bp->type == BREAK_ADDRESS && bp->regAddress == address) { + _console->debugPrintf("Break at %04x:%04x\n", PRINT_REG(address)); + _debugState.debugging = true; + _debugState.breakpointWasHit = true; + return true; + } + } + } + + return false; +} + void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr argp, ObjVarRef &varp, reg_t funcp, SegManager *segMan, SelectorType selectorType) { int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes; const char *objectName = segMan->getObjectName(send_obj); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index ac15aebf3a..e82128ebad 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -634,6 +634,8 @@ void run_vm(EngineState *s) { if (s->abortScriptProcessing != kAbortNone) return; // Stop processing + g_sci->checkAddressBreakpoint(s->xs->addr.pc); + // Debug if this has been requested: // TODO: re-implement sci_debug_flags if (g_sci->_debugState.debugging /* sci_debug_flags*/) { diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 61dccb4aba..7d248906cf 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -334,6 +334,7 @@ public: void scriptDebug(); bool checkExportBreakpoint(uint16 script, uint16 pubfunct); bool checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector); + bool checkAddressBreakpoint(const reg32_t &address); void patchGameSaveRestore(); -- cgit v1.2.3