1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/* 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 {
// Please do not use the #defines, that are called SIG_CODE_* / PATCH_CODE_* inside signature/patch-tables
#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_CODE_ADDTOOFFSET 0xE000
#define SIG_ADDTOOFFSET(_offset_) SIG_CODE_ADDTOOFFSET | (_offset_)
#define SIG_CODE_SELECTOR16 0x9000
#define SIG_SELECTOR16(_selectorID_) SIG_CODE_SELECTOR16 | SELECTOR_##_selectorID_
#define SIG_CODE_SELECTOR8 0x8000
#define SIG_SELECTOR8(_selectorID_) SIG_CODE_SELECTOR8 | SELECTOR_##_selectorID_
#define SIG_CODE_UINT16 0x1000
#define SIG_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8)
#define SIG_CODE_BYTE 0x0000
#define PATCH_END SIG_END
#define PATCH_COMMANDMASK SIG_COMMANDMASK
#define PATCH_VALUEMASK SIG_VALUEMASK
#define PATCH_BYTEMASK SIG_BYTEMASK
#define PATCH_CODE_ADDTOOFFSET SIG_CODE_ADDTOOFFSET
#define PATCH_ADDTOOFFSET(_offset_) SIG_CODE_ADDTOOFFSET | (_offset_)
#define PATCH_CODE_GETORIGINALBYTE 0xC000
#define PATCH_GETORIGINALBYTE(_offset_) PATCH_CODE_GETORIGINALBYTE | (_offset_), 0
#define PATCH_GETORIGINALBYTEADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALBYTE | (_offset_), (uint16)(_adjustValue_)
#define PATCH_CODE_GETORIGINALUINT16 0xD000
#define PATCH_GETORIGINALUINT16(_offset_) PATCH_CODE_GETORIGINALUINT16 | (_offset_), 0
#define PATCH_GETORIGINALUINT16ADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALUINT16 | (_offset_), (uint16)(_adjustValue_)
#define PATCH_CODE_SELECTOR16 SIG_CODE_SELECTOR16
#define PATCH_SELECTOR16(_selectorID_) SIG_CODE_SELECTOR16 | SELECTOR_##_selectorID_
#define PATCH_CODE_SELECTOR8 SIG_CODE_SELECTOR8
#define PATCH_SELECTOR8(_selectorID_) SIG_CODE_SELECTOR8 | SELECTOR_##_selectorID_
#define PATCH_CODE_UINT16 SIG_CODE_UINT16
#define PATCH_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8)
#define PATCH_CODE_BYTE SIG_CODE_BYTE
// defines maximum scratch area for getting original bytes from unpatched script data
#define PATCH_VALUELIMIT 4096
struct SciScriptPatcherEntry {
bool defaultActive;
uint16 scriptNr;
const char *description;
int16 applyCount;
const uint16 *signatureData;
const uint16 *patchData;
};
#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();
// Calculates the magic DWord for fast search and verifies signature/patch data
// Returns the magic DWord in platform-specific byte-order. This is done on purpose for performance.
void calculateMagicDWordAndVerify(const char *signatureDescription, const uint16 *signatureData, bool magicDWordIncluded, uint32 &calculatedMagicDWord, int &calculatedMagicDWordOffset);
// Called when a script is loaded to check for signature matches and apply patches in such cases
void processScript(uint16 scriptNr, SciSpan<byte> scriptData);
// Verifies, if a given signature matches the given script data (pointed to by additional byte offset)
bool verifySignature(uint32 byteOffset, const uint16 *signatureData, const char *signatureDescription, const SciSpan<const byte> &scriptData);
// searches for a given signature inside script data
// returns -1 in case it was not found or an offset to the matching data
int32 findSignature(uint32 magicDWord, int magicOffset, const uint16 *signatureData, const char *patchDescription, const SciSpan<const byte> &scriptData);
private:
// Initializes a patch table and creates run time information for it (for enabling/disabling), also calculates magic DWORD)
void initSignature(const SciScriptPatcherEntry *patchTable);
// Enables a patch inside the patch table (used for optional patches like CD+Text support for KQ6 & LB2)
void enablePatch(const SciScriptPatcherEntry *patchTable, const char *searchDescription);
// Searches for a given signature entry inside script data
// returns -1 in case it was not found or an offset to the matching data
int32 findSignature(const SciScriptPatcherEntry *patchEntry, const SciScriptPatcherRuntimeEntry *runtimeEntry, const SciSpan<const byte> &scriptData);
// Applies a patch to a given script + offset (overwrites parts)
void applyPatch(const SciScriptPatcherEntry *patchEntry, SciSpan<byte> scriptData, int32 signatureOffset);
Selector *_selectorIdTable;
SciScriptPatcherRuntimeEntry *_runtimeTable;
bool _isMacSci11;
};
} // End of namespace Sci
#endif // SCI_ENGINE_WORKAROUNDS_H
|