From f9459656f56e52930fca10ef6ab7fa143fd11b15 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 3 Jan 2016 18:09:06 +0100 Subject: 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. --- engines/sci/engine/kevent.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'engines/sci/engine') 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; } -- cgit v1.2.3