aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/state.h
diff options
context:
space:
mode:
authorColin Snover2017-05-06 16:37:11 -0500
committerColin Snover2017-05-06 19:03:54 -0500
commit57dd79d4dcb977f9803c8c4d8fe6c19eaac35d90 (patch)
treeaa1f25e65606b0fd848849043bd5982c9a565027 /engines/sci/engine/state.h
parent604ac1a375ca76765133e2b56329763ac5c9874c (diff)
downloadscummvm-rg350-57dd79d4dcb977f9803c8c4d8fe6c19eaac35d90.tar.gz
scummvm-rg350-57dd79d4dcb977f9803c8c4d8fe6c19eaac35d90.tar.bz2
scummvm-rg350-57dd79d4dcb977f9803c8c4d8fe6c19eaac35d90.zip
SCI32: Detect and handle tight loops around kGetEvent
In SSCI, mouse events are received through a hardware interrupt and the cursor is drawn directly to the graphics card by the interrupt handler. This allows game scripts to omit calls to kFrameOut without stopping the mouse cursor from being redrawn in response to mouse movement. ScummVM, in contrast, needs to poll for events and submit screen updates explicitly from the main thread. Submitting screen updates may block on vsync, which means that this call should really only be made once per frame, just after the game has finished updating its back buffer. The closest signal in SCI32 for having completed drawing a frame is the kFrameOut call, so this is where the update is submitted (by calling OSystem::updateScreen). The problem with the approach in ScummVM is that, even though the mouse position is being updated (by calls to kGetEvent) and drawn to the backend's back buffer (by GfxCursor32::drawToHardware), OSystem::updateScreen is never called during game loops that omit calls to kFrameOut. This commit introduces a workaround that looks at the number of times kGetEvent is called between calls to kFrameOut. If the number of kGetEvent calls is higher than usual (where "usual" seems to be 0 or 1), we assume that the game is running one of these tight event loops, and kGetEvent starts calling OSystem::updateScreen until the next kFrameOut call. We also then start throttling the calls to kGetEvent to keep CPU usage down. This fixes at least two such known loops: 1. When interacting with the menu bar at the top of the screen in LSL6hires; 2. When restoring a game in Phant2 and sitting on the "click mouse" screen. A similar workaround may also be needed for kGetTime, though loops around kGetTime should preferably be replaced using a script patch to call kWait instead.
Diffstat (limited to 'engines/sci/engine/state.h')
-rw-r--r--engines/sci/engine/state.h4
1 files changed, 3 insertions, 1 deletions
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;