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.
This commit is contained in:
Martin Kiewitz 2016-01-03 18:09:06 +01:00
parent 35e526d34b
commit f9459656f5

View file

@ -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;
}