aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/vm.cpp
diff options
context:
space:
mode:
authormd52011-02-22 18:52:44 +0200
committermd52011-02-22 18:52:44 +0200
commitcf904b1156091c65486bf3124e3ef1d3fd1b6f8f (patch)
treeb85b6b1db6d5af1c88e59d779214fae7c1e66eb0 /engines/sci/engine/vm.cpp
parent07c054d6c63bec5a9abd1b77781958f4a83969bc (diff)
downloadscummvm-rg350-cf904b1156091c65486bf3124e3ef1d3fd1b6f8f.tar.gz
scummvm-rg350-cf904b1156091c65486bf3124e3ef1d3fd1b6f8f.tar.bz2
scummvm-rg350-cf904b1156091c65486bf3124e3ef1d3fd1b6f8f.zip
SCI: Added code to aid in detecting infinite loops in scripts
When the ABORT_ON_INFINITE_LOOP define is defined in vm.cpp, the VM will now abort in cases where a conditional statement is followed by an unconditional jump (which will most likely lead to an infinite loop). Aids in detecting infinite loop bugs such as #3040722.
Diffstat (limited to 'engines/sci/engine/vm.cpp')
-rw-r--r--engines/sci/engine/vm.cpp25
1 files changed, 24 insertions, 1 deletions
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index a70ff5ab72..43d38a4979 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -47,6 +47,10 @@ const reg_t NULL_REG = {0, 0};
const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET};
const reg_t TRUE_REG = {0, 1};
//#define VM_DEBUG_SEND
+// Enable the define below to have the VM abort on cases where a conditional
+// statement is followed by an unconditional jump (which will most likely lead
+// to an infinite loop). Aids in detecting script bugs such as #3040722.
+//#define ABORT_ON_INFINITE_LOOP
#define SCI_XS_CALLEE_LOCALS ((SegmentId)-1)
@@ -871,6 +875,10 @@ void run_vm(EngineState *s) {
s->_executionStackPosChanged = true; // Force initialization
+#ifdef ABORT_ON_INFINITE_LOOP
+ byte prevOpcode = 0xFF;
+#endif
+
while (1) {
int var_type; // See description below
int var_number;
@@ -935,7 +943,22 @@ void run_vm(EngineState *s) {
byte extOpcode;
s->xs->addr.pc.offset += readPMachineInstruction(scr->getBuf() + s->xs->addr.pc.offset, extOpcode, opparams);
const byte opcode = extOpcode >> 1;
- //debug("%s: %d, %d, %d, %d, acc = %04x:%04x", opcodeNames[opcode], opparams[0], opparams[1], opparams[2], opparams[3], PRINT_REG(s->r_acc));
+ //debug("%s: %d, %d, %d, %d, acc = %04x:%04x, script %d, local script %d", opcodeNames[opcode], opparams[0], opparams[1], opparams[2], opparams[3], PRINT_REG(s->r_acc), scr->getScriptNumber(), local_script->getScriptNumber());
+
+#ifdef ABORT_ON_INFINITE_LOOP
+ if (prevOpcode != 0xFF) {
+ if (prevOpcode == op_eq_ || prevOpcode == op_ne_ ||
+ prevOpcode == op_gt_ || prevOpcode == op_ge_ ||
+ prevOpcode == op_lt_ || prevOpcode == op_le_ ||
+ prevOpcode == op_ugt_ || prevOpcode == op_uge_ ||
+ prevOpcode == op_ult_ || prevOpcode == op_ule_) {
+ if (opcode == op_jmp)
+ error("Infinite loop detected in script %d", scr->getScriptNumber());
+ }
+ }
+
+ prevOpcode = opcode;
+#endif
switch (opcode) {