aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillem Jan Palenstijn2011-03-12 23:43:29 +0100
committerWillem Jan Palenstijn2011-03-12 23:46:32 +0100
commit6fe95780d358f2d7854c342448eb61159f267656 (patch)
tree8fa2ff1de442d8a11a65ce6d71aaf84217e715b6
parentfa10ee66e46be4a08743f920ec50f11df1017a12 (diff)
downloadscummvm-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.cpp15
-rw-r--r--engines/sci/console.h1
-rw-r--r--engines/sci/engine/scriptdebug.cpp29
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;