SCI: Allow deep inspection of objects in debugger

This commit is contained in:
Colin Snover 2017-09-04 12:28:05 -05:00
parent 50e7a7eb3f
commit 67fcb0bdaf
2 changed files with 137 additions and 98 deletions

View file

@ -2832,94 +2832,7 @@ bool Console::cmdViewReference(int argc, const char **argv) {
} }
} }
int type_mask = g_sci->getKernel()->findRegType(reg); printReference(reg, reg_end);
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;
}
}
return true; return true;
} }
@ -3043,9 +2956,9 @@ bool Console::cmdDumpReference(int argc, const char **argv) {
} }
bool Console::cmdViewObject(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("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"); debugPrintf("Check the \"addresses\" command on how to use addresses\n");
return true; return true;
} }
@ -3058,8 +2971,45 @@ bool Console::cmdViewObject(int argc, const char **argv) {
return true; return true;
} }
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"); debugPrintf("Information on the object at the given address:\n");
printObject(addr); printObject(addr);
}
return true; return true;
} }
@ -4791,6 +4741,96 @@ int Console::printNode(reg_t addr) {
return 0; 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 #ifdef ENABLE_SCI32
void Console::printArray(reg_t reg) { void Console::printArray(reg_t reg) {
SegmentObj *mobj = _engine->_gamestate->_segMan->getSegment(reg.getSegment(), SEG_TYPE_ARRAY); SegmentObj *mobj = _engine->_gamestate->_segMan->getSegment(reg.getSegment(), SEG_TYPE_ARRAY);

View file

@ -41,16 +41,10 @@ public:
Console(SciEngine *engine); Console(SciEngine *engine);
virtual ~Console(); virtual ~Console();
#ifdef ENABLE_SCI32
void printArray(reg_t reg);
void printBitmap(reg_t reg);
#endif
private: private:
virtual void preEnter(); virtual void preEnter();
virtual void postEnter(); virtual void postEnter();
private:
// General // General
bool cmdHelp(int argc, const char **argv); bool cmdHelp(int argc, const char **argv);
// Kernel // Kernel
@ -192,6 +186,11 @@ private:
void printKernelCallsFound(int kernelFuncNum, bool showFoundScripts); void printKernelCallsFound(int kernelFuncNum, bool showFoundScripts);
void printBreakpoint(int index, const Breakpoint &bp); 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; SciEngine *_engine;
DebugState &_debugState; DebugState &_debugState;