aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorWalter van Niftrik2010-01-27 13:14:28 +0000
committerWalter van Niftrik2010-01-27 13:14:28 +0000
commited199f38b4fa2fd69077341f41609b4a84aa9ade (patch)
tree96fd6060d3c600746a5807a2031e82696bdd69a8 /engines/sci
parent0b4b3da4e4bf516e46d7bc43d2cf60569559993a (diff)
downloadscummvm-rg350-ed199f38b4fa2fd69077341f41609b4a84aa9ade.tar.gz
scummvm-rg350-ed199f38b4fa2fd69077341f41609b4a84aa9ade.tar.bz2
scummvm-rg350-ed199f38b4fa2fd69077341f41609b4a84aa9ade.zip
SCI: Experimental fix for Longbow outlook crash.
When using a pointer in number arithmetic, substitute a large value instead of 0 (cf. Hoyle hack in kAbs). svn-id: r47597
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/vm.cpp26
1 files changed, 20 insertions, 6 deletions
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 3d320d485c..e636935908 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -87,8 +87,10 @@ static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) {
static int validate_arithmetic(reg_t reg) {
if (reg.segment) {
+ // When using a pointer in number arithmetic, we substitute a large value as
+ // some scripts rely on this (cf. Hoyle hack in kAbs).
warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment);
- return 0;
+ return 0x3e9;
}
return reg.offset;
@@ -97,7 +99,7 @@ static int validate_arithmetic(reg_t reg) {
static int signed_validate_arithmetic(reg_t reg) {
if (reg.segment) {
warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment);
- return 0;
+ return 0x3e9;
}
if (reg.offset & 0x8000)
@@ -890,25 +892,37 @@ void run_vm(EngineState *s, int restoring) {
case 0x13: // ugt?
s->r_prev = s->r_acc;
r_temp = POP32();
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset);
+ if (r_temp.segment && s->r_acc.segment)
+ s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset);
+ else
+ s->r_acc = ACC_ARITHMETIC_L(validate_arithmetic(r_temp) > /*acc*/);
break;
case 0x14: // uge?
s->r_prev = s->r_acc;
r_temp = POP32();
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset >= s->r_acc.offset);
+ if (r_temp.segment && s->r_acc.segment)
+ s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset >= s->r_acc.offset);
+ else
+ s->r_acc = ACC_ARITHMETIC_L(validate_arithmetic(r_temp) >= /*acc*/);
break;
case 0x15: // ult?
s->r_prev = s->r_acc;
r_temp = POP32();
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset < s->r_acc.offset);
+ if (r_temp.segment && s->r_acc.segment)
+ s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset < s->r_acc.offset);
+ else
+ s->r_acc = ACC_ARITHMETIC_L(validate_arithmetic(r_temp) < /*acc*/);
break;
case 0x16: // ule?
s->r_prev = s->r_acc;
r_temp = POP32();
- s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset <= s->r_acc.offset);
+ if (r_temp.segment && s->r_acc.segment)
+ s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset <= s->r_acc.offset);
+ else
+ s->r_acc = ACC_ARITHMETIC_L(validate_arithmetic(r_temp) <= /*acc*/);
break;
case 0x17: // bt