aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
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 /engines/sci
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.
Diffstat (limited to 'engines/sci')
-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;