aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2017-09-04 12:28:05 -0500
committerColin Snover2017-09-04 15:19:59 -0500
commit67fcb0bdafac4384dbb6be3dca565a6e99b75e0a (patch)
tree3dce113f1ba5aee4f2fa8107d54c02f1ab237791
parent50e7a7eb3f6558c6f9cdb906356bcd70bd31f33d (diff)
downloadscummvm-rg350-67fcb0bdafac4384dbb6be3dca565a6e99b75e0a.tar.gz
scummvm-rg350-67fcb0bdafac4384dbb6be3dca565a6e99b75e0a.tar.bz2
scummvm-rg350-67fcb0bdafac4384dbb6be3dca565a6e99b75e0a.zip
SCI: Allow deep inspection of objects in debugger
-rw-r--r--engines/sci/console.cpp224
-rw-r--r--engines/sci/console.h11
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 <address>\n", argv[0]);
+ debugPrintf("Usage: %s <address> [<selector name> ...]\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;