aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kevent.cpp
diff options
context:
space:
mode:
authorMartin Kiewitz2016-01-03 18:09:06 +0100
committerMartin Kiewitz2016-01-03 18:09:06 +0100
commitf9459656f56e52930fca10ef6ab7fa143fd11b15 (patch)
tree63fb3d29afe3dafe1f1bc8dc0bfa828abe6d8a08 /engines/sci/engine/kevent.cpp
parent35e526d34b4306739938a80c329a24b294a1860d (diff)
downloadscummvm-rg350-f9459656f56e52930fca10ef6ab7fa143fd11b15.tar.gz
scummvm-rg350-f9459656f56e52930fca10ef6ab7fa143fd11b15.tar.bz2
scummvm-rg350-f9459656f56e52930fca10ef6ab7fa143fd11b15.zip
SCI: implement kGetEvent modifiers DOS bug
Will fix darts minigame in the fan game "Betrayed Alliance" This bug in the original interpreter/keyboard driver seems to have been fixed in SCI32.
Diffstat (limited to 'engines/sci/engine/kevent.cpp')
-rw-r--r--engines/sci/engine/kevent.cpp27
1 files changed, 24 insertions, 3 deletions
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index eb052dd24e..1d9dbdcbb4 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -42,6 +42,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
reg_t obj = argv[1];
SciEvent curEvent;
int modifier_mask = getSciVersion() <= SCI_VERSION_01 ? SCI_KEYMOD_ALL : SCI_KEYMOD_NO_FOOLOCK;
+ uint16 modifiers = 0;
SegManager *segMan = s->_segMan;
Common::Point mousePos;
@@ -110,6 +111,25 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
writeSelectorValue(segMan, obj, SELECTOR(x), mousePos.x);
writeSelectorValue(segMan, obj, SELECTOR(y), mousePos.y);
+ // Get current keyboard modifiers, only keep relevant bits
+ modifiers = curEvent.modifiers & modifier_mask;
+ if (g_sci->getPlatform() == Common::kPlatformDOS) {
+ // We are supposed to emulate SCI running in DOS
+
+ // We set the higher byte of the modifiers to 02h
+ // Original SCI also did that indirectly, because it asked BIOS for shift status
+ // via AH=0x02 INT16, which then sets the shift flags in AL
+ // AH is supposed to be destroyed in that case and it's not defined that 0x02
+ // is still in it on return. The value of AX was then set into the modifiers selector.
+ // At least one fan-made game (Betrayed Alliance) requires 0x02 to be in the upper byte,
+ // otherwise the darts game (script 111) will not work properly.
+
+ // It seems Sierra fixed this behaviour (effectively bug) in SCI32
+ if (getSciVersion() <= SCI_VERSION_1_1) {
+ modifiers |= 0x0200;
+ }
+ }
+
//s->_gui->moveCursor(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y);
switch (curEvent.type) {
@@ -125,7 +145,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
writeSelectorValue(segMan, obj, SELECTOR(message), curEvent.character);
// We only care about the translated character
- writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers);
break;
case SCI_EVENT_MOUSE_RELEASE:
@@ -149,10 +169,11 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
default:
break;
}
+ modifiers |= extra_bits; // add these additional bits to the mix
writeSelectorValue(segMan, obj, SELECTOR(type), curEvent.type);
writeSelectorValue(segMan, obj, SELECTOR(message), 0);
- writeSelectorValue(segMan, obj, SELECTOR(modifiers), (curEvent.modifiers | extra_bits) & modifier_mask);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers);
s->r_acc = make_reg(0, 1);
}
break;
@@ -161,7 +182,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// Return a null event
writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_NONE);
writeSelectorValue(segMan, obj, SELECTOR(message), 0);
- writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask);
+ writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers);
s->r_acc = NULL_REG;
}