SCI: Remove speed test detector

This heuristic was originally how all SCI16 speed tests were handled.
It has been gradually replaced with script patches, until all games
were patched in: ea48986006

At the time, I left this in because it had the benefit of speeding up
the SCI11 test variants so that they didn't produce a startup delay.
Now we know that this heuristic has been identifying regular rooms as
speed tests and unthrottling them too, causing unintended effects.
Some of this behavior was masked by fast-cast throttling occurring
everywhere, until: e09010f7d8

For example, the QFG1VGA Sierra logo animation changes speed and runs
very fast as soon as the sparkle is finished. The Longbow map rooms
were also detected as speed test rooms and animated too fast. Cast-less
rooms like LB2's title screen run unthrottled and consume CPU.

There are only a few SCI11 speed test rooms, so now they're explicitly
unthrottled in kGameIsRestarting with the other throttling exceptions.
This commit is contained in:
sluicebox 2022-12-21 12:26:51 -08:00
parent 5f5530d1a8
commit ae5db52c2e
4 changed files with 18 additions and 55 deletions

View File

@ -137,16 +137,20 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) {
neededSleep = 60;
}
break;
case GID_LONGBOW:
// LONWBOW map rooms have no cast, so kAnimate doesn't trigger throttling
// because it thinks it's a speed test room. See: GfxAnimate::throttleSpeed.
// This causes the palette animation to run unthrottled. Sierra also attempts
// to throttle these screens in a conflicting way based on speed test results,
// and we patch that out.
if (s->currentRoomNumber() == 100 || s->currentRoomNumber() == 260) {
s->_throttleTrigger = true;
}
break;
// Don't throttle SCI1.1 speed test rooms. Prevents delays at startup.
// We generically patch these scripts to calculate a passing result,
// but each script performs a different test, so to speed them all up
// it's easier to just let them run unthrottled. See: sci11SpeedTestPatch
case GID_ECOQUEST2: if (s->currentRoomNumber() == 10) s->_throttleTrigger = false; break;
case GID_FREDDYPHARKAS: if (s->currentRoomNumber() == 28) s->_throttleTrigger = false; break;
case GID_GK1DEMO: if (s->currentRoomNumber() == 17) s->_throttleTrigger = false; break;
case GID_KQ5: if (s->currentRoomNumber() == 99) s->_throttleTrigger = false; break;
case GID_KQ6: if (s->currentRoomNumber() == 99) s->_throttleTrigger = false; break;
case GID_LAURABOW2: if (s->currentRoomNumber() == 28) s->_throttleTrigger = false; break;
case GID_LSL6: if (s->currentRoomNumber() == 99) s->_throttleTrigger = false; break;
case GID_QFG1VGA: if (s->currentRoomNumber() == 299) s->_throttleTrigger = false; break;
default:
break;
}

View File

@ -555,9 +555,6 @@ static const uint16 torinLarry7NumSavesPatch[] = {
// We disable speed tests by patching them to return fixed results so that all
// graphics are enabled and games behave consistently. This also fixes the bug
// where tests fail on fast CPUs because their scores overflow. (bug #13529)
// We still have a heuristic in GfxAnimate::throttleSpeed() that attempts to
// detect tests and unthrottle the engine so that they score well. That should
// reasonably handle any games or versions that haven't been patched yet.
//
// Note that these patches are only for SCI16 games; the test was rewritten for
// SCI32 and we have separate patches for those.
@ -618,6 +615,9 @@ static const uint16 sci01SpeedTestLocalPatch[] = {
// The second generation of speed tests measured how much time it takes to do a
// fixed amount of work. Patch the duration calculation to always be zero.
// We also disable speed throttling in these rooms in kGameIsRestarting, but
// that's just to prevent the delay these tests create. Each game's script does
// different work, so that part can't be generically patched.
static const uint16 sci11SpeedTestSignature[] = {
0x76, // push0
0x43, 0x42, 0x00, // callk GetTime 00

View File

@ -710,47 +710,7 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
_ports->setPort(oldPort);
// Now trigger speed throttler
throttleSpeed();
}
void GfxAnimate::throttleSpeed() {
switch (_lastCastData.size()) {
case 0:
// No entries drawn -> no speed throttler triggering
break;
case 1: {
// One entry drawn -> check if that entry was a speed benchmark view, if not enable speed throttler
AnimateEntry *onlyCast = &_lastCastData[0];
// Note that we now use script patches disable speed tests and avoid their overflow errors.
// This heuristic is still useful for any games or versions that haven't been patched yet
// and it does make some of the patched tests complete faster and reduce startup delay.
// first loop and first cel used?
if ((onlyCast->loopNo == 0) && (onlyCast->celNo == 0)) {
// and that cel has a known speed benchmark resolution
int16 onlyHeight = onlyCast->celRect.height();
int16 onlyWidth = onlyCast->celRect.width();
if (((onlyWidth == 12) && (onlyHeight == 35)) || // regular benchmark view ("fred", "Speedy", "ego")
((onlyWidth == 29) && (onlyHeight == 45)) || // King's Quest 5 french "fred"
((onlyWidth == 1) && (onlyHeight == 5)) || // Freddy Pharkas "fred"
((onlyWidth == 1) && (onlyHeight == 1))) { // Laura Bow 2 Talkie
// check further that there is only one cel in that view
GfxView *onlyView = _cache->getView(onlyCast->viewId);
if ((onlyView->getLoopCount() == 1) && (onlyView->getCelCount(0))) {
return;
}
}
}
_s->_throttleTrigger = true;
break;
}
default:
// More than 1 entry drawn -> time for speed throttling
_s->_throttleTrigger = true;
break;
}
_s->_throttleTrigger = true;
}
void GfxAnimate::addToPicSetPicNotValid() {

View File

@ -117,7 +117,6 @@ private:
void addToPicSetPicNotValid();
void animateShowPic();
void throttleSpeed();
void adjustInvalidCels(GfxView *view, AnimateList::iterator it);
void processViewScaling(GfxView *view, AnimateList::iterator it);
void setNsRect(GfxView *view, AnimateList::iterator it);