aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/kevent.cpp24
-rw-r--r--engines/sci/engine/kgraphics32.cpp1
-rw-r--r--engines/sci/engine/state.cpp2
-rw-r--r--engines/sci/engine/state.h4
4 files changed, 27 insertions, 4 deletions
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index 18205a4219..389277b9bc 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -83,9 +83,29 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// For a real event we use its associated mouse position
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2)
+ if (getSciVersion() >= SCI_VERSION_2) {
mousePos = curEvent.mousePosSci;
- else {
+
+ // Some games, like LSL6hires (when interacting with the menu bar) and
+ // Phant2 (when on the "click mouse" screen after restoring a game),
+ // have unthrottled loops that call kGetEvent but do not call kFrameOut.
+ // In these cases we still need to call OSystem::updateScreen to update
+ // the mouse cursor (in SSCI this was not necessary because mouse
+ // updates were made directly to hardware from an interrupt handler),
+ // and we need to throttle these calls so the game does not use 100%
+ // CPU.
+ // This situation seems to be detectable by looking at how many times
+ // kGetEvent has been called between calls to kFrameOut. During normal
+ // game operation, there are usually just 0 or 1 kGetEvent calls between
+ // kFrameOut calls; any more than that indicates that we are probably in
+ // one of these ugly loops and should be updating the screen &
+ // throttling the VM.
+ if (++s->_eventCounter > 2) {
+ g_system->updateScreen();
+ s->speedThrottler(10); // 10ms is an arbitrary value
+ s->_throttleTrigger = true;
+ }
+ } else {
#endif
mousePos = curEvent.mousePos;
// Limit the mouse cursor position, if necessary
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index b0a1c70ed8..38c760fabc 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -234,6 +234,7 @@ reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) {
reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) {
bool showBits = argc > 0 ? argv[0].toUint16() : true;
g_sci->_gfxFrameout->kernelFrameOut(showBits);
+ s->_eventCounter = 0;
return s->r_acc;
}
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 44aecdf0ff..4abf5ce303 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -101,7 +101,7 @@ void EngineState::reset(bool isRestoring) {
gcCountDown = 0;
- _throttleCounter = 0;
+ _eventCounter = 0;
_throttleLastTime = 0;
_throttleTrigger = false;
_gameIsBenchmarking = false;
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index c41f86c781..57839ab04e 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -128,7 +128,9 @@ public:
void speedThrottler(uint32 neededSleep);
void wait(int16 ticks);
- uint32 _throttleCounter; /**< total times kAnimate was invoked */
+#ifdef ENABLE_SCI32
+ uint32 _eventCounter; /**< total times kGetEvent was invoked since the last call to kFrameOut */
+#endif
uint32 _throttleLastTime; /**< last time kAnimate was invoked */
bool _throttleTrigger;
bool _gameIsBenchmarking;