SCI: script patcher is now a separate class

This commit is contained in:
Martin Kiewitz 2013-12-04 20:42:16 +01:00
parent 37f72f56b2
commit 8bdffcb2fb
10 changed files with 291 additions and 191 deletions

View file

@ -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<ResourceId>::iterator itr;
for (itr = resources.begin(); itr != resources.end(); ++itr) {

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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++;
}
}
}

View file

@ -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

View file

@ -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);

View file

@ -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<int, SegmentId> _scriptSegMap;
ResourceManager *_resMan;
ScriptPatcher *_scriptPatcher;
SegmentId _clonesSegId; ///< ID of the (a) clones segment
SegmentId _listsSegId; ///< ID of the (a) list segment

View file

@ -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);

View file

@ -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;