aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/scriptdebug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/scriptdebug.cpp')
-rw-r--r--engines/sci/engine/scriptdebug.cpp113
1 files changed, 85 insertions, 28 deletions
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index f0157a6569..54b925a1b6 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -68,7 +68,7 @@ const char *opcodeNames[] = {
#endif // REDUCE_MEMORY_USAGE
// Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered.
-reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printBytecode) {
+reg_t disassemble(EngineState *s, reg32_t pos, reg_t objAddr, bool printBWTag, bool printBytecode) {
SegmentObj *mobj = s->_segMan->getSegment(pos.getSegment(), SEG_TYPE_SCRIPT);
Script *script_entity = NULL;
const byte *scr;
@@ -99,17 +99,6 @@ reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printByteco
debugN("%04x:%04x: ", PRINT_REG(pos));
- if (opcode == op_pushSelf) { // 0x3e (62)
- if ((opsize & 1) && g_sci->getGameId() != GID_FANMADE) {
- // Debug opcode op_file
- debugN("file \"%s\"\n", scr + pos.getOffset() + 1); // +1: op_pushSelf size
- retval.incOffset(bytecount - 1);
- return retval;
- }
- }
-
- opsize &= 1; // byte if true, word if false
-
if (printBytecode) {
if (pos.getOffset() + bytecount > scr_size) {
warning("Operation arguments extend beyond end of script");
@@ -123,13 +112,24 @@ reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printByteco
debugN(" ");
}
+ opsize &= 1; // byte if true, word if false
+
if (printBWTag)
debugN("[%c] ", opsize ? 'B' : 'W');
+ if (opcode == op_pushSelf && opsize && g_sci->getGameId() != GID_FANMADE) { // 0x3e (62)
+ // Debug opcode op_file
+ debugN("file \"%s\"\n", scr + pos.getOffset() + 1); // +1: op_pushSelf size
+ retval.incOffset(bytecount - 1);
+ return retval;
+ }
+
#ifndef REDUCE_MEMORY_USAGE
- debugN("%s", opcodeNames[opcode]);
+ debugN("%-5s", opcodeNames[opcode]);
#endif
+ static const char *defaultSeparator = "\t\t; ";
+
i = 0;
while (g_sci->_opcode_formats[opcode][i]) {
switch (g_sci->_opcode_formats[opcode][i++]) {
@@ -140,14 +140,21 @@ reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printByteco
case Script_SByte:
case Script_Byte:
param_value = scr[retval.getOffset()];
- debugN(" %02x", scr[retval.getOffset()]);
+ debugN("\t%02x", param_value);
+ if (param_value > 9) {
+ debugN("%s%u", defaultSeparator, param_value);
+ }
retval.incOffset(1);
break;
case Script_Word:
case Script_SWord:
param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.getOffset()]);
- debugN(" %04x", READ_SCI11ENDIAN_UINT16(&scr[retval.getOffset()]));
+ debugN("\t%04x", param_value);
+ if (param_value > 9) {
+ debugN("%s%u", defaultSeparator, param_value);
+ }
+
retval.incOffset(2);
break;
@@ -166,12 +173,38 @@ reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printByteco
retval.incOffset(2);
}
- if (opcode == op_callk)
- debugN(" %s[%x]", (param_value < kernel->_kernelFuncs.size()) ?
+ if (opcode == op_callk) {
+ debugN("\t%s[%x],", (param_value < kernel->_kernelFuncs.size()) ?
((param_value < kernel->getKernelNamesSize()) ? kernel->getKernelName(param_value).c_str() : "[Unknown(postulated)]")
: "<invalid>", param_value);
- else
- debugN(opsize ? " %02x" : " %04x", param_value);
+ } else if (opcode == op_super) {
+ Object *obj;
+ if (objAddr != NULL_REG && (obj = s->_segMan->getObject(objAddr)) != nullptr) {
+ debugN("\t%s", s->_segMan->getObjectName(obj->getSuperClassSelector()));
+ debugN(opsize ? "[%02x]" : "[%04x]", param_value);
+ } else {
+ debugN(opsize ? "\t%02x" : "\t%04x", param_value);
+ }
+
+ debugN(",");
+ } else {
+ const char *separator = defaultSeparator;
+
+ debugN(opsize ? "\t%02x" : "\t%04x", param_value);
+ if (param_value > 9) {
+ debugN("%s%u", separator, param_value);
+ separator = ", ";
+ }
+
+ if (param_value >= 0x20 && param_value <= 0x7e) {
+ debugN("%s'%c'", separator, param_value);
+ separator = ", ";
+ }
+
+ if (opcode == op_pushi && param_value < kernel->getSelectorNamesSize()) {
+ debugN("%s%s", separator, kernel->getSelectorName(param_value).c_str());
+ }
+ }
break;
@@ -183,19 +216,27 @@ reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printByteco
param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.getOffset()]);
retval.incOffset(2);
}
- debugN(opsize ? " %02x" : " %04x", param_value);
+
+ if (opcode == op_lofsa || opcode == op_lofss) {
+ reg_t addr = make_reg(pos.getSegment(), findOffset(param_value, script_entity, pos.getOffset()));
+ debugN("\t%s", s->_segMan->getObjectName(addr));
+ debugN(opsize ? "[%02x]" : "[%04x]", param_value);
+ } else {
+ debugN(opsize ? "\t%02x" : "\t%04x", param_value);
+ }
+
break;
case Script_SRelative:
if (opsize) {
int8 offset = (int8)scr[retval.getOffset()];
retval.incOffset(1);
- debugN(" %02x [%04x]", 0xff & offset, 0xffff & (retval.getOffset() + offset));
+ debugN("\t%02x [%04x]", 0xff & offset, 0xffff & (retval.getOffset() + offset));
}
else {
int16 offset = (int16)READ_SCI11ENDIAN_UINT16(&scr[retval.getOffset()]);
retval.incOffset(2);
- debugN(" %04x [%04x]", 0xffff & offset, 0xffff & (retval.getOffset() + offset));
+ debugN("\t%04x [%04x]", 0xffff & offset, 0xffff & (retval.getOffset() + offset));
}
break;
@@ -396,7 +437,7 @@ void SciEngine::scriptDebug() {
}
debugN("Step #%d\n", s->scriptStepCounter);
- disassemble(s, s->xs->addr.pc, false, true);
+ disassemble(s, s->xs->addr.pc, s->xs->objp, false, true);
if (_debugState.runningStep) {
_debugState.runningStep--;
@@ -499,7 +540,7 @@ void Kernel::dumpScriptClass(char *data, int seeker, int objsize) {
void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
int objectctr[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- unsigned int _seeker = 0;
+ uint32 _seeker = 0;
Resource *script = _resMan->findResource(ResourceId(kResourceTypeScript, scriptNumber), 0);
if (!script) {
@@ -510,7 +551,7 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
while (_seeker < script->size) {
int objType = (int16)READ_SCI11ENDIAN_UINT16(script->data + _seeker);
int objsize;
- unsigned int seeker = _seeker + 4;
+ uint32 seeker = _seeker + 4;
if (!objType) {
debugN("End of script object (#0) encountered.\n");
@@ -631,6 +672,22 @@ bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
return false;
}
+bool SciEngine::checkAddressBreakpoint(const reg32_t &address) {
+ if (_debugState._activeBreakpointTypes & BREAK_ADDRESS) {
+ Common::List<Breakpoint>::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);
@@ -741,13 +798,13 @@ void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *ke
switch (mobj->getType()) {
case SEG_TYPE_HUNK:
{
- HunkTable *ht = (HunkTable *)mobj;
+ HunkTable &ht = *(HunkTable *)mobj;
int index = argv[parmNr].getOffset();
- if (ht->isValidEntry(index)) {
+ if (ht.isValidEntry(index)) {
// NOTE: This ", deleted" isn't as useful as it could
// be because it prints the status _after_ the kernel
// call.
- debugN(" ('%s' hunk%s)", ht->_table[index].type, ht->_table[index].mem ? "" : ", deleted");
+ debugN(" ('%s' hunk%s)", ht[index].type, ht[index].mem ? "" : ", deleted");
} else
debugN(" (INVALID hunk ref)");
break;