diff options
author | Willem Jan Palenstijn | 2011-03-12 23:43:29 +0100 |
---|---|---|
committer | Willem Jan Palenstijn | 2011-03-12 23:46:32 +0100 |
commit | 6fe95780d358f2d7854c342448eb61159f267656 (patch) | |
tree | 8fa2ff1de442d8a11a65ce6d71aaf84217e715b6 | |
parent | fa10ee66e46be4a08743f920ec50f11df1017a12 (diff) | |
download | scummvm-rg350-6fe95780d358f2d7854c342448eb61159f267656.tar.gz scummvm-rg350-6fe95780d358f2d7854c342448eb61159f267656.tar.bz2 scummvm-rg350-6fe95780d358f2d7854c342448eb61159f267656.zip |
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.
-rw-r--r-- | engines/sci/console.cpp | 15 | ||||
-rw-r--r-- | engines/sci/console.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 29 |
3 files changed, 38 insertions, 7 deletions
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; |