From 6fe95780d358f2d7854c342448eb61159f267656 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 12 Mar 2011 23:43:29 +0100 Subject: SCI: Continue disasm until no jumps go past the current opcode This should ensure disasm will disassemble an entire function, and not stop at an intermediate ret opcode. --- engines/sci/console.cpp | 15 ++++++++------- engines/sci/console.h | 1 + engines/sci/engine/scriptdebug.cpp | 29 +++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 6a64f198f6..b11aab0196 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2601,7 +2601,6 @@ bool Console::cmdDisassemble(int argc, const char **argv) { DebugPrintf("Valid options are:\n"); DebugPrintf(" bwt : Print byte/word tag\n"); DebugPrintf(" bc : Print bytecode\n"); - DebugPrintf(" rX : Continue after X ret opcodes before stopping decompilation\n"); return true; } @@ -2640,17 +2639,19 @@ bool Console::cmdDisassemble(int argc, const char **argv) { printBWTag = true; else if (!scumm_stricmp(argv[i], "bc")) printBytecode = true; - else if (argv[i][0] == 'r') - ignoreXret = atoi(argv[i] + 1); } + reg_t farthestTarget = addr; do { reg_t prevAddr = addr; - addr = disassemble(_engine->_gamestate, addr, printBWTag, printBytecode); - if (addr.isNull() && ignoreXret) { - addr = prevAddr + 1; // skip past the ret - ignoreXret--; + reg_t jumpTarget; + if (isJumpOpcode(_engine->_gamestate, addr, jumpTarget)) { + if (jumpTarget > farthestTarget) + farthestTarget = jumpTarget; } + addr = disassemble(_engine->_gamestate, addr, printBWTag, printBytecode); + if (addr.isNull() && prevAddr < farthestTarget) + addr = prevAddr + 1; // skip past the ret } while (addr.offset > 0); return true; diff --git a/engines/sci/console.h b/engines/sci/console.h index b0a1de6ebd..d45454376a 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -37,6 +37,7 @@ class SciEngine; struct List; reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode); +bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpOffset); class Console : public GUI::Debugger { public: diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 184f81bb99..76490217c3 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -281,6 +281,35 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode return retval; } +bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpTarget) +{ + SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT); + if (!mobj) + return false; + Script *script_entity = (Script *)mobj; + + const byte *scr = script_entity->getBuf(); + int scr_size = script_entity->getBufSize(); + + if (pos.offset >= scr_size) + return false; + + int16 opparams[4]; + byte opsize; + int bytecount = readPMachineInstruction(scr + pos.offset, opsize, opparams); + const byte opcode = opsize >> 1; + + switch (opcode) { + case op_bt: + case op_bnt: + case op_jmp: + jumpTarget = pos + bytecount + opparams[0]; + return true; + default: + return false; + } +} + void SciEngine::scriptDebug() { EngineState *s = _gamestate; -- cgit v1.2.3