aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/script_patches.cpp157
-rw-r--r--engines/sci/graphics/frameout.cpp65
-rw-r--r--engines/sci/graphics/frameout.h22
3 files changed, 167 insertions, 77 deletions
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 7ba5f45bed..b0a307d517 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -107,6 +107,9 @@ static const char *const selectorNameTable[] = {
#ifdef ENABLE_SCI32
"newWith", // SCI2 array script
"scrollSelections", // GK2
+ "posn", // SCI2 benchmarking script
+ "detailLevel", // GK2 benchmarking
+ "view", // RAMA benchmarking
#endif
NULL
};
@@ -141,7 +144,10 @@ enum ScriptPatcherSelectors {
#ifdef ENABLE_SCI32
,
SELECTOR_newWith,
- SELECTOR_scrollSelections
+ SELECTOR_scrollSelections,
+ SELECTOR_posn,
+ SELECTOR_detailLevel,
+ SELECTOR_view
#endif
};
@@ -217,6 +223,34 @@ static const uint16 sci21IntArrayPatch[] = {
0x34, PATCH_UINT16(0x0001), // ldi 0001 (waste bytes)
PATCH_END
};
+
+// Most SCI32 games have a video performance benchmarking loop at the
+// beginning of the game. Running this benchmark with calls to
+// `OSystem::updateScreen` will often cause the benchmark to return a low value,
+// which causes games to disable some visual effects. Running without calls to
+// `OSystem::updateScreen` on any reasonably modern CPU will cause the benchmark
+// to overflow, leading to randomly disabled effects. This patch changes the
+// benchmarking code to always return the game's maximum speed value.
+//
+// Applies to at least: GK1 floppy, PQ4 floppy, PQ4CD, LSL6hires, Phant1,
+// Shivers, SQ6
+static const uint16 sci2BenchmarkSignature[] = {
+ SIG_MAGICDWORD,
+ 0x38, SIG_SELECTOR16(init), // pushi init
+ 0x76, // push0
+ 0x38, SIG_SELECTOR16(posn), // pushi posn
+ SIG_END
+};
+
+static const uint16 sci2BenchmarkPatch[] = {
+ 0x7a, // push2
+ 0x38, SIG_UINT16(64908), // pushi 64908
+ 0x76, // push0
+ 0x43, 0x03, SIG_UINT16(0x04), // callk DisposeScript[3], 4
+ 0x48, // ret
+ PATCH_END
+};
+
#endif
// ===========================================================================
@@ -1042,6 +1076,7 @@ static const SciScriptPatcherEntry gk1Signatures[] = {
{ true, 230, "day 6 police beignet timer issue", 1, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet },
{ true, 230, "day 6 police sleep timer issue", 1, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep },
{ true, 808, "day 10 gabriel dress up infinite turning", 1, gk1SignatureDay10GabrielDressUp, gk1PatchDay10GabrielDressUp },
+ { true, 64908, "disable video benchmarking", 1, sci2BenchmarkSignature, sci2BenchmarkPatch },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature1, sci2NumSavesPatch1 },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature2, sci2NumSavesPatch2 },
{ true, 64990, "disable change directory button", 1, sci2ChangeDirSignature, sci2ChangeDirPatch },
@@ -1095,9 +1130,39 @@ static const uint16 gk2VolumeResetPatch[] = {
PATCH_END
};
+// GK2 has custom video benchmarking code that needs to be disabled; see
+// sci2BenchmarkSignature
+static const uint16 gk2BenchmarkSignature[] = {
+ 0x7e, SIG_ADDTOOFFSET(+2), // line
+ 0x38, SIG_SELECTOR16(new), // pushi new
+ 0x76, // push0
+ 0x51, SIG_ADDTOOFFSET(+1), // class Actor
+ 0x4a, SIG_UINT16(0x04), // send 4
+ 0xa5, 0x00, // sat 0
+ 0x7e, SIG_ADDTOOFFSET(+2), // line
+ 0x7e, SIG_ADDTOOFFSET(+2), // line
+ 0x39, 0x0e, // pushi $e
+ SIG_MAGICDWORD,
+ 0x78, // push1
+ 0x38, SIG_UINT16(0xfdd4), // pushi 64980
+ SIG_END
+};
+
+static const uint16 gk2BenchmarkPatch[] = {
+ 0x38, PATCH_SELECTOR16(detailLevel), // pushi detailLevel
+ 0x78, // push1
+ 0x38, PATCH_UINT16(399), // pushi 10000 / 25 - 1
+ 0x81, 0x01, // lag 1
+ 0x4a, PATCH_UINT16(0x06), // send 6
+ 0x34, PATCH_UINT16(10000), // ldi 10000
+ 0x48, // ret
+ PATCH_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry gk2Signatures[] = {
{ true, 0, "disable volume reset on startup", 1, gk2VolumeResetSignature, gk2VolumeResetPatch },
+ { true, 0, "disable video benchmarking", 1, gk2BenchmarkSignature, gk2BenchmarkPatch },
{ true, 23, "inventory starts scroll down in the wrong direction", 1, gk2InvScrollSignature, gk2InvScrollPatch },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature1, sci2NumSavesPatch1 },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature2, sci2NumSavesPatch2 },
@@ -1980,8 +2045,30 @@ static const uint16 kq7PatchSubtitleFix3[] = {
PATCH_END
};
+// KQ7 has custom video benchmarking code that needs to be disabled; see
+// sci2BenchmarkSignature
+static const uint16 kq7BenchmarkSignature[] = {
+ 0x38, SIG_SELECTOR16(new), // pushi new
+ 0x76, // push0
+ 0x51, SIG_ADDTOOFFSET(+1), // class Actor
+ 0x4a, SIG_UINT16(0x04), // send 4
+ 0xa5, 0x00, // sat 0
+ 0x39, 0x0e, // pushi $e
+ SIG_MAGICDWORD,
+ 0x78, // push1
+ 0x38, SIG_UINT16(0xfdd4), // pushi 64980
+ SIG_END
+};
+
+static const uint16 kq7BenchmarkPatch[] = {
+ 0x34, PATCH_UINT16(10000), // ldi 10000
+ 0x48, // ret
+ PATCH_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry kq7Signatures[] = {
+ { true, 0, "disable video benchmarking", 1, kq7BenchmarkSignature, kq7BenchmarkPatch },
{ true, 31, "subtitle fix 1/3", 1, kq7SignatureSubtitleFix1, kq7PatchSubtitleFix1 },
{ true, 64928, "subtitle fix 2/3", 1, kq7SignatureSubtitleFix2, kq7PatchSubtitleFix2 },
{ true, 64928, "subtitle fix 3/3", 1, kq7SignatureSubtitleFix3, kq7PatchSubtitleFix3 },
@@ -2337,6 +2424,7 @@ static const uint16 larry6HiresPatchVolumeReset[] = {
static const SciScriptPatcherEntry larry6HiresSignatures[] = {
{ true, 71, "disable volume reset on startup", 1, larry6HiresSignatureVolumeReset, larry6HiresPatchVolumeReset },
{ true, 270, "fix incorrect setScale call", 1, larry6HiresSignatureSetScale, larry6HiresPatchSetScale },
+ { true, 64908, "disable video benchmarking", 1, sci2BenchmarkSignature, sci2BenchmarkPatch },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature1, sci2NumSavesPatch1 },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature2, sci2NumSavesPatch2 },
{ true, 64990, "disable change directory button", 1, sci2ChangeDirSignature, sci2ChangeDirPatch },
@@ -3226,6 +3314,7 @@ static const uint16 phant1PatchSavedVolume[] = {
static const SciScriptPatcherEntry phantasmagoriaSignatures[] = {
{ true, 901, "invalid array construction", 1, sci21IntArraySignature, sci21IntArrayPatch },
{ true, 1111, "ignore audio settings from save game", 1, phant1SignatureSavedVolume, phant1PatchSavedVolume },
+ { true, 64908, "disable video benchmarking", 1, sci2BenchmarkSignature, sci2BenchmarkPatch },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -3454,6 +3543,7 @@ static const SciScriptPatcherEntry pq1vgaSignatures[] = {
// script, description, signature patch
static const SciScriptPatcherEntry pq4Signatures[] = {
+ { true, 64908, "disable video benchmarking", 1, sci2BenchmarkSignature, sci2BenchmarkPatch },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature1, sci2NumSavesPatch1 },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature2, sci2NumSavesPatch2 },
{ true, 64990, "disable change directory button", 1, sci2ChangeDirSignature, sci2ChangeDirPatch },
@@ -4526,10 +4616,33 @@ static const uint16 qfg4PatchTrapArrayType[] = {
PATCH_END
};
+// QFG4 has custom video benchmarking code that needs to be disabled; see
+// sci2BenchmarkSignature
+static const uint16 qfg4BenchmarkSignature[] = {
+ 0x38, SIG_SELECTOR16(new), // pushi new
+ 0x76, // push0
+ 0x51, SIG_ADDTOOFFSET(+1), // class View
+ 0x4a, SIG_UINT16(0x04), // send 4
+ 0xa5, 0x00, // sat 0
+ 0x39, 0x0e, // pushi $e
+ SIG_MAGICDWORD,
+ 0x78, // push1
+ 0x38, SIG_UINT16(0x270f), // push $270f (9999)
+ SIG_END
+};
+
+static const uint16 qfg4BenchmarkPatch[] = {
+ 0x35, 0x01, // ldi 0
+ 0xa1, 0xbf, // sag $bf (191)
+ 0x48, // ret
+ PATCH_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry qfg4Signatures[] = {
{ true, 1, "disable volume reset on startup (floppy)", 1, qfg4SignatureVolumeReset, qfg4PatchVolumeReset },
{ true, 1, "disable volume reset on startup (CD)", 1, qfg4CDSignatureVolumeReset, qfg4PatchVolumeReset },
+ { true, 1, "disable video benchmarking", 1, qfg4BenchmarkSignature, qfg4BenchmarkPatch },
{ true, 83, "fix incorrect array type", 1, qfg4SignatureTrapArrayType, qfg4PatchTrapArrayType },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature1, sci2NumSavesPatch1 },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature2, sci2NumSavesPatch2 },
@@ -5104,6 +5217,31 @@ static const SciScriptPatcherEntry sq5Signatures[] = {
#ifdef ENABLE_SCI32
#pragma mark -
+#pragma mark RAMA
+
+// RAMA has custom video benchmarking code that needs to be disabled; see
+// sci2BenchmarkSignature
+static const uint16 ramaBenchmarkSignature[] = {
+ 0x38, SIG_SELECTOR16(view), // pushi view
+ SIG_MAGICDWORD,
+ 0x78, // push1
+ 0x38, SIG_UINT16(0xfdd4), // pushi 64980
+ SIG_END
+};
+
+static const uint16 ramaBenchmarkPatch[] = {
+ 0x34, PATCH_UINT16(10000), // ldi 10000
+ 0x48, // ret
+ PATCH_END
+};
+
+// script, description, signature patch
+static const SciScriptPatcherEntry ramaSignatures[] = {
+ { true, 64908, "disable video benchmarking", 1, ramaBenchmarkSignature, ramaBenchmarkPatch },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+#pragma mark -
#pragma mark Shivers
// In room 35170, there is a CCTV control station with a joystick that must be
@@ -5137,6 +5275,7 @@ static const uint16 shiversPatchSuperCall[] = {
static const SciScriptPatcherEntry shiversSignatures[] = {
{ true, 35170, "fix CCTV joystick interaction", 1, shiversSignatureSuperCall, shiversPatchSuperCall },
{ true, 990, "fix volume & brightness sliders", 2, shiversSignatureSuperCall, shiversPatchSuperCall },
+ { true, 64908, "disable video benchmarking", 1, sci2BenchmarkSignature, sci2BenchmarkPatch },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -5175,6 +5314,18 @@ static const uint16 sq6SlowTransitionPatch2[] = {
PATCH_END
};
+// SQ6 has custom video benchmarking code that needs to be disabled; see
+// sci2BenchmarkSignature. (The sci2BenchmarkPatch is suitable for use with
+// SQ6 as well.)
+static const uint16 sq6BenchmarkSignature[] = {
+ SIG_MAGICDWORD,
+ 0x38, SIG_SELECTOR16(init), // pushi init
+ 0x76, // push0
+ 0x7e, SIG_ADDTOOFFSET(+2), // line
+ 0x38, SIG_SELECTOR16(posn), // pushi $140 (posn)
+ SIG_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry sq6Signatures[] = {
{ true, 0, "fix slow transitions", 1, sq6SlowTransitionSignature2, sq6SlowTransitionPatch2 },
@@ -5184,6 +5335,7 @@ static const SciScriptPatcherEntry sq6Signatures[] = {
{ true, 460, "invalid array construction", 1, sci21IntArraySignature, sci21IntArrayPatch },
{ true, 500, "fix slow transitions", 1, sq6SlowTransitionSignature1, sq6SlowTransitionPatch1 },
{ true, 510, "invalid array construction", 1, sci21IntArraySignature, sci21IntArrayPatch },
+ { true, 64908, "disable video benchmarking", 1, sq6BenchmarkSignature, sci2BenchmarkPatch },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature1, sci2NumSavesPatch1 },
{ true, 64990, "increase number of save games", 1, sci2NumSavesSignature2, sci2NumSavesPatch2 },
{ true, 64990, "disable change directory button", 1, sci2ChangeDirSignature, sci2ChangeDirPatch },
@@ -5787,6 +5939,9 @@ void ScriptPatcher::processScript(uint16 scriptNr, SciSpan<byte> scriptData) {
case GID_QFG4:
signatureTable = qfg4Signatures;
break;
+ case GID_RAMA:
+ signatureTable = ramaSignatures;
+ break;
case GID_SHIVERS:
signatureTable = shiversSignatures;
break;
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 259e3a01b8..d5a7e33c32 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -65,8 +65,6 @@ GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitio
_cursor(cursor),
_segMan(segMan),
_transitions(transitions),
- _benchmarkingFinished(false),
- _throttleFrameOut(true),
_throttleState(0),
_remapOccurred(false),
_overdrawThreshold(0),
@@ -153,28 +151,6 @@ bool GfxFrameout::gameIsHiRes() const {
}
#pragma mark -
-#pragma mark Benchmarking
-
-bool GfxFrameout::checkForFred(const reg_t object) {
- const int16 viewId = readSelectorValue(_segMan, object, SELECTOR(view));
- const SciGameId gameId = g_sci->getGameId();
-
- if (gameId == GID_QFG4 && viewId == 9999) {
- return true;
- }
-
- if (gameId != GID_QFG4 && viewId == -556) {
- return true;
- }
-
- if (Common::String(_segMan->getObjectName(object)) == "fred") {
- return true;
- }
-
- return false;
-}
-
-#pragma mark -
#pragma mark Screen items
void GfxFrameout::addScreenItem(ScreenItem &screenItem) const {
@@ -226,14 +202,6 @@ void GfxFrameout::deleteScreenItem(ScreenItem &screenItem, const reg_t planeObje
}
void GfxFrameout::kernelAddScreenItem(const reg_t object) {
- // The "fred" object is used to test graphics performance;
- // it is impacted by framerate throttling, so disable the
- // throttling when this item is on the screen for the
- // performance check to pass.
- if (!_benchmarkingFinished && _throttleFrameOut && checkForFred(object)) {
- _throttleFrameOut = false;
- }
-
const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
_segMan->getObject(object)->setInfoSelectorFlag(kInfoFlagViewInserted);
@@ -273,15 +241,6 @@ void GfxFrameout::kernelUpdateScreenItem(const reg_t object) {
}
void GfxFrameout::kernelDeleteScreenItem(const reg_t object) {
- // The "fred" object is used to test graphics performance;
- // it is impacted by framerate throttling, so disable the
- // throttling when this item is on the screen for the
- // performance check to pass.
- if (!_benchmarkingFinished && checkForFred(object)) {
- _benchmarkingFinished = true;
- _throttleFrameOut = true;
- }
-
_segMan->getObject(object)->clearInfoSelectorFlag(kInfoFlagViewInserted);
const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
@@ -430,7 +389,7 @@ void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &eraseR
// we must poll for mouse events instead, poll here so that the mouse gets
// updated with its current position at render time. If we do not do this,
// the mouse gets "stuck" during loops that do not make calls to kGetEvent,
- // like transitions and the benchmarking loop at the start of every game.
+ // like transitions.
g_sci->getEventManager()->getSciEvent(SCI_EVENT_PEEK);
RobotDecoder &robotPlayer = g_sci->_video32->getRobotPlayer();
@@ -1177,19 +1136,17 @@ void GfxFrameout::kernelFrameOut(const bool shouldShowBits) {
}
void GfxFrameout::throttle() {
- if (_throttleFrameOut) {
- uint8 throttleTime;
- if (_throttleState == 2) {
- throttleTime = 16;
- _throttleState = 0;
- } else {
- throttleTime = 17;
- ++_throttleState;
- }
-
- g_sci->getEngineState()->speedThrottler(throttleTime);
- g_sci->getEngineState()->_throttleTrigger = true;
+ uint8 throttleTime;
+ if (_throttleState == 2) {
+ throttleTime = 16;
+ _throttleState = 0;
+ } else {
+ throttleTime = 17;
+ ++_throttleState;
}
+
+ g_sci->getEngineState()->speedThrottler(throttleTime);
+ g_sci->getEngineState()->_throttleTrigger = true;
}
void GfxFrameout::shakeScreen(int16 numShakes, const ShakeDirection direction) {
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index 146211544c..650c2c7889 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -61,28 +61,6 @@ public:
void run();
#pragma mark -
-#pragma mark Benchmarking
-private:
- /**
- * Optimization to avoid the more expensive object name
- * comparision on every call to kAddScreenItem and
- * kRemoveScreenItem.
- */
- bool _benchmarkingFinished;
-
- /**
- * Whether or not calls to kFrameOut should be framerate
- * limited to 60fps.
- */
- bool _throttleFrameOut;
-
- /**
- * Determines whether or not a screen item is the "Fred"
- * object.
- */
- bool checkForFred(const reg_t object);
-
-#pragma mark -
#pragma mark Screen items
private:
void remapMarkRedraw();