From 67fcb0bdafac4384dbb6be3dca565a6e99b75e0a Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Mon, 4 Sep 2017 12:28:05 -0500 Subject: SCI: Allow deep inspection of objects in debugger --- engines/sci/console.cpp | 224 ++++++++++++++++++++++++++++-------------------- engines/sci/console.h | 11 ++- 2 files changed, 137 insertions(+), 98 deletions(-) diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 82661f044b..a81cdd2d64 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2832,94 +2832,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { } } - int type_mask = g_sci->getKernel()->findRegType(reg); - int filter; - int found = 0; - - debugPrintf("%04x:%04x is of type 0x%x: ", PRINT_REG(reg), type_mask); - - if (reg.getSegment() == 0 && reg.getOffset() == 0) { - debugPrintf("Null.\n"); - return true; - } - - if (reg_end.getSegment() != reg.getSegment() && reg_end != NULL_REG) { - 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 SIG_TYPE_LIST: - printList(reg); - break; - case SIG_TYPE_NODE: - debugPrintf("list node\n"); - printNode(reg); - break; - case SIG_TYPE_OBJECT: - debugPrintf("object\n"); - printObject(reg); - break; - case SIG_TYPE_REFERENCE: { - switch (_engine->_gamestate->_segMan->getSegmentType(reg.getSegment())) { -#ifdef ENABLE_SCI32 - case SEG_TYPE_ARRAY: { - printArray(reg); - break; - } - case SEG_TYPE_BITMAP: { - printBitmap(reg); - break; - } -#endif - default: { - const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); - uint16 size = block.maxSize; - - debugPrintf("raw data\n"); - - if (reg_end.getSegment() != 0 && (size < reg_end.getOffset() - reg.getOffset())) { - debugPrintf("Block end out of bounds (size %d). Resetting.\n", size); - reg_end = NULL_REG; - } - - if (reg_end.getSegment() != 0 && (size >= reg_end.getOffset() - reg.getOffset())) - size = reg_end.getOffset() - reg.getOffset(); - - if (reg_end.getSegment() != 0) - debugPrintf("Block size less than or equal to %d\n", size); - - if (block.isRaw) - Common::hexdump(block.raw, size, 16, 0); - else - hexDumpReg(block.reg, size / 2, 4, 0); - } - } - break; - } - case SIG_TYPE_INTEGER: - debugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.getOffset(), reg.getOffset()); - break; - default: - debugPrintf("unknown type %d.\n", type); - } - - if (type) { - debugPrintf("\n"); - found = 1; - } - } - + printReference(reg, reg_end); return true; } @@ -3043,9 +2956,9 @@ bool Console::cmdDumpReference(int argc, const char **argv) { } bool Console::cmdViewObject(int argc, const char **argv) { - if (argc != 2) { + if (argc < 2) { debugPrintf("Examines the object at the given address.\n"); - debugPrintf("Usage: %s
\n", argv[0]); + debugPrintf("Usage: %s
[ ...]\n", argv[0]); debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -3058,8 +2971,45 @@ bool Console::cmdViewObject(int argc, const char **argv) { return true; } - debugPrintf("Information on the object at the given address:\n"); - printObject(addr); + if (argc >= 3) { + for (int i = 2; i < argc; ++i) { + const Object *obj = _engine->_gamestate->_segMan->getObject(addr); + if (!obj) { + debugPrintf("%04x:%04x is not an object.\n", PRINT_REG(addr)); + break; + } + + const Selector selector = _engine->getKernel()->findSelector(argv[i]); + if (selector == -1) { + debugPrintf("Invalid selector '%s'.\n", argv[i]); + break; + } + + const int index = obj->locateVarSelector(_engine->_gamestate->_segMan, selector); + if (index == -1) { + debugPrintf("Selector '%s' is not valid for object %04x:%04x.\n", argv[i], PRINT_REG(addr)); + break; + } + + const reg_t value = obj->getVariable(index); + if (i == argc - 1) { + if (value.isPointer()) { + printReference(value); + } else { + debugPrintf("%04x:%04x (%u)\n", PRINT_REG(value), value.toUint16()); + } + } else if (!value.isPointer()) { + debugPrintf("Selector '%s' on object %04x:%04x is not a pointer to an object.\n", argv[i], PRINT_REG(addr)); + debugPrintf("Value is %04x:%04x (%u).\n", PRINT_REG(value), value.toUint16()); + break; + } else { + addr = value; + } + } + } else { + debugPrintf("Information on the object at the given address:\n"); + printObject(addr); + } return true; } @@ -4791,6 +4741,96 @@ int Console::printNode(reg_t addr) { return 0; } +void Console::printReference(reg_t reg, reg_t reg_end) { + int type_mask = g_sci->getKernel()->findRegType(reg); + int filter; + int found = 0; + + debugPrintf("%04x:%04x is of type 0x%x: ", PRINT_REG(reg), type_mask); + + if (reg.getSegment() == 0 && reg.getOffset() == 0) { + debugPrintf("Null.\n"); + return; + } + + if (reg_end.getSegment() != reg.getSegment() && reg_end != NULL_REG) { + 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 SIG_TYPE_LIST: + printList(reg); + break; + case SIG_TYPE_NODE: + debugPrintf("list node\n"); + printNode(reg); + break; + case SIG_TYPE_OBJECT: + debugPrintf("object\n"); + printObject(reg); + break; + case SIG_TYPE_REFERENCE: { + switch (_engine->_gamestate->_segMan->getSegmentType(reg.getSegment())) { +#ifdef ENABLE_SCI32 + case SEG_TYPE_ARRAY: { + printArray(reg); + break; + } + case SEG_TYPE_BITMAP: { + printBitmap(reg); + break; + } +#endif + default: { + const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); + uint16 size = block.maxSize; + + debugPrintf("raw data\n"); + + if (reg_end.getSegment() != 0 && (size < reg_end.getOffset() - reg.getOffset())) { + debugPrintf("Block end out of bounds (size %d). Resetting.\n", size); + reg_end = NULL_REG; + } + + if (reg_end.getSegment() != 0 && (size >= reg_end.getOffset() - reg.getOffset())) + size = reg_end.getOffset() - reg.getOffset(); + + if (reg_end.getSegment() != 0) + debugPrintf("Block size less than or equal to %d\n", size); + + if (block.isRaw) + Common::hexdump(block.raw, size, 16, 0); + else + hexDumpReg(block.reg, size / 2, 4, 0); + } + } + break; + } + case SIG_TYPE_INTEGER: + debugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.getOffset(), reg.getOffset()); + break; + default: + debugPrintf("unknown type %d.\n", type); + } + + if (type) { + debugPrintf("\n"); + found = 1; + } + } +} + #ifdef ENABLE_SCI32 void Console::printArray(reg_t reg) { SegmentObj *mobj = _engine->_gamestate->_segMan->getSegment(reg.getSegment(), SEG_TYPE_ARRAY); diff --git a/engines/sci/console.h b/engines/sci/console.h index 82a5f69db1..c467b863cd 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -41,16 +41,10 @@ public: Console(SciEngine *engine); virtual ~Console(); -#ifdef ENABLE_SCI32 - void printArray(reg_t reg); - void printBitmap(reg_t reg); -#endif - private: virtual void preEnter(); virtual void postEnter(); -private: // General bool cmdHelp(int argc, const char **argv); // Kernel @@ -192,6 +186,11 @@ private: void printKernelCallsFound(int kernelFuncNum, bool showFoundScripts); void printBreakpoint(int index, const Breakpoint &bp); + void printReference(reg_t reg, reg_t reg_end = NULL_REG); +#ifdef ENABLE_SCI32 + void printArray(reg_t reg); + void printBitmap(reg_t reg); +#endif SciEngine *_engine; DebugState &_debugState; -- cgit v1.2.3