diff options
Diffstat (limited to 'engines/sci/engine/scriptdebug.cpp')
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 113 |
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; |