From 5b401215d9e0a31687c27b8b56ba3d651b89e000 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 30 Jul 2010 14:56:38 +0000 Subject: SCI: Added handling of negative numbers to op_mod for SCI01 and newer games. Fixes the battlecruiser mini-game in SQ5. Many thanks to lskovlun, wjp and m_kiewitz for their joined effort on this issue svn-id: r51508 --- engines/sci/engine/vm.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'engines/sci/engine/vm.cpp') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index b7f6896a48..0ab66419c0 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1069,11 +1069,17 @@ void run_vm(EngineState *s) { case op_mod: { // 0x05 (05) r_temp = POP32(); - int16 modulo, value; - if (validate_signedInteger(s->r_acc, modulo) && validate_signedInteger(r_temp, value)) - s->r_acc = make_reg(0, (modulo != 0 ? value % modulo : 0)); - else + int16 modulo, value, result; + if (validate_signedInteger(s->r_acc, modulo) && validate_signedInteger(r_temp, value)) { + modulo = ABS(modulo); + result = (modulo != 0 ? value % modulo : 0); + // In SCI01, handling for negative numbers was added + if (getSciVersion() >= SCI_VERSION_01 && result < 0) + result += modulo; + s->r_acc = make_reg(0, result); + } else { s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp); + } break; } -- cgit v1.2.3 From cbbafc138b897387f702e541a0bf873348604179 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 30 Jul 2010 15:19:21 +0000 Subject: SCI: Updated the op_mod changes and added a link to the original bug report svn-id: r51509 --- engines/sci/engine/vm.cpp | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'engines/sci/engine/vm.cpp') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 0ab66419c0..d849d3e008 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1069,16 +1069,29 @@ void run_vm(EngineState *s) { case op_mod: { // 0x05 (05) r_temp = POP32(); - int16 modulo, value, result; - if (validate_signedInteger(s->r_acc, modulo) && validate_signedInteger(r_temp, value)) { - modulo = ABS(modulo); - result = (modulo != 0 ? value % modulo : 0); - // In SCI01, handling for negative numbers was added - if (getSciVersion() >= SCI_VERSION_01 && result < 0) - result += modulo; - s->r_acc = make_reg(0, result); + + if (getSciVersion() <= SCI_VERSION_0_LATE) { + uint16 modulo, value; + if (validate_unsignedInteger(s->r_acc, modulo) && validate_unsignedInteger(r_temp, value)) + s->r_acc = make_reg(0, (modulo != 0 ? value % modulo : 0)); + else + s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp); } else { - s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp); + // In Iceman (and perhaps from SCI0 0.000.685 onwards in general), + // handling for negative numbers was added. Since Iceman doesn't + // seem to have issues with the older code, we exclude it for now + // for simplicity's sake and use the new code for SCI01 and newer + // games. Fixes the battlecruiser mini game in SQ5 (room 850), + // bug #3035755 + int16 modulo, value, result; + if (validate_signedInteger(s->r_acc, modulo) && validate_signedInteger(r_temp, value)) { + modulo = ABS(modulo); + result = (modulo != 0 ? value % modulo : 0); + if (result < 0) + result += modulo; + s->r_acc = make_reg(0, result); + } else + s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp); } break; } -- cgit v1.2.3 From f54b9e3527ac89f1030795a97b787fef4a047850 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 31 Jul 2010 14:38:28 +0000 Subject: SCI: removing warning about uninitialized parameters didn't cause any harm till now and it seems testers get irritated by it. Switching it to VM debug level 2. svn-id: r51540 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci/engine/vm.cpp') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index d849d3e008..56d16e798e 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -231,7 +231,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i case VAR_PARAM: // Out-of-bounds read for a parameter that goes onto stack and hits an uninitialized temp // We return 0 currently in that case - warning("Read for a parameter goes out-of-bounds, onto the stack and gets uninitialized temp"); + debugC(2, kDebugLevelVM, "[VM] Read for a parameter goes out-of-bounds, onto the stack and gets uninitialized temp"); return NULL_REG; default: break; -- cgit v1.2.3 From ee28c2eb54b3b02643a2e46d793acdf0843596a0 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 3 Aug 2010 15:51:31 +0000 Subject: SCI: adding workaround for pq3 fixes bug #3037565 svn-id: r51701 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci/engine/vm.cpp') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 56d16e798e..c25e26dc2c 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1215,7 +1215,7 @@ void run_vm(EngineState *s) { if (validate_signedInteger(r_temp, compare1) && validate_signedInteger(s->r_acc, compare2)) s->r_acc = make_reg(0, compare1 >= compare2); else - s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, r_temp, s->r_acc); + s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeGeWorkarounds, r_temp, s->r_acc); } break; -- cgit v1.2.3 From fcede4680a03e4f7a389a43f71d1484794e8dead Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 3 Aug 2010 19:06:40 +0000 Subject: SCI: adding bpk debug command currently removing or listing such breakpoints is not yet supported svn-id: r51710 --- engines/sci/engine/vm.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'engines/sci/engine/vm.cpp') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index c25e26dc2c..c6e8b3e2dd 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -743,6 +743,11 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { if (kernelCall.debugLogging) logKernelCall(&kernelCall, NULL, s, argc, argv, s->r_acc); + if (kernelCall.debugBreakpoint) { + printf("Break on k%s\n", kernelCall.name); + g_sci->_debugState.debugging = true; + g_sci->_debugState.breakpointWasHit = true; + } } else { // Sub-functions available, check signature and call that one directly if (argc < 1) @@ -793,6 +798,11 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { if (kernelSubCall.debugLogging) logKernelCall(&kernelCall, &kernelSubCall, s, argc, argv, s->r_acc); + if (kernelSubCall.debugBreakpoint) { + printf("Break on k%s\n", kernelSubCall.name); + g_sci->_debugState.debugging = true; + g_sci->_debugState.breakpointWasHit = true; + } } // Remove callk stack frame again, if there's still an execution stack -- cgit v1.2.3 From ed741dc96c2369bfc6abf29704108bc29e5ba9a9 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Wed, 4 Aug 2010 18:11:11 +0000 Subject: SCI: Fix bug #3038913 - SCI Fanmade - The Legend of the Lost Jewel: Crash by bugs Added workaround for calling mul with an object and kSetAngle with two objects as parameters. svn-id: r51743 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sci/engine/vm.cpp') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index c6e8b3e2dd..7f6d6cfd82 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1063,7 +1063,7 @@ void run_vm(EngineState *s) { if (validate_signedInteger(s->r_acc, value1) && validate_signedInteger(r_temp, value2)) s->r_acc = make_reg(0, value1 * value2); else - s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp); + s->r_acc = arithmetic_lookForWorkaround(opcode, opcodeMulWorkarounds, s->r_acc, r_temp); break; } -- cgit v1.2.3 From 19e624ae5be72bfe1dc677911d656871737dd371 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 5 Aug 2010 16:58:59 +0000 Subject: SCI: Changed the warning when a script can't be found from a segment into an error svn-id: r51758 --- engines/sci/engine/vm.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'engines/sci/engine/vm.cpp') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 7f6d6cfd82..35fc3ca566 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -933,11 +933,7 @@ void run_vm(EngineState *s) { obj = s->_segMan->getObject(s->xs->objp); local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); if (!local_script) { - // FIXME: Why does this happen? Is the script not loaded yet at this point? - warning("Could not find local script from segment %x", s->xs->local_segment); - local_script = NULL; - s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; - s->variablesMax[VAR_LOCAL] = 0; + error("Could not find local script from segment %x", s->xs->local_segment); } else { s->variablesSegment[VAR_LOCAL] = local_script->_localsSegment; if (local_script->_localsBlock) -- cgit v1.2.3 From 6c8bcd2ba1cad1312f0a588ca284110bbbb81ccc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 5 Aug 2010 23:08:05 +0000 Subject: SCI: Added a workaround for a script bug in QFG2, room 200, when talking with the astrologer. Fixes bug #3039879, "QFG2: Crash at astrologer's" svn-id: r51772 --- engines/sci/engine/vm.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'engines/sci/engine/vm.cpp') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 35fc3ca566..7bcc5b43a3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -135,9 +135,13 @@ static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) { static int validate_arithmetic(reg_t reg) { if (reg.segment) { // The results of this are likely unpredictable... It most likely means that a kernel function is returning something wrong. - // If such an error occurs, we usually need to find the last kernel function called and check its return value. Check - // callKernelFunc() below - error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]. Address: %04x:%04x", reg.segment, PRINT_REG(reg)); + // If such an error occurs, we usually need to find the last kernel function called and check its return value. + if (g_sci->getGameId() == GID_QFG2 && g_sci->getEngineState()->currentRoomNumber() == 200) { + // WORKAROUND: This happens in QFG2, room 200, when talking to the astrologer (bug #3039879) - script bug. + // Returning 0 in this case. + } else { + error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]. Address: %04x:%04x", reg.segment, PRINT_REG(reg)); + } return 0; } -- cgit v1.2.3