aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kevent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/kevent.cpp')
-rw-r--r--engines/sci/engine/kevent.cpp73
1 files changed, 50 insertions, 23 deletions
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index 8e16e0a07a..534d9ce713 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;
@@ -58,7 +59,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// In case we use a simulated event we query the current mouse position
mousePos = g_sci->_gfxCursor->getPosition();
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1)
+ if (getSciVersion() >= SCI_VERSION_2_1_EARLY)
g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
#endif
// Limit the mouse cursor position, if necessary
@@ -82,11 +83,12 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
}
// For a real event we use its associated mouse position
- mousePos = curEvent.mousePos;
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1)
- g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
+ if (getSciVersion() >= SCI_VERSION_2)
+ mousePos = curEvent.mousePosSci;
+ else
#endif
+ mousePos = curEvent.mousePos;
// Limit the mouse cursor position, if necessary
g_sci->_gfxCursor->refreshPosition();
@@ -100,7 +102,25 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// question. Check GfxCursor::setPosition(), for a more detailed
// explanation and a list of cursor position workarounds.
if (s->_cursorWorkaroundRect.contains(mousePos.x, mousePos.y)) {
- s->_cursorWorkaroundActive = false;
+ // For OpenPandora and possibly other platforms, that support analog-stick control + touch screen
+ // control at the same time: in case the cursor is currently at the coordinate set by the scripts,
+ // we will count down instead of immediately disabling the workaround.
+ // On OpenPandora the cursor position is set, but it's overwritten shortly afterwards by the
+ // touch screen. In this case we would sometimes disable the workaround, simply because the touch
+ // screen hasn't yet overwritten the position and thus the workaround would not work anymore.
+ // On OpenPandora it would sometimes work and sometimes not without this.
+ if (s->_cursorWorkaroundPoint == mousePos) {
+ // Cursor is still at the same spot as set by the scripts
+ if (s->_cursorWorkaroundPosCount > 0) {
+ s->_cursorWorkaroundPosCount--;
+ } else {
+ // Was for quite a bit of time at that spot, so disable workaround now
+ s->_cursorWorkaroundActive = false;
+ }
+ } else {
+ // Cursor has moved, but is within the rect -> disable workaround immediately
+ s->_cursorWorkaroundActive = false;
+ }
} else {
mousePos.x = s->_cursorWorkaroundPoint.x;
mousePos.y = s->_cursorWorkaroundPoint.y;
@@ -110,7 +130,27 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
writeSelectorValue(segMan, obj, SELECTOR(x), mousePos.x);
writeSelectorValue(segMan, obj, SELECTOR(y), mousePos.y);
- //s->_gui->moveCursor(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.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 the SCI1 keyboard driver.
+ // SCI32 also resets the upper byte.
+
+ // This was verified in SSCI itself by creating a SCI game and checking behavior.
+ if (getSciVersion() <= SCI_VERSION_01) {
+ modifiers |= 0x0200;
+ }
+ }
switch (curEvent.type) {
case SCI_EVENT_QUIT:
@@ -125,34 +165,21 @@ 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:
case SCI_EVENT_MOUSE_PRESS:
-
// track left buttton clicks, if requested
- if (curEvent.type == SCI_EVENT_MOUSE_PRESS && curEvent.data == 1 && g_debug_track_mouse_clicks) {
+ if (curEvent.type == SCI_EVENT_MOUSE_PRESS && curEvent.modifiers == 0 && g_debug_track_mouse_clicks) {
g_sci->getSciDebugger()->debugPrintf("Mouse clicked at %d, %d\n",
mousePos.x, mousePos.y);
}
if (mask & curEvent.type) {
- int extra_bits = 0;
-
- switch (curEvent.data) {
- case 2:
- extra_bits = SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT;
- break;
- case 3:
- extra_bits = SCI_KEYMOD_CTRL;
- default:
- break;
- }
-
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 +188,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;
}