From 8bdffcb2fb7aefc96aa10fde1bebd372233cac9d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 4 Dec 2013 20:42:16 +0100 Subject: SCI: script patcher is now a separate class --- engines/sci/console.cpp | 2 +- engines/sci/engine/savegame.cpp | 2 +- engines/sci/engine/script.cpp | 7 +- engines/sci/engine/script.h | 9 +- engines/sci/engine/script_patches.cpp | 342 +++++++++++++++++----------------- engines/sci/engine/script_patches.h | 100 ++++++++++ engines/sci/engine/seg_manager.cpp | 7 +- engines/sci/engine/seg_manager.h | 3 +- engines/sci/sci.cpp | 7 +- engines/sci/sci.h | 3 + 10 files changed, 291 insertions(+), 191 deletions(-) create mode 100644 engines/sci/engine/script_patches.h (limited to 'engines/sci') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 80d8ab8257..e7cbde6cbb 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2980,7 +2980,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { Script *script; // Create a custom segment manager here, so that the game's segment // manager won't be affected by loading and unloading scripts here. - SegManager *customSegMan = new SegManager(_engine->getResMan()); + SegManager *customSegMan = new SegManager(_engine->getResMan(), _engine->getScriptPatcher()); Common::List::iterator itr; for (itr = resources.begin(); itr != resources.end(); ++itr) { diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index c60b50a964..fbbab6bcd8 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -484,7 +484,7 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(_nr); if (s.isLoading()) - load(_nr, g_sci->getResMan()); + load(_nr, g_sci->getResMan(), g_sci->getScriptPatcher()); s.skip(4, VER(14), VER(22)); // OBSOLETE: Used to be _bufSize s.skip(4, VER(14), VER(22)); // OBSOLETE: Used to be _scriptSize s.skip(4, VER(14), VER(22)); // OBSOLETE: Used to be _heapSize diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 6616a0ee13..c661a00185 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -32,7 +32,8 @@ namespace Sci { -Script::Script() : SegmentObj(SEG_TYPE_SCRIPT), _buf(NULL) { +Script::Script() + : SegmentObj(SEG_TYPE_SCRIPT), _buf(NULL) { freeScript(); } @@ -65,7 +66,7 @@ void Script::freeScript() { _objects.clear(); } -void Script::load(int script_nr, ResourceManager *resMan) { +void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptPatcher) { freeScript(); Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); @@ -136,7 +137,7 @@ void Script::load(int script_nr, ResourceManager *resMan) { memcpy(_buf, script->data, script->size); // Check scripts for matching signatures and patch those, if found - patcherProcessScript(_nr, _buf, script->size); + scriptPatcher->processScript(_nr, _buf, script->size); if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) { Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0); diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 6a27dc7f64..9e016156b8 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -25,6 +25,7 @@ #include "common/str.h" #include "sci/engine/segment.h" +#include "sci/engine/script_patches.h" namespace Sci { @@ -96,13 +97,7 @@ public: ~Script(); void freeScript(); - void load(int script_nr, ResourceManager *resMan); - - void patcherProcessScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize); - void patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacSci11); - void patcherEnablePatch(SciScriptPatcherEntry *patchTable, const char *searchDescription); - int32 patcherFindSignature(const SciScriptPatcherEntry *patchEntry, const byte *scriptData, const uint32 scriptSize, bool isMacSci11); - void patcherApplyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, bool isMacSci11); + void load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptPatcher); virtual bool isValidOffset(uint16 offset) const; virtual SegmentRef dereference(reg_t pointer); diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 6293fb42ae..5370c59256 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -25,6 +25,7 @@ #include "sci/engine/script.h" #include "sci/engine/state.h" #include "sci/engine/features.h" +#include "sci/engine/script_patches.h" #include "common/util.h" @@ -76,72 +77,27 @@ namespace Sci { // You have to use the exact same order in both the table and the enum, otherwise // it won't work. -#define SIG_END 0xFFFF -#define SIG_MISMATCH 0xFFFE -#define SIG_COMMANDMASK 0xF000 -#define SIG_VALUEMASK 0x0FFF -#define SIG_BYTEMASK 0x00FF -#define SIG_MAGICDWORD 0xF000 -#define SIG_ADDTOOFFSET 0xE000 -#define SIG_SELECTOR16 0x9000 -#define SIG_SELECTOR8 0x8000 -#define SIG_UINT16 0x1000 -#define SIG_BYTE 0x0000 - -#define PATCH_END SIG_END -#define PATCH_COMMANDMASK SIG_COMMANDMASK -#define PATCH_VALUEMASK SIG_VALUEMASK -#define PATCH_BYTEMASK SIG_BYTEMASK -#define PATCH_ADDTOOFFSET SIG_ADDTOOFFSET -#define PATCH_GETORIGINALBYTE 0xD000 -#define PATCH_GETORIGINALBYTEADJUST 0xC000 -#define PATCH_SELECTOR16 SIG_SELECTOR16 -#define PATCH_SELECTOR8 SIG_SELECTOR8 -#define PATCH_UINT16 SIG_UINT16 -#define PATCH_BYTE SIG_BYTE - -// defines maximum scratch area for getting original bytes from unpatched script data -#define PATCH_VALUELIMIT 4096 - -struct SciScriptPatcherEntry { - bool active; - uint16 scriptNr; - const char *description; - int16 applyCount; - uint32 magicDWord; - int magicOffset; - const uint16 *signatureData; - const uint16 *patchData; -}; - -#define SCI_SIGNATUREENTRY_TERMINATOR { false, 0, NULL, 0, 0, 0, NULL, NULL } - -struct SciScriptPatcherSelector { - const char *name; - int16 id; -}; - -SciScriptPatcherSelector selectorTable[] = { - { "cycles", -1, }, // system selector - { "seconds", -1, }, // system selector - { "init", -1, }, // system selector - { "dispose", -1, }, // system selector - { "new", -1, }, // system selector - { "curEvent", -1, }, // system selector - { "disable", -1, }, // system selector - { "show", -1, }, // system selector - { "x", -1, }, // system selector - { "cel", -1, }, // system selector - { "setMotion", -1, }, // system selector - { "deskSarg", -1, }, // Gabriel Knight - { "localize", -1, }, // Freddy Pharkas - { "put", -1, }, // Police Quest 1 VGA - { "solvePuzzle", -1, }, // Quest For Glory 3 - { "timesShownID", -1, }, // Space Quest 1 VGA - { "startText", -1, }, // King's Quest 6 CD / Laura Bow 2 CD for audio+text support - { "startAudio", -1, }, // King's Quest 6 CD / Laura Bow 2 CD for audio+text support - { "modNum", -1, }, // King's Quest 6 CD / Laura Bow 2 CD for audio+text support - { NULL, -1 } +static const char *selectorNameTable[] = { + "cycles", // system selector + "seconds", // system selector + "init", // system selector + "dispose", // system selector + "new", // system selector + "curEvent", // system selector + "disable", // system selector + "show", // system selector + "x", // system selector + "cel", // system selector + "setMotion", // system selector + "deskSarg", // Gabriel Knight + "localize", // Freddy Pharkas + "put", // Police Quest 1 VGA + "solvePuzzle", // Quest For Glory 3 + "timesShownID", // Space Quest 1 VGA + "startText", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support + "startAudio", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support + "modNum", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support + NULL }; enum ScriptPatcherSelectors { @@ -209,9 +165,9 @@ const uint16 camelotPatchPeepingTom[] = { PATCH_END }; -// script, description, signature patch +// script, description, signature patch SciScriptPatcherEntry camelotSignatures[] = { - { true, 62, "fix peepingTom Sierra bug", 1, 0, 0, camelotSignaturePeepingTom, camelotPatchPeepingTom }, + { true, 62, "fix peepingTom Sierra bug", 1, camelotSignaturePeepingTom, camelotPatchPeepingTom }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -278,9 +234,9 @@ const uint16 ecoquest1PatchStayAndHelp[] = { PATCH_END }; -// script, description, signature patch +// script, description, signature patch SciScriptPatcherEntry ecoquest1Signatures[] = { - { true, 660, "CD: bad messagebox and freeze", 1, 0, 0, ecoquest1SignatureStayAndHelp, ecoquest1PatchStayAndHelp }, + { true, 660, "CD: bad messagebox and freeze", 1, ecoquest1SignatureStayAndHelp, ecoquest1PatchStayAndHelp }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -403,10 +359,10 @@ const uint16 ecoquest2PatchEcorderTutorial[] = { PATCH_END }; -// script, description, signature patch +// script, description, signature patch SciScriptPatcherEntry ecoquest2Signatures[] = { - { true, 50, "initial text not removed on ecorder", 1, 0, 0, ecoquest2SignatureEcorder, ecoquest2PatchEcorder }, - { true, 333, "initial text not removed on ecorder tutorial",1, 0, 0, ecoquest2SignatureEcorderTutorial, ecoquest2PatchEcorderTutorial }, + { true, 50, "initial text not removed on ecorder", 1, ecoquest2SignatureEcorder, ecoquest2PatchEcorder }, + { true, 333, "initial text not removed on ecorder tutorial",1, ecoquest2SignatureEcorderTutorial, ecoquest2PatchEcorderTutorial }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -433,9 +389,9 @@ const uint16 fanmadePatchInfiniteLoop[] = { PATCH_END }; -// script, description, signature patch +// script, description, signature patch SciScriptPatcherEntry fanmadeSignatures[] = { - { true, 999, "infinite loop on typo", 1, 0, 0, fanmadeSignatureInfiniteLoop, fanmadePatchInfiniteLoop }, + { true, 999, "infinite loop on typo", 1, fanmadeSignatureInfiniteLoop, fanmadePatchInfiniteLoop }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -556,10 +512,10 @@ const uint16 freddypharkasPatchMacInventory[] = { // script, description, signature patch SciScriptPatcherEntry freddypharkasSignatures[] = { - { true, 0, "CD: score early disposal", 1, 0, 0, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal }, - { true, 15, "Mac: broken inventory", 1, 0, 0, freddypharkasSignatureMacInventory, freddypharkasPatchMacInventory }, - { true, 235, "CD: canister pickup hang", 3, 0, 0, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang }, - { true, 320, "ladder event issue", 2, 0, 0, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent }, + { true, 0, "CD: score early disposal", 1, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal }, + { true, 15, "Mac: broken inventory", 1, freddypharkasSignatureMacInventory, freddypharkasPatchMacInventory }, + { true, 235, "CD: canister pickup hang", 3, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang }, + { true, 320, "ladder event issue", 2, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -697,10 +653,10 @@ const uint16 gk1PatchInterrogationBug[] = { // script, description, signature patch SciScriptPatcherEntry gk1Signatures[] = { - { true, 51, "interrogation bug", 1, 0, 0, gk1SignatureInterrogationBug, gk1PatchInterrogationBug }, - { true, 212, "day 5 phone freeze", 1, 0, 0, gk1SignatureDay5PhoneFreeze, gk1PatchDay5PhoneFreeze }, - { true, 230, "day 6 police beignet timer issue", 1, 0, 0, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet }, - { true, 230, "day 6 police sleep timer issue", 1, 0, 0, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep }, + { true, 51, "interrogation bug", 1, gk1SignatureInterrogationBug, gk1PatchInterrogationBug }, + { true, 212, "day 5 phone freeze", 1, gk1SignatureDay5PhoneFreeze, gk1PatchDay5PhoneFreeze }, + { true, 230, "day 6 police beignet timer issue", 1, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet }, + { true, 230, "day 6 police sleep timer issue", 1, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -821,9 +777,9 @@ const uint16 kq5PatchWinGMSignals[] = { // script, description, signature patch SciScriptPatcherEntry kq5Signatures[] = { - { true, 0, "CD: harpy volume change", 1, 0, 0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume }, - { true, 200, "CD: witch cage init", 1, 0, 0, kq5SignatureWitchCageInit, kq5PatchWitchCageInit }, - { false, 124, "Win: GM Music signal checks", 4, 0, 0, kq5SignatureWinGMSignals, kq5PatchWinGMSignals }, + { true, 0, "CD: harpy volume change", 1, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume }, + { true, 200, "CD: witch cage init", 1, kq5SignatureWitchCageInit, kq5PatchWitchCageInit }, + { false, 124, "Win: GM Music signal checks", 4, kq5SignatureWinGMSignals, kq5PatchWinGMSignals }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1019,19 +975,19 @@ const uint16 kq6laurabow2CDPatchAudioTextSupport5[] = { PATCH_END }; -// script, description, signature patch +// script, description, signature patch SciScriptPatcherEntry kq6Signatures[] = { - { true, 481, "duplicate baby cry", 1, 0, 0, kq6SignatureDuplicateBabyCry, kq6PatchDuplicateBabyCry }, - { true, 907, "inventory stack fix", 1, 0, 0, kq6SignatureInventoryStackFix, kq6PatchInventoryStackFix }, + { true, 481, "duplicate baby cry", 1, kq6SignatureDuplicateBabyCry, kq6PatchDuplicateBabyCry }, + { true, 907, "inventory stack fix", 1, kq6SignatureInventoryStackFix, kq6PatchInventoryStackFix }, // King's Quest 6 and Laura Bow 2 share basic patches for audio + text support // *** King's Quest 6 audio + text support - CURRENTLY DISABLED *** // TODO: fix window placement (currently part of the text windows go off-screen) // TODO: fix hi-res portraits mode graphic glitches - { false, 924, "CD: audio + text support 1", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, - { false, 924, "CD: audio + text support 2", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, - { false, 924, "CD: audio + text support 3", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 }, - { false, 928, "CD: audio + text support 4", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 }, - { false, 928, "CD: audio + text support 5", 2, 0, 0, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 }, + { false, 924, "CD: audio + text support 1", 1, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, + { false, 924, "CD: audio + text support 2", 1, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, + { false, 924, "CD: audio + text support 3", 1, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 }, + { false, 928, "CD: audio + text support 4", 1, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 }, + { false, 928, "CD: audio + text support 5", 2, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1075,9 +1031,9 @@ const uint16 longbowPatchShowHandCode[] = { PATCH_END }; -// script, description, signature patch +// script, description, signature patch SciScriptPatcherEntry longbowSignatures[] = { - { true, 210, "hand code crash", 5, 0, 0, longbowSignatureShowHandCode, longbowPatchShowHandCode }, + { true, 210, "hand code crash", 5, longbowSignatureShowHandCode, longbowPatchShowHandCode }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1119,7 +1075,7 @@ const uint16 larry2PatchWearParachutePoints[] = { // script, description, signature patch SciScriptPatcherEntry larry2Signatures[] = { - { true, 63, "plane: no points for wearing plane", 1, 0, 0, larry2SignatureWearParachutePoints, larry2PatchWearParachutePoints }, + { true, 63, "plane: no points for wearing plane", 1, larry2SignatureWearParachutePoints, larry2PatchWearParachutePoints }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1148,7 +1104,7 @@ const uint16 larry5PatchGermanEndingPattiTalker[] = { // script, description, signature patch SciScriptPatcherEntry larry5Signatures[] = { - { true, 380, "German-only: Enlarge Patti Textbox", 1, 0, 0, larry5SignatureGermanEndingPattiTalker, larry5PatchGermanEndingPattiTalker }, + { true, 380, "German-only: Enlarge Patti Textbox", 1, larry5SignatureGermanEndingPattiTalker, larry5PatchGermanEndingPattiTalker }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1199,7 +1155,7 @@ const uint16 larry6PatchDeathDialog[] = { // script, description, signature patch SciScriptPatcherEntry larry6Signatures[] = { - { true, 82, "death dialog memory corruption", 1, 0, 0, larry6SignatureDeathDialog, larry6PatchDeathDialog }, + { true, 82, "death dialog memory corruption", 1, larry6SignatureDeathDialog, larry6PatchDeathDialog }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1323,14 +1279,14 @@ const uint16 laurabow2CDPatchFixProblematicIconBar[] = { // script, description, signature patch SciScriptPatcherEntry laurabow2Signatures[] = { - { true, 560, "CD: painting closing immediately", 1, 0, 0, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing }, - { true, 0, "CD: fix problematic icon bar", 1, 0, 0, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar }, + { true, 560, "CD: painting closing immediately", 1, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing }, + { true, 0, "CD: fix problematic icon bar", 1, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar }, // King's Quest 6 and Laura Bow 2 share basic patches for audio + text support - { false, 924, "CD: audio + text support 1", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, - { false, 924, "CD: audio + text support 2", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, - { false, 924, "CD: audio + text support 3", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 }, - { false, 928, "CD: audio + text support 4", 1, 0, 0, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 }, - { false, 928, "CD: audio + text support 5", 2, 0, 0, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 }, + { false, 924, "CD: audio + text support 1", 1, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, + { false, 924, "CD: audio + text support 2", 1, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, + { false, 924, "CD: audio + text support 3", 1, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 }, + { false, 928, "CD: audio + text support 4", 1, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 }, + { false, 928, "CD: audio + text support 5", 2, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1370,9 +1326,9 @@ const uint16 mothergoose256PatchSaveLimit[] = { // script, description, signature patch SciScriptPatcherEntry mothergoose256Signatures[] = { - { true, 0, "replay save issue", 1, 0, 0, mothergoose256SignatureReplay, mothergoose256PatchReplay }, - { true, 0, "save limit dialog (SCI1.1)", 1, 0, 0, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit }, - { true, 994, "save limit dialog (SCI1)", 1, 0, 0, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit }, + { true, 0, "replay save issue", 1, mothergoose256SignatureReplay, mothergoose256PatchReplay }, + { true, 0, "save limit dialog (SCI1.1)", 1, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit }, + { true, 994, "save limit dialog (SCI1)", 1, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1435,7 +1391,7 @@ const uint16 pq1vgaPatchPutGunInLockerBug[] = { // script, description, signature patch SciScriptPatcherEntry pq1vgaSignatures[] = { - { true, 341, "put gun in locker bug", 1, 0, 0, pq1vgaSignaturePutGunInLockerBug, pq1vgaPatchPutGunInLockerBug }, + { true, 341, "put gun in locker bug", 1, pq1vgaSignaturePutGunInLockerBug, pq1vgaPatchPutGunInLockerBug }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1633,14 +1589,14 @@ const uint16 qfg1vgaPatchFunnyRoomFix[] = { // script, description, signature patch SciScriptPatcherEntry qfg1vgaSignatures[] = { - { true, 215, "fight event issue", 1, 0, 0, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, - { true, 216, "weapon master event issue", 1, 0, 0, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, - { true, 814, "window text temp space", 1, 0, 0, qfg1vgaSignatureTempSpace, qfg1vgaPatchTempSpace }, - { true, 814, "dialog header offset", 3, 0, 0, qfg1vgaSignatureDialogHeader, qfg1vgaPatchDialogHeader }, - { true, 331, "moving to crusher", 1, 0, 0, qfg1vgaSignatureMoveToCrusher, qfg1vgaPatchMoveToCrusher }, - { true, 41, "moving to castle gate", 1, 0, 0, qfg1vgaSignatureMoveToCastleGate, qfg1vgaPatchMoveToCastleGate }, - { true, 210, "cheetaur description fixed", 1, 0, 0, qfg1vgaSignatureCheetaurDescription, qfg1vgaPatchCheetaurDescription }, - { true, 96, "funny room script bug fixed", 1, 0, 0, qfg1vgaSignatureFunnyRoomFix, qfg1vgaPatchFunnyRoomFix }, + { true, 215, "fight event issue", 1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, + { true, 216, "weapon master event issue", 1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, + { true, 814, "window text temp space", 1, qfg1vgaSignatureTempSpace, qfg1vgaPatchTempSpace }, + { true, 814, "dialog header offset", 3, qfg1vgaSignatureDialogHeader, qfg1vgaPatchDialogHeader }, + { true, 331, "moving to crusher", 1, qfg1vgaSignatureMoveToCrusher, qfg1vgaPatchMoveToCrusher }, + { true, 41, "moving to castle gate", 1, qfg1vgaSignatureMoveToCastleGate, qfg1vgaPatchMoveToCastleGate }, + { true, 210, "cheetaur description fixed", 1, qfg1vgaSignatureCheetaurDescription, qfg1vgaPatchCheetaurDescription }, + { true, 96, "funny room script bug fixed", 1, qfg1vgaSignatureFunnyRoomFix, qfg1vgaPatchFunnyRoomFix }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1678,7 +1634,7 @@ const uint16 qfg2PatchImportDialog[] = { // script, description, signature patch SciScriptPatcherEntry qfg2Signatures[] = { - { true, 944, "import dialog continuous calls", 1, 0, 0, qfg2SignatureImportDialog, qfg2PatchImportDialog }, + { true, 944, "import dialog continuous calls", 1, qfg2SignatureImportDialog, qfg2PatchImportDialog }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1749,8 +1705,8 @@ const uint16 qfg3PatchWooDialog[] = { // script, description, signature patch SciScriptPatcherEntry qfg3Signatures[] = { - { true, 944, "import dialog continuous calls", 1, 0, 0, qfg3SignatureImportDialog, qfg3PatchImportDialog }, - { true, 440, "dialog crash when asking about Woo", 1, 0, 0, qfg3SignatureWooDialog, qfg3PatchWooDialog }, + { true, 944, "import dialog continuous calls", 1, qfg3SignatureImportDialog, qfg3PatchImportDialog }, + { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialog, qfg3PatchWooDialog }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1870,10 +1826,10 @@ const uint16 sq4CdPatchTextOptions[] = { // script, description, signature patch SciScriptPatcherEntry sq4Signatures[] = { - { true, 298, "Floppy: endless flight", 1, 0, 0, sq4FloppySignatureEndlessFlight, sq4FloppyPatchEndlessFlight }, - { true, 818, "CD: Speech and subtitles option", 1, 0, 0, sq4CdSignatureTextOptions, sq4CdPatchTextOptions }, - { true, 0, "CD: Babble icon speech and subtitles fix", 1, 0, 0, sq4CdSignatureBabbleIcon, sq4CdPatchBabbleIcon }, - { true, 818, "CD: Speech and subtitles option button", 1, 0, 0, sq4CdSignatureTextOptionsButton, sq4CdPatchTextOptionsButton }, + { true, 298, "Floppy: endless flight", 1, sq4FloppySignatureEndlessFlight, sq4FloppyPatchEndlessFlight }, + { true, 818, "CD: Speech and subtitles option", 1, sq4CdSignatureTextOptions, sq4CdPatchTextOptions }, + { true, 0, "CD: Babble icon speech and subtitles fix", 1, sq4CdSignatureBabbleIcon, sq4CdPatchBabbleIcon }, + { true, 818, "CD: Speech and subtitles option button", 1, sq4CdSignatureTextOptionsButton, sq4CdPatchTextOptionsButton }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -1947,8 +1903,8 @@ const uint16 sq1vgaPatchEgoShowsCard[] = { // script, description, signature patch SciScriptPatcherEntry sq1vgaSignatures[] = { - { true, 45, "Ulence Flats: timepod graphic glitch", 1, 0, 0, sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch }, - { true, 58, "Sarien armory droid zapping ego first time", 1, 0, 0, sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard }, + { true, 45, "Ulence Flats: timepod graphic glitch", 1, sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch }, + { true, 58, "Sarien armory droid zapping ego first time", 1, sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard }, SCI_SIGNATUREENTRY_TERMINATOR}; // =========================================================================== @@ -2005,13 +1961,31 @@ const uint16 sq5PatchToolboxFix[] = { // script, description, signature patch SciScriptPatcherEntry sq5Signatures[] = { - { true, 226, "toolbox fix", 1, 0, 0, sq5SignatureToolboxFix, sq5PatchToolboxFix }, + { true, 226, "toolbox fix", 1, sq5SignatureToolboxFix, sq5PatchToolboxFix }, SCI_SIGNATUREENTRY_TERMINATOR }; +// ================================================================================= + +ScriptPatcher::ScriptPatcher() { + int selectorCount = ARRAYSIZE(selectorNameTable); + int selectorNr; + + // Allocate table for selector-IDs and initialize that table as well + _selectorIdTable = new Selector[ selectorCount ]; + for (selectorNr = 0; selectorNr < selectorCount; selectorNr++) + _selectorIdTable[selectorNr] = -1; + + _runtimeTable = NULL; +} + +ScriptPatcher::~ScriptPatcher() { + delete[] _runtimeTable; + delete[] _selectorIdTable; +} // will actually patch previously found signature area -void Script::patcherApplyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, const bool isMacSci11) { +void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, const bool isMacSci11) { const uint16 *patchData = patchEntry->patchData; byte orgData[PATCH_VALUELIMIT]; int32 offset = signatureOffset; @@ -2067,7 +2041,7 @@ void Script::patcherApplyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc break; } case PATCH_SELECTOR16: { - patchSelector = selectorTable[patchValue].id; + patchSelector = _selectorIdTable[patchValue]; byte1 = patchSelector & 0xFF; byte2 = patchSelector >> 8; break; @@ -2086,7 +2060,7 @@ void Script::patcherApplyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc break; } case PATCH_SELECTOR8: { - patchSelector = selectorTable[patchValue].id; + patchSelector = _selectorIdTable[patchValue]; if (patchSelector & 0xFF00) error("Script-Patcher: 8 bit selector required, game uses 16 bit selector"); scriptData[offset] = patchSelector & 0xFF; @@ -2103,18 +2077,18 @@ void Script::patcherApplyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc } // will return -1 if no match was found, otherwise an offset to the start of the signature match -int32 Script::patcherFindSignature(const SciScriptPatcherEntry *patchEntry, const byte *scriptData, const uint32 scriptSize, const bool isMacSci11) { +int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize, const bool isMacSci11) { if (scriptSize < 4) // we need to find a DWORD, so less than 4 bytes is not okay return -1; - const uint32 magicDWord = patchEntry->magicDWord; // is platform-specific BE/LE form, so that the later match will work + const uint32 magicDWord = runtimeEntry->magicDWord; // is platform-specific BE/LE form, so that the later match will work const uint32 searchLimit = scriptSize - 3; uint32 DWordOffset = 0; // first search for the magic DWORD while (DWordOffset < searchLimit) { if (magicDWord == READ_UINT32(scriptData + DWordOffset)) { // magic DWORD found, check if actual signature matches - uint32 offset = DWordOffset + patchEntry->magicOffset; + uint32 offset = DWordOffset + runtimeEntry->magicOffset; uint32 byteOffset = offset; const uint16 *signatureData = patchEntry->signatureData; uint16 sigSelector = 0; @@ -2145,7 +2119,7 @@ int32 Script::patcherFindSignature(const SciScriptPatcherEntry *patchEntry, cons break; } case SIG_SELECTOR16: { - sigSelector = selectorTable[sigValue].id; + sigSelector = _selectorIdTable[sigValue]; byte1 = sigSelector & 0xFF; byte2 = sigSelector >> 8; break; @@ -2169,7 +2143,7 @@ int32 Script::patcherFindSignature(const SciScriptPatcherEntry *patchEntry, cons } case SIG_SELECTOR8: { if (byteOffset < scriptSize) { - sigSelector = selectorTable[sigValue].id; + sigSelector = _selectorIdTable[sigValue]; if (sigSelector & 0xFF00) error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", patchEntry->description); if (scriptData[byteOffset] != (sigSelector & 0xFF)) @@ -2208,9 +2182,10 @@ int32 Script::patcherFindSignature(const SciScriptPatcherEntry *patchEntry, cons // This method calculates the magic DWORD for each entry in the signature table // and it also initializes the selector table for selectors used in the signatures/patches of the current game -void Script::patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacSci11) { +void ScriptPatcher::initSignature(SciScriptPatcherEntry *patchTable, bool isMacSci11) { SciScriptPatcherEntry *curEntry = patchTable; - SciScriptPatcherSelector *curSelector = NULL; + SciScriptPatcherRuntimeEntry *curRuntimeEntry; + Selector curSelector = -1; int step; int magicOffset; byte magicDWord[4]; @@ -2221,10 +2196,24 @@ void Script::patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacS uint32 curValue; byte byte1; byte byte2; + int patchEntryCount = 0; + + // Count entries and allocate runtime data + while (curEntry->signatureData) { + patchEntryCount++; curEntry++; + } + _runtimeTable = new SciScriptPatcherRuntimeEntry[patchEntryCount]; + memset(_runtimeTable, 0, sizeof(SciScriptPatcherRuntimeEntry) * patchEntryCount); + curEntry = patchTable; + curRuntimeEntry = _runtimeTable; while (curEntry->signatureData) { // process signature memset(magicDWord, 0, sizeof(magicDWord)); + + curRuntimeEntry->active = curEntry->defaultActive; + curRuntimeEntry->magicDWord = 0; + curRuntimeEntry->magicOffset = 0; for (step = 0; step < 2; step++) { switch (step) { @@ -2240,10 +2229,10 @@ void Script::patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacS switch (curCommand) { case SIG_MAGICDWORD: { if (step == 0) { - if ((curEntry->magicDWord) || (magicDWordLeft)) + if ((curRuntimeEntry->magicDWord) || (magicDWordLeft)) error("Script-Patcher: Magic-DWORD specified multiple times in signature\nFaulty patch: '%s'", curEntry->description); magicDWordLeft = 4; - curEntry->magicOffset = magicOffset; + curRuntimeEntry->magicOffset = magicOffset; } break; } @@ -2271,15 +2260,17 @@ void Script::patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacS break; } case SIG_SELECTOR16: { - curSelector = &selectorTable[curValue]; - if (curSelector->id == -1) - curSelector->id = g_sci->getKernel()->findSelector(curSelector->name); + curSelector = _selectorIdTable[curValue]; + if (curSelector == -1) { + curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]); + _selectorIdTable[curValue] = curSelector; + } if (!isMacSci11) { - byte1 = curSelector->id & 0x00FF; - byte2 = curSelector->id >> 8; + byte1 = curSelector & 0x00FF; + byte2 = curSelector >> 8; } else { - byte1 = curSelector->id >> 8; - byte2 = curSelector->id & 0x00FF; + byte1 = curSelector >> 8; + byte2 = curSelector & 0x00FF; } break; } @@ -2294,7 +2285,7 @@ void Script::patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacS magicDWordLeft--; } if (!magicDWordLeft) { - curEntry->magicDWord = READ_LE_UINT32(magicDWord); + curRuntimeEntry->magicDWord = READ_LE_UINT32(magicDWord); } } break; @@ -2302,15 +2293,16 @@ void Script::patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacS case SIG_BYTE: case SIG_SELECTOR8: { if (curCommand == SIG_SELECTOR8) { - curSelector = &selectorTable[curValue]; - if (curSelector->id == -1) { - curSelector->id = g_sci->getKernel()->findSelector(curSelector->name); - if (curSelector->id != -1) { - if (curSelector->id & 0xFF00) + curSelector = _selectorIdTable[curValue]; + if (curSelector == -1) { + curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]); + _selectorIdTable[curValue] = curSelector; + if (curSelector != -1) { + if (curSelector & 0xFF00) error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", curEntry->description); } } - curValue = curSelector->id; + curValue = curSelector; } magicOffset--; if (magicDWordLeft) { @@ -2318,7 +2310,7 @@ void Script::patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacS magicDWord[4 - magicDWordLeft] = (byte)curValue; magicDWordLeft--; if (!magicDWordLeft) { - curEntry->magicDWord = READ_LE_UINT32(magicDWord); + curRuntimeEntry->magicDWord = READ_LE_UINT32(magicDWord); } } } @@ -2329,35 +2321,38 @@ void Script::patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacS } if (magicDWordLeft) error("Script-Patcher: Magic-DWORD beyond End-Of-Signature\nFaulty patch: '%s'", curEntry->description); - if (!curEntry->magicDWord) + if (!curRuntimeEntry->magicDWord) error("Script-Patcher: Magic-DWORD not specified in signature\nFaulty patch: '%s'", curEntry->description); - curEntry++; + curEntry++; curRuntimeEntry++; } } // This method enables certain patches // It's used for patches, which are not meant to get applied all the time -void Script::patcherEnablePatch(SciScriptPatcherEntry *patchTable, const char *searchDescription) { +void ScriptPatcher::enablePatch(SciScriptPatcherEntry *patchTable, const char *searchDescription) { SciScriptPatcherEntry *curEntry = patchTable; + SciScriptPatcherRuntimeEntry *runtimeEntry = _runtimeTable; int searchDescriptionLen = strlen( searchDescription ); int matchCount = 0; while (curEntry->signatureData) { if (strncmp(curEntry->description, searchDescription, searchDescriptionLen) == 0) { // match found, enable patch - curEntry->active = true; + runtimeEntry->active = true; matchCount++; } - curEntry++; + curEntry++; runtimeEntry++; } if (!matchCount) error("Script-Patcher: no patch found to enable"); } -void Script::patcherProcessScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) { +void ScriptPatcher::processScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) { SciScriptPatcherEntry *signatureTable = NULL; + SciScriptPatcherEntry *curEntry = NULL; + SciScriptPatcherRuntimeEntry *curRuntimeEntry = NULL; const Sci::SciGameId gameId = g_sci->getGameId(); switch (gameId) { @@ -2431,48 +2426,51 @@ void Script::patcherProcessScript(uint16 scriptNr, byte *scriptData, const uint3 if (signatureTable) { bool isMacSci11 = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1); - if (!signatureTable->magicDWord) { + if (!_runtimeTable) { // Abort, in case selectors are not yet initialized (happens for games w/o selector-dictionary) if (!g_sci->getKernel()->selectorNamesAvailable()) return; // signature table needs to get initialized (Magic DWORD set, selector table set) - patcherInitSignature(signatureTable, isMacSci11); + initSignature(signatureTable, isMacSci11); // Do additional game-specific initialization switch (gameId) { case GID_KQ5: if (g_sci->_features->useAltWinGMSound()) { // See the explanation in the kq5SignatureWinGMSignals comment - patcherEnablePatch(signatureTable, "Win: GM Music signal checks"); + enablePatch(signatureTable, "Win: GM Music signal checks"); } break; case GID_LAURABOW2: if (g_sci->speechAndSubtitlesEnabled()) { // Enables Audio + subtitles patches for Laura Bow 2, when "Text and Speech: Both" is selected - patcherEnablePatch(signatureTable, "CD: audio + text support"); + enablePatch(signatureTable, "CD: audio + text support"); } break; default: break; } } + + curEntry = signatureTable; + curRuntimeEntry = _runtimeTable; - while (signatureTable->signatureData) { - if ( (scriptNr == signatureTable->scriptNr) && (signatureTable->active) ) { + while (curEntry->signatureData) { + if ( (scriptNr == curEntry->scriptNr) && (curRuntimeEntry->active) ) { int32 foundOffset = 0; - int16 applyCount = signatureTable->applyCount; + int16 applyCount = curEntry->applyCount; do { - foundOffset = patcherFindSignature(signatureTable, scriptData, scriptSize, isMacSci11); + foundOffset = findSignature(curEntry, curRuntimeEntry, scriptData, scriptSize, isMacSci11); if (foundOffset != -1) { // found, so apply the patch - debugC(kDebugLevelScriptPatcher, "Script-Patcher: '%s' on script %d offset %d", signatureTable->description, scriptNr, foundOffset); - patcherApplyPatch(signatureTable, scriptData, scriptSize, foundOffset, isMacSci11); + debugC(kDebugLevelScriptPatcher, "Script-Patcher: '%s' on script %d offset %d", curEntry->description, scriptNr, foundOffset); + applyPatch(curEntry, scriptData, scriptSize, foundOffset, isMacSci11); } applyCount--; } while ((foundOffset != -1) && (applyCount)); } - signatureTable++; + curEntry++; curRuntimeEntry++; } } } diff --git a/engines/sci/engine/script_patches.h b/engines/sci/engine/script_patches.h new file mode 100644 index 0000000000..77cb2c7ef1 --- /dev/null +++ b/engines/sci/engine/script_patches.h @@ -0,0 +1,100 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SCI_ENGINE_SCRIPT_PATCHES_H +#define SCI_ENGINE_SCRIPT_PATCHES_H + +#include "sci/sci.h" + +namespace Sci { + +#define SIG_END 0xFFFF +#define SIG_MISMATCH 0xFFFE +#define SIG_COMMANDMASK 0xF000 +#define SIG_VALUEMASK 0x0FFF +#define SIG_BYTEMASK 0x00FF +#define SIG_MAGICDWORD 0xF000 +#define SIG_ADDTOOFFSET 0xE000 +#define SIG_SELECTOR16 0x9000 +#define SIG_SELECTOR8 0x8000 +#define SIG_UINT16 0x1000 +#define SIG_BYTE 0x0000 + +#define PATCH_END SIG_END +#define PATCH_COMMANDMASK SIG_COMMANDMASK +#define PATCH_VALUEMASK SIG_VALUEMASK +#define PATCH_BYTEMASK SIG_BYTEMASK +#define PATCH_ADDTOOFFSET SIG_ADDTOOFFSET +#define PATCH_GETORIGINALBYTE 0xD000 +#define PATCH_GETORIGINALBYTEADJUST 0xC000 +#define PATCH_SELECTOR16 SIG_SELECTOR16 +#define PATCH_SELECTOR8 SIG_SELECTOR8 +#define PATCH_UINT16 SIG_UINT16 +#define PATCH_BYTE SIG_BYTE + +// defines maximum scratch area for getting original bytes from unpatched script data +#define PATCH_VALUELIMIT 4096 + +struct SciScriptPatcherEntry { + bool defaultActive; +// bool active; + uint16 scriptNr; + const char *description; + int16 applyCount; +// uint32 magicDWord; +// int magicOffset; + const uint16 *signatureData; + const uint16 *patchData; +}; + +//#define SCI_SIGNATUREENTRY_TERMINATOR { false, 0, NULL, 0, 0, 0, NULL, NULL } +#define SCI_SIGNATUREENTRY_TERMINATOR { false, 0, NULL, 0, NULL, NULL } + +struct SciScriptPatcherRuntimeEntry { + bool active; + uint32 magicDWord; + int magicOffset; +}; + +/** + * ScriptPatcher class, handles on-the-fly patching of script data + */ +class ScriptPatcher { +public: + ScriptPatcher(); + ~ScriptPatcher(); + + void processScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize); + +private: + void initSignature(SciScriptPatcherEntry *patchTable, bool isMacSci11); + void enablePatch(SciScriptPatcherEntry *patchTable, const char *searchDescription); + int32 findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize, bool isMacSci11); + void applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, bool isMacSci11); + + Selector *_selectorIdTable; + SciScriptPatcherRuntimeEntry *_runtimeTable; +}; + +} // End of namespace Sci + +#endif // SCI_ENGINE_WORKAROUNDS_H diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index a059bee74e..161a4f5c79 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -28,7 +28,8 @@ namespace Sci { -SegManager::SegManager(ResourceManager *resMan) { +SegManager::SegManager(ResourceManager *resMan, ScriptPatcher *scriptPatcher) + : _resMan(resMan), _scriptPatcher(scriptPatcher) { _heap.push_back(0); _clonesSegId = 0; @@ -44,8 +45,6 @@ SegManager::SegManager(ResourceManager *resMan) { _stringSegId = 0; #endif - _resMan = resMan; - createClassTable(); } @@ -983,7 +982,7 @@ int SegManager::instantiateScript(int scriptNum) { scr = allocateScript(scriptNum, &segmentId); } - scr->load(scriptNum, _resMan); + scr->load(scriptNum, _resMan, _scriptPatcher); scr->initializeLocals(this); scr->initializeClasses(this); scr->initializeObjects(this, segmentId); diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 074d3f6b0a..b73399d08d 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -49,7 +49,7 @@ public: /** * Initialize the segment manager. */ - SegManager(ResourceManager *resMan); + SegManager(ResourceManager *resMan, ScriptPatcher *scriptPatcher); /** * Deallocate all memory associated with the segment manager. @@ -448,6 +448,7 @@ private: Common::HashMap _scriptSegMap; ResourceManager *_resMan; + ScriptPatcher *_scriptPatcher; SegmentId _clonesSegId; ///< ID of the (a) clones segment SegmentId _listsSegId; ///< ID of the (a) list segment diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 065565d8de..69a7c0bc56 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -38,6 +38,7 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/script.h" // for script_adjust_opcode_formats +#include "sci/engine/script_patches.h" #include "sci/engine/selector.h" // for SELECTOR #include "sci/sound/audio.h" @@ -184,6 +185,7 @@ SciEngine::~SciEngine() { delete[] _opcode_formats; + delete _scriptPatcher; delete _resMan; // should be deleted last g_sci = 0; } @@ -217,8 +219,9 @@ Common::Error SciEngine::run() { // Add the after market GM patches for the specified game, if they exist _resMan->addNewGMPatch(_gameId); _gameObjectAddress = _resMan->findGameObject(); - - SegManager *segMan = new SegManager(_resMan); + + _scriptPatcher = new ScriptPatcher(); + SegManager *segMan = new SegManager(_resMan, _scriptPatcher); // Initialize the game screen _gfxScreen = new GfxScreen(_resMan); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index c91606fbc9..418f8c5e50 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -55,6 +55,7 @@ class AudioPlayer; class SoundCommandParser; class EventManager; class SegManager; +class ScriptPatcher; class GfxAnimate; class GfxCache; @@ -269,6 +270,7 @@ public: bool hasMacIconBar() const; inline ResourceManager *getResMan() const { return _resMan; } + inline ScriptPatcher *getScriptPatcher() const { return _scriptPatcher; } inline Kernel *getKernel() const { return _kernel; } inline EngineState *getEngineState() const { return _gamestate; } inline Vocabulary *getVocabulary() const { return _vocabulary; } @@ -400,6 +402,7 @@ private: const ADGameDescription *_gameDescription; const SciGameId _gameId; ResourceManager *_resMan; /**< The resource manager */ + ScriptPatcher *_scriptPatcher; /**< The script patcher */ EngineState *_gamestate; Kernel *_kernel; Vocabulary *_vocabulary; -- cgit v1.2.3