[Scummvm-cvs-logs] scummvm master -> de0151a26dbc5abf5c4aa80ae3cf4f073bd138b0

m-kiewitz m_kiewitz at users.sourceforge.net
Sun Nov 3 23:51:14 CET 2013


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
3fbbdbc2da SCI: improved script patcher
de0151a26d Merge branch 'master' of github.com:scummvm/scummvm


Commit: 3fbbdbc2dac29b63547d9302b531015433fcb625
    https://github.com/scummvm/scummvm/commit/3fbbdbc2dac29b63547d9302b531015433fcb625
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2013-11-03T14:49:31-08:00

Commit Message:
SCI: improved script patcher

Gabriel Knight + King's Quest 6 patches now also work for Mac versions of those games
added support for selectors instead of using hardcoded values

Changed paths:
    engines/sci/engine/script.cpp
    engines/sci/engine/script.h
    engines/sci/engine/script_patches.cpp



diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 36d2841..6616a0e 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -136,7 +136,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
-	matchSignatureAndPatch(_nr, _buf, script->size);
+	patcherProcessScript(_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 7dde7f4..56a9004 100644
--- a/engines/sci/engine/script.h
+++ b/engines/sci/engine/script.h
@@ -30,7 +30,7 @@ namespace Sci {
 
 struct EngineState;
 class ResourceManager;
-struct SciScriptSignature;
+struct SciScriptPatcherEntry;
 
 enum ScriptObjectTypes {
 	SCI_OBJ_TERMINATOR,
@@ -98,9 +98,10 @@ public:
 	void freeScript();
 	void load(int script_nr, ResourceManager *resMan);
 
-	void matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize);
-	int32 findSignature(const SciScriptSignature *signature, const byte *scriptData, const uint32 scriptSize, bool isMacSci11);
-	void applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, bool isMacSci11);
+	void patcherProcessScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize);
+	void patcherInitSignature(SciScriptPatcherEntry *patchTable, bool isMacSci11);
+	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);
 
 	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 cb80ba7..94e3510 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "sci/sci.h"
+#include "sci/engine/kernel.h"
 #include "sci/engine/script.h"
 #include "sci/engine/state.h"
 #include "sci/engine/features.h"
@@ -34,41 +35,83 @@ namespace Sci {
 #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                   0xFFFF
-#define PATCH_COMMANDMASK           0xF000
-#define PATCH_VALUEMASK             0x0FFF
-#define PATCH_BYTEMASK              0x00FF
-#define PATCH_ADDTOOFFSET           0xE000
+#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_ADJUSTWORD            0xB000
-#define PATCH_ADJUSTWORD_NEG        0xA000
-#define PATCH_UINT16                0x1000
+#define PATCH_SELECTOR16            SIG_SELECTOR16
+#define PATCH_SELECTOR8             SIG_SELECTOR8
+#define PATCH_UINT16                SIG_UINT16
+#define PATCH_BYTE                  SIG_BYTE
 
-#define PATCH_MAGICDWORD(a, b, c, d) CONSTANT_LE_32(a | (b << 8) | (c << 16) | (d << 24))
+// defines maximum scratch area for getting original bytes from unpatched script data
 #define PATCH_VALUELIMIT      4096
 
-struct SciScriptSignature {
+struct SciScriptPatcherEntry {
 	uint16 scriptNr;
 	const char *description;
 	int16 applyCount;
 	uint32 magicDWord;
 	int magicOffset;
-	const uint16 *data;
-	const uint16 *patch;
+	const uint16 *signatureData;
+	const uint16 *patchData;
 };
 
 #define SCI_SIGNATUREENTRY_TERMINATOR { 0, NULL, 0, 0, 0, NULL, NULL }
 
-// signatures are built like this:
-//  - first a counter of the bytes that follow
-//  - then the actual bytes that need to get matched
-//  - then another counter of bytes (0 for EOS)
-//  - if not EOS, an adjust offset and the actual bytes
-//  - rinse and repeat
+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
+	NULL,                -1
+};
+
+enum ScriptPatcherSelectors {
+	SELECTOR_cycles = 0,
+	SELECTOR_seconds,
+	SELECTOR_init,
+	SELECTOR_dispose,
+	SELECTOR_new,
+	SELECTOR_curEvent,
+	SELECTOR_disable,
+	SELECTOR_show,
+	SELECTOR_x,
+	SELECTOR_cel,
+	SELECTOR_setMotion,
+	SELECTOR_deskSarg,
+	SELECTOR_localize,
+	SELECTOR_put,
+	SELECTOR_solvePuzzle,
+	SELECTOR_timesShownID
+};
 
 // ===========================================================================
 // Conquests of Camelot
@@ -91,7 +134,7 @@ struct SciScriptSignature {
 // Responsible method: fawaz::handleEvent
 // Fixes bug #3614969
 const uint16 camelotSignaturePeepingTom[] = {
-	0x72, SIG_UINT16 + 0x7e, 0x07,   // lofsa fawaz <-- start of proper initializion code
+	0x72, SIG_MAGICDWORD, SIG_UINT16 + 0x7e, 0x07, // lofsa fawaz <-- start of proper initializion code
 	0xa1, 0xb9,                      // sag b9h
 	SIG_ADDTOOFFSET +571,            // skip 571 bytes
 	0x39, 0x7a,                      // pushi 7a <-- initialization code when walking automatically
@@ -113,9 +156,9 @@ const uint16 camelotPatchPeepingTom[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                 adjust
-const SciScriptSignature camelotSignatures[] = {
-	{    62, "fix peepingTom Sierra bug", 1, PATCH_MAGICDWORD(0x7e, 0x07, 0xa1, 0xb9), -1, camelotSignaturePeepingTom, camelotPatchPeepingTom },
+//    script, description,                                            signature                   patch
+SciScriptPatcherEntry camelotSignatures[] = {
+	{    62, "fix peepingTom Sierra bug",                    1, 0, 0, camelotSignaturePeepingTom, camelotPatchPeepingTom },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -124,7 +167,10 @@ const SciScriptSignature camelotSignatures[] = {
 //  boundaries of room 660. Normally a textbox is supposed to get on screen
 //  but the call is wrong, so not only do we get an error message the script
 //  is also hanging because the cue won't get sent out
-//  This also happens in sierra sci - refer to bug #3038387
+//  This also happens in sierra sci
+// Applies to at least: PC-CD
+// Responsible method: stayAndHelp::changeState
+// Fixes bug: #3038387
 const uint16 ecoquest1SignatureStayAndHelp[] = {
 	0x3f, 0x01,                      // link 01
 	0x87, 0x01,                      // lap param[1]
@@ -136,12 +182,13 @@ const uint16 ecoquest1SignatureStayAndHelp[] = {
 	0x31, 0x1c,                      // bnt [next state]
 	0x76,                            // push0
 	0x45, 0x01, 0x00,                // callb export1 from script 0 (switching control off)
+	SIG_MAGICDWORD,
 	0x38, SIG_UINT16 + 0x22, 0x01,   // pushi 0122
 	0x78,                            // push1
 	0x76,                            // push0
 	0x81, 0x00,                      // lag global[0]
 	0x4a, 0x06,                      // send 06 - call ego::setMotion(0)
-	0x39, 0x6e,                      // pushi 6e (selector init)
+	0x39, SIG_SELECTOR8 + SELECTOR_init, // pushi "init"
 	0x39, 0x04,                      // pushi 04
 	0x76,                            // push0
 	0x76,                            // push0
@@ -165,7 +212,7 @@ const uint16 ecoquest1PatchStayAndHelp[] = {
 	0x76,                            // push0
 	0x81, 0x00,                      // lag global[0]
 	0x4a, 0x06,                      // send 06 - call ego::setMotion(0)
-	0x39, 0x6e,                      // pushi 6e (selector init)
+	0x39, PATCH_SELECTOR8 + SELECTOR_init, // pushi "init"
 	0x39, 0x06,                      // pushi 06
 	0x39, 0x02,                      // pushi 02 (additional 2 bytes)
 	0x76,                            // push0
@@ -178,9 +225,9 @@ const uint16 ecoquest1PatchStayAndHelp[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                 adjust
-const SciScriptSignature ecoquest1Signatures[] = {
-	{    660, "CD: bad messagebox and freeze",               1, PATCH_MAGICDWORD(0x38, 0x22, 0x01, 0x78),   -17, ecoquest1SignatureStayAndHelp, ecoquest1PatchStayAndHelp },
+//    script, description,                                            signature                      patch
+SciScriptPatcherEntry ecoquest1Signatures[] = {
+	{    660, "CD: bad messagebox and freeze",               1, 0, 0, ecoquest1SignatureStayAndHelp, ecoquest1PatchStayAndHelp },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -195,6 +242,7 @@ const uint16 ecoquest2SignatureEcorder[] = {
 	0x39, 0x0a,                      // pushi 0a
 	0x5b, 0x04, 0x1e,                // lea temp[1e]
 	0x36,                            // push
+	SIG_MAGICDWORD,
 	0x39, 0x64,                      // pushi 64
 	0x39, 0x7d,                      // pushi 7d
 	0x39, 0x32,                      // pushi 32
@@ -249,6 +297,7 @@ const uint16 ecoquest2SignatureEcorderTutorial[] = {
 	0x39, 0x0a,                      // pushi 0a
 	0x5b, 0x04, 0x1f,                // lea temp[1f]
 	0x36,                            // push
+	SIG_MAGICDWORD,
 	0x39, 0x64,                      // pushi 64
 	0x39, 0x7d,                      // pushi 7d
 	0x39, 0x32,                      // pushi 32
@@ -267,42 +316,42 @@ const uint16 ecoquest2SignatureEcorderTutorial[] = {
 };
 
 const uint16 ecoquest2PatchEcorderTutorial[] = {
-	0x31, 0x23,        // bnt [next state] (save 1 byte)
+	0x31, 0x23,                      // bnt [next state] (save 1 byte)
 	// The parameter count below should be 7, but we're out of bytes
 	// to patch! A workaround has been added because of this
-	0x78,              // push1 (parameter count)
-	//0x39, 0x07,        // pushi 07 (parameter count)
-	0x39, 0x0b,        // push (FillBoxAny)
-	0x39, 0x1d,        // pushi 29d
-	0x39, 0x73,        // pushi 115d
-	0x39, 0x5e,        // pushi 94d
-	0x38, 0xd7, 0x00,  // pushi 215d
-	0x78,              // push1 (visual screen)
-	0x39, 0x17,        // pushi 17 (color)
-	0x43, 0x6c, 0x0e,  // call kGraph
+	0x78,                            // push1 (parameter count)
+	//0x39, 0x07,                    // pushi 07 (parameter count)
+	0x39, 0x0b,                      // push (FillBoxAny)
+	0x39, 0x1d,                      // pushi 29d
+	0x39, 0x73,                      // pushi 115d
+	0x39, 0x5e,                      // pushi 94d
+	0x38, PATCH_UINT16 + 0xd7, 0x00, // pushi 215d
+	0x78,                            // push1 (visual screen)
+	0x39, 0x17,                      // pushi 17 (color)
+	0x43, 0x6c, 0x0e,                // call kGraph
 	// The parameter count below should be 5, but we're out of bytes
 	// to patch! A workaround has been added because of this
-	0x78,              // push1 (parameter count)
-	//0x39, 0x05,        // pushi 05 (parameter count)
-	0x39, 0x0c,        // pushi 12d (UpdateBox)
-	0x39, 0x1d,        // pushi 29d
-	0x39, 0x73,        // pushi 115d
-	0x39, 0x5e,        // pushi 94d
-	0x38, 0xd7, 0x00,  // pushi 215d
-	0x43, 0x6c, 0x0a,  // call kGraph
+	0x78,                            // push1 (parameter count)
+	//0x39, 0x05,                    // pushi 05 (parameter count)
+	0x39, 0x0c,                      // pushi 12d (UpdateBox)
+	0x39, 0x1d,                      // pushi 29d
+	0x39, 0x73,                      // pushi 115d
+	0x39, 0x5e,                      // pushi 94d
+	0x38, PATCH_UINT16 + 0xd7, 0x00, // pushi 215d
+	0x43, 0x6c, 0x0a,                // call kGraph
 	// We are out of bytes to patch at this point,
 	// so we skip 494 (0x1EE) bytes to reuse this code:
 	// ldi 1e
 	// aTop 20
 	// jmp 030e (jump to end)
-	0x32, 0xee, 0x01,  // skip 494 (0x1EE) bytes
+	0x32, PATCH_UINT16 + 0xee, 0x01, // skip 494 (0x1EE) bytes
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                 adjust
-const SciScriptSignature ecoquest2Signatures[] = {
-	{     50, "initial text not removed on ecorder",         1, PATCH_MAGICDWORD(0x39, 0x64, 0x39, 0x7d),    -8, ecoquest2SignatureEcorder, ecoquest2PatchEcorder },
-	{    333, "initial text not removed on ecorder tutorial",1, PATCH_MAGICDWORD(0x39, 0x64, 0x39, 0x7d),    -9, ecoquest2SignatureEcorderTutorial, ecoquest2PatchEcorderTutorial },
+//    script, description,                                            signature                          patch
+SciScriptPatcherEntry ecoquest2Signatures[] = {
+	{     50, "initial text not removed on ecorder",         1, 0, 0, ecoquest2SignatureEcorder,         ecoquest2PatchEcorder },
+	{    333, "initial text not removed on ecorder tutorial",1, 0, 0, ecoquest2SignatureEcorderTutorial, ecoquest2PatchEcorderTutorial },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -317,6 +366,7 @@ const uint16 fanmadeSignatureInfiniteLoop[] = {
 	0x39, 0x00,                      // pushi 00
 	0x87, 0x01,                      // lap 01
 	0x4b, 0x04,                      // send 04
+	SIG_MAGICDWORD,
 	0x18,                            // not
 	0x30, SIG_UINT16 + 0x2f, 0x00,   // bnt 002f  [06a5]	--> jmp ffbc  [0664] --> BUG! infinite loop
 	SIG_END
@@ -328,9 +378,9 @@ const uint16 fanmadePatchInfiniteLoop[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                 adjust
-const SciScriptSignature fanmadeSignatures[] = {
-	{    999, "infinite loop on typo",                       1, PATCH_MAGICDWORD(0x18, 0x30, 0x2f, 0x00),    -9, fanmadeSignatureInfiniteLoop, fanmadePatchInfiniteLoop },
+//    script, description,                                            signature                     patch
+SciScriptPatcherEntry fanmadeSignatures[] = {
+	{    999, "infinite loop on typo",                       1, 0, 0, fanmadeSignatureInfiniteLoop, fanmadePatchInfiniteLoop },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -342,13 +392,16 @@ const SciScriptSignature fanmadeSignatures[] = {
 //   was already playing in the sound driver. In our case we would also stop
 //   the sample from playing, so we patch it out
 //   The "score" code is already buggy and sets volume to 0 when playing
+// Applies to at least: English PC-CD
+// Responsible method: unknown
 const uint16 freddypharkasSignatureScoreDisposal[] = {
-	0x67, 0x32,       // pTos 32 (selector theAudCount)
-	0x78,             // push1
-	0x39, 0x0d,       // pushi 0d
-	0x43, 0x75, 0x02, // call kDoAudio
-	0x1c,             // ne?
-	0x31,             // bnt (-> to skip disposal)
+	0x67, 0x32,                      // pTos 32 (selector theAudCount)
+	0x78,                            // push1
+	SIG_MAGICDWORD,
+	0x39, 0x0d,                      // pushi 0d
+	0x43, 0x75, 0x02,                // call kDoAudio
+	0x1c,                            // ne?
+	0x31,                            // bnt (-> to skip disposal)
 	SIG_END
 };
 
@@ -365,9 +418,12 @@ const uint16 freddypharkasPatchScoreDisposal[] = {
 //   in IconBar::disable doing endless loops even in sierra sci, because there
 //   is no enabled icon left. We remove disabling of icon 8 (which is help),
 //   this fixes the issue.
+// Applies to at least: English PC-CD
+// Responsible method: rm235::init and sEnterFrom500::changeState
 const uint16 freddypharkasSignatureCanisterHang[] = {
-	0x38, SIG_UINT16 + 0xf1, 0x00,   // pushi f1 (selector disable)
+	0x38, SIG_SELECTOR16 + SELECTOR_disable, // pushi disable
 	0x7a,                            // push2
+	SIG_MAGICDWORD,
 	0x39, 0x07,                      // pushi 07
 	0x39, 0x08,                      // pushi 08
 	0x81, 0x45,                      // lag 45
@@ -377,11 +433,11 @@ const uint16 freddypharkasSignatureCanisterHang[] = {
 
 const uint16 freddypharkasPatchCanisterHang[] = {
 	PATCH_ADDTOOFFSET | +3,
-	0x78,             // push1
+	0x78,                            // push1
 	PATCH_ADDTOOFFSET | +2,
-	0x33, 0x00,       // ldi 00 (waste 2 bytes)
+	0x33, 0x00,                      // ldi 00 (waste 2 bytes)
 	PATCH_ADDTOOFFSET | +3,
-	0x06,             // send 06 - call IconBar::disable(7)
+	0x06,                            // send 06 - call IconBar::disable(7)
 	PATCH_END
 };
 
@@ -393,35 +449,41 @@ const uint16 freddypharkasPatchCanisterHang[] = {
 //   ego, sometimes clicks also won't get registered. Strangely it's not nearly
 //   as bad as in our sci, but these differences may be caused by timing.
 //   We just reuse the active event, thus removing the duplicate kGetEvent call.
+// Applies to at least: English PC-CD, German Floppy, English Mac
+// Responsible method: lowerLadder::doit and highLadder::doit
 const uint16 freddypharkasSignatureLadderEvent[] = {
-	0x39, 0x6d,                      // pushi 6d (selector new)
+	0x39, SIG_MAGICDWORD,
+	SIG_SELECTOR8 + SELECTOR_new,    // pushi new
 	0x76,                            // push0
-	0x38, SIG_UINT16 + 0xf5, 0x00,   // pushi f5 (selector curEvent)
+	0x38, SIG_SELECTOR16 + SELECTOR_curEvent, // pushi curEvent
 	0x76,                            // push0
 	0x81, 0x50,                      // lag global[50]
 	0x4a, 0x04,                      // send 04 - read User::curEvent
 	0x4a, 0x04,                      // send 04 - call curEvent::new
 	0xa5, 0x00,                      // sat temp[0]
-	0x38, SIG_UINT16 + 0x94, 0x00,   // pushi 94 (selector localize)
+	0x38, SIG_SELECTOR16 + SELECTOR_localize,
 	0x76,                            // push0
 	0x4a, 0x04,                      // send 04 - call curEvent::localize
 	SIG_END
 };
 
 const uint16 freddypharkasPatchLadderEvent[] = {
-	0x34, 0x00, 0x00, // ldi 0000 (waste 3 bytes, overwrites first 2 pushes)
+	0x34, 0x00, 0x00,                // ldi 0000 (waste 3 bytes, overwrites first 2 pushes)
 	PATCH_ADDTOOFFSET | +8,
-	0xa5, 0x00,       // sat temp[0] (waste 2 bytes, overwrites 2nd send)
+	0xa5, 0x00,                      // sat temp[0] (waste 2 bytes, overwrites 2nd send)
 	PATCH_ADDTOOFFSET | +2,
-	0x34, 0x00, 0x00, // ldi 0000
-	0x34, 0x00, 0x00, // ldi 0000 (waste 6 bytes, overwrites last 3 opcodes)
+	0x34, 0x00, 0x00,                // ldi 0000
+	0x34, 0x00, 0x00,                // ldi 0000 (waste 6 bytes, overwrites last 3 opcodes)
 	PATCH_END
 };
 
 // In the Macintosh version of Freddy Pharkas, kRespondsTo is broken for
 // property selectors. They hacked the script to work around the issue,
 // so we revert the script back to using the values of the DOS script.
+// Applies to at least: English Mac
+// Responsible method: unknown
 const uint16 freddypharkasSignatureMacInventory[] = {
+	SIG_MAGICDWORD,
 	0x39, 0x23,                      // pushi 23
 	0x39, 0x74,                      // pushi 74
 	0x78,                            // push1
@@ -437,28 +499,31 @@ const uint16 freddypharkasPatchMacInventory[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature freddypharkasSignatures[] = {
-	{      0, "CD: score early disposal",                    1, PATCH_MAGICDWORD(0x39, 0x0d, 0x43, 0x75),    -3, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal },
-	{     15, "Mac: broken inventory",                       1, PATCH_MAGICDWORD(0x39, 0x23, 0x39, 0x74),     0, freddypharkasSignatureMacInventory,  freddypharkasPatchMacInventory },
-	{    235, "CD: canister pickup hang",                    3, PATCH_MAGICDWORD(0x39, 0x07, 0x39, 0x08),    -4, freddypharkasSignatureCanisterHang,  freddypharkasPatchCanisterHang },
-	{    320, "ladder event issue",                          2, PATCH_MAGICDWORD(0x6d, 0x76, 0x38, 0xf5),    -1, freddypharkasSignatureLadderEvent,   freddypharkasPatchLadderEvent },
+//    script, description,                                            signature                            patch
+SciScriptPatcherEntry freddypharkasSignatures[] = {
+	{      0, "CD: score early disposal",                    1, 0, 0, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal },
+	{     15, "Mac: broken inventory",                       1, 0, 0, freddypharkasSignatureMacInventory,  freddypharkasPatchMacInventory },
+	{    235, "CD: canister pickup hang",                    3, 0, 0, freddypharkasSignatureCanisterHang,  freddypharkasPatchCanisterHang },
+	{    320, "ladder event issue",                          2, 0, 0, freddypharkasSignatureLadderEvent,   freddypharkasPatchLadderEvent },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
 // ===========================================================================
 // daySixBeignet::changeState (4) is called when the cop goes out and sets cycles to 220.
 //  this is not enough time to get to the door, so we patch that to 23 seconds
+// Applies to at least: English PC-CD, German PC-CD, English Mac
+// Responsible method: daySixBeignet::changeState
 const uint16 gk1SignatureDay6PoliceBeignet[] = {
 	0x35, 0x04,                         // ldi 04
 	0x1a,                               // eq?
 	0x30, SIG_ADDTOOFFSET +2,           // bnt [next state check]
-	0x38, SIG_UINT16 + 0x93, 0x00,      // pushi 93 (selector dispose)
+	0x38, SIG_SELECTOR16 + SELECTOR_dispose, // pushi dispose
 	0x76,                               // push0
 	0x72, SIG_ADDTOOFFSET +2,           // lofsa deskSarg
-	0x4a, 0x04, 0x00,                   // send 04
+	0x4a, SIG_UINT16 + 0x04, 0x00,      // send 04
+	SIG_MAGICDWORD,
 	0x34, SIG_UINT16 + 0xdc, 0x00,      // ldi 220
-	0x65, 0x1a,                         // aTop cycles
+	0x65, SIG_ADDTOOFFSET +1,           // aTop cycles (1a for PC, 1c for Mac)
 	0x32,                               // jmp [end]
 	SIG_END
 };
@@ -466,18 +531,21 @@ const uint16 gk1SignatureDay6PoliceBeignet[] = {
 const uint16 gk1PatchDay6PoliceBeignet[] = {
 	PATCH_ADDTOOFFSET +16,
 	0x34, PATCH_UINT16 + 0x17, 0x00,    // ldi 23
-	0x65, 0x1c,                         // aTop seconds
+	0x65, PATCH_GETORIGINALBYTEADJUST +20, +2, // aTop seconds (1c for PC, 1e for Mac)
 	PATCH_END
 };
 
 // sargSleeping::changeState (8) is called when the cop falls asleep and sets cycles to 220.
 //  this is not enough time to get to the door, so we patch it to 42 seconds
+// Applies to at least: English PC-CD, German PC-CD, English Mac
+// Responsible method: sargSleeping::changeState
 const uint16 gk1SignatureDay6PoliceSleep[] = {
 	0x35, 0x08,                         // ldi 08
 	0x1a,                               // eq?
 	0x31, SIG_ADDTOOFFSET +1,           // bnt [next state check]
+	SIG_MAGICDWORD,
 	0x34, SIG_UINT16 + 0xdc, 0x00,      // ldi 220
-	0x65, 0x1a,                         // aTop cycles
+	0x65, SIG_ADDTOOFFSET +1,           // aTop cycles (1a for PC, 1c for Mac)
 	0x32,                               // jmp [end]
 	0
 };
@@ -485,14 +553,18 @@ const uint16 gk1SignatureDay6PoliceSleep[] = {
 const uint16 gk1PatchDay6PoliceSleep[] = {
 	PATCH_ADDTOOFFSET +5,
 	0x34, SIG_UINT16 + 0x2a, 0x00,      // ldi 42
-	0x65, 0x1c,                         // aTop seconds
+	0x65, PATCH_GETORIGINALBYTEADJUST +9, +2, // aTop seconds (1c for PC, 1e for Mac)
 	PATCH_END
 };
 
 // startOfDay5::changeState (20h) - when gabriel goes to the phone the script will hang
+// Applies to at least: English PC-CD, German PC-CD, English Mac
+// Responsible method: startOfDay5::changeState
 const uint16 gk1SignatureDay5PhoneFreeze[] = {
+	0x4a,
+	SIG_MAGICDWORD, SIG_UINT16 + 0x0c, 0x00, // send 0c
 	0x35, 0x03,                         // ldi 03
-	0x65, 0x1a,                         // aTop cycles
+	0x65, SIG_ADDTOOFFSET +1,           // aTop cycles
 	0x32, SIG_ADDTOOFFSET +2,           // jmp [end]
 	0x3c,                               // dup
 	0x35, 0x21,                         // ldi 21
@@ -500,8 +572,9 @@ const uint16 gk1SignatureDay5PhoneFreeze[] = {
 };
 
 const uint16 gk1PatchDay5PhoneFreeze[] = {
-	0x35, 0x06,                         // ldi 06
-	0x65, 0x20,                         // aTop ticks
+	PATCH_ADDTOOFFSET +3,
+	0x35, 0x06,                         // ldi 01
+	0x65, PATCH_GETORIGINALBYTEADJUST +6, +6, // aTop ticks
 	PATCH_END
 };
 
@@ -513,7 +586,11 @@ const uint16 gk1PatchDay5PhoneFreeze[] = {
 // comparison between a number an an object. In the CD version, the checks are
 // in the correct order, thus the comparison is correct, thus we use the code
 // from the CD version in the floppy one.
+// Applies to at least: English Floppy
+// Responsible method: Interrogation::dispose
+// TODO: Check, if English Mac is affected too and if this patch applies
 const uint16 gk1SignatureInterrogationBug[] = {
+	SIG_MAGICDWORD,
 	0x65, 0x4c,                      // aTop 4c
 	0x67, 0x50,                      // pTos 50
 	0x34, SIG_UINT16 + 0x10, 0x27,   // ldi 2710
@@ -527,12 +604,12 @@ const uint16 gk1SignatureInterrogationBug[] = {
 	0x31, 0x15,                      // bnt 15  [05b9]
 	0x39, 0x0e,                      // pushi 0e
 	0x76,                            // push0
-	0x4a, 0x04, 0x00,                // send 0004
+	0x4a, SIG_UINT16 + 0x04, 0x00,   // send 0004
 	0xa5, 0x00,                      // sat 00
-	0x38, SIG_UINT16 + 0x93, 0x00,   // pushi 0093
+	0x38, SIG_SELECTOR16 + SELECTOR_dispose, // pushi dispose
 	0x76,                            // push0
 	0x63, 0x50,                      // pToa 50
-	0x4a, 0x04, 0x00,                // send 0004
+	0x4a, SIG_UINT16 + 0x04, 0x00,   // send 0004
 	0x85, 0x00,                      // lat 00
 	0x65, 0x50,                      // aTop 50
 	SIG_END
@@ -546,7 +623,7 @@ const uint16 gk1PatchInterrogationBug[] = {
 	0x76,                            // push0
 	0x4a, 0x04, 0x00,                // send 0004
 	0xa5, 0x00,                      // sat 00
-	0x38, PATCH_UINT16 + 0x93, 0x00, // pushi 0093
+	0x38, SIG_SELECTOR16 + SELECTOR_dispose, // pushi dispose
 	0x76,                            // push0
 	0x63, 0x50,                      // pToa 50
 	0x4a, 0x04, 0x00,                // send 0004
@@ -563,12 +640,12 @@ const uint16 gk1PatchInterrogationBug[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                 adjust
-const SciScriptSignature gk1Signatures[] = {
-	{     51, "interrogation bug",                           1, PATCH_MAGICDWORD(0x65, 0x4c, 0x67, 0x50),     0, gk1SignatureInterrogationBug, gk1PatchInterrogationBug },
-	{    212, "day 5 phone freeze",                          1, PATCH_MAGICDWORD(0x35, 0x03, 0x65, 0x1a),     0, gk1SignatureDay5PhoneFreeze, gk1PatchDay5PhoneFreeze },
-	{    230, "day 6 police beignet timer issue",            1, PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65),   -16, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet },
-	{    230, "day 6 police sleep timer issue",              1, PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65),    -5, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep },
+//    script, description,                                            signature                     patch
+SciScriptPatcherEntry gk1Signatures[] = {
+	{     51, "interrogation bug",                           1, 0, 0, gk1SignatureInterrogationBug, gk1PatchInterrogationBug },
+	{    212, "day 5 phone freeze",                          1, 0, 0, gk1SignatureDay5PhoneFreeze, gk1PatchDay5PhoneFreeze },
+	{    230, "day 6 police beignet timer issue",            1, 0, 0, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet },
+	{    230, "day 6 police sleep timer issue",              1, 0, 0, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -579,6 +656,7 @@ const SciScriptSignature gk1Signatures[] = {
 //  the volume to max. We fix the export, so volume won't get modified in
 //  those cases.
 const uint16 kq5SignatureCdHarpyVolume[] = {
+	SIG_MAGICDWORD,
 	0x80, SIG_UINT16 + 0x91, 0x01,   // lag global[191h]
 	0x18,                            // not
 	0x30, SIG_UINT16 + 0x2c, 0x00,   // bnt [jump further] (jumping, if global 191h is 1)
@@ -641,6 +719,7 @@ const uint16 kq5SignatureWitchCageInit[] = {
 	SIG_UINT16 + 0x00, 0x00,	// bottom
 	SIG_UINT16 + 0x00, 0x00,	// right
 	SIG_UINT16 + 0x00, 0x00,	// extra property #1
+	SIG_MAGICDWORD,
 	SIG_UINT16 + 0x7a, 0x00,	// extra property #2
 	SIG_UINT16 + 0xc8, 0x00,	// extra property #3
 	SIG_UINT16 + 0xa3, 0x00,	// extra property #4
@@ -670,6 +749,7 @@ const uint16 kq5PatchWitchCageInit[] = {
 // compatibilty between the DOS and Windows CD versions of KQ5.
 // TODO: Investigate these side effects more closely.
 const uint16 kq5SignatureWinGMSignals[] = {
+	SIG_MAGICDWORD,
 	0x80, SIG_UINT16 + 0x90, 0x01,   // lag 0x190
 	0x18,                            // not
 	0x30, SIG_UINT16 + 0x1b, 0x00,   // bnt +0x001B
@@ -682,17 +762,17 @@ const uint16 kq5PatchWinGMSignals[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                 adjust
-const SciScriptSignature kq5Signatures[] = {
-	{      0, "CD: harpy volume change",                     1, PATCH_MAGICDWORD(0x80, 0x91, 0x01, 0x18),     0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
-	{    200, "CD: witch cage init",                         1, PATCH_MAGICDWORD(0x7a, 0x00, 0xc8, 0x00),   -10, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
+//    script, description,                                            signature                  patch
+SciScriptPatcherEntry kq5Signatures[] = {
+	{      0, "CD: harpy volume change",                     1, 0, 0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
+	{    200, "CD: witch cage init",                         1, 0, 0, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
-const SciScriptSignature kq5WinGMSignatures[] = {
-	{      0, "CD: harpy volume change",                     1, PATCH_MAGICDWORD(0x80, 0x91, 0x01, 0x18),     0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
-	{    200, "CD: witch cage init",                         1, PATCH_MAGICDWORD(0x7a, 0x00, 0xc8, 0x00),   -10, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
-	{    124, "Win: GM Music signal checks",                 4, PATCH_MAGICDWORD(0x80, 0x90, 0x01, 0x18),     0, kq5SignatureWinGMSignals, kq5PatchWinGMSignals },
+SciScriptPatcherEntry kq5WinGMSignatures[] = {
+	{      0, "CD: harpy volume change",                     1, 0, 0, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
+	{    200, "CD: witch cage init",                         1, 0, 0, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
+	{    124, "Win: GM Music signal checks",                 4, 0, 0, kq5SignatureWinGMSignals, kq5PatchWinGMSignals },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -706,6 +786,7 @@ const SciScriptSignature kq5WinGMSignatures[] = {
 // constantly restarting (since it's being looped anyway), thus the normal
 // game speech can work while the baby cry sound is heard. Fixes bug #3034579.
 const uint16 kq6SignatureDuplicateBabyCry[] = {
+	SIG_MAGICDWORD,
 	0x83, 0x00,                      // lal 00
 	0x31, 0x1e,                      // bnt 1e  [07f4]
 	0x78,                            // push1
@@ -724,9 +805,9 @@ const uint16 kq6PatchDuplicateBabyCry[] = {
 //  grow the stack, because it's calling itself per switch.
 // Which means after a while ScummVM will bomb out because the stack frame
 //  will be too large. This patch fixes the buggy script.
-// This patch applies to at least CD, English floppy, German floppy
+// Applies to at least: PC-CD, English PC floppy, German PC floppy, English Mac
 // Responsible method: KqInv::showSelf
-// Fixes bug #3293954
+// Fixes bug: #3293954
 const uint16 kq6SignatureInventoryStackFix[] = {
 	0x67, 0x30,                         // pTos state
 	0x34, SIG_UINT16 + 0x00, 0x20,      // ldi 2000
@@ -734,12 +815,13 @@ const uint16 kq6SignatureInventoryStackFix[] = {
 	0x18,                               // not
 	0x31, 0x04,                         // bnt [not first refresh]
 	0x35, 0x00,                         // ldi 00
+	SIG_MAGICDWORD,
 	0x65, 0x1e,                         // aTop curIcon
 	0x67, 0x30,                         // pTos state
 	0x34, SIG_UINT16 + 0xff, 0xdf,      // ldi dfff
 	0x12,                               // and
 	0x65, 0x30,                         // aTop state
-	0x38, SIG_ADDTOOFFSET + 2,          // pushi "show" ("show" may be e100h for KQ6CD, xxxxh for KQ6 floppy)
+	0x38, SIG_SELECTOR16 + SELECTOR_show, // pushi "show" ("show" is e1h for KQ6CD)
 	0x78,                               // push1
 	0x87, 0x00,                         // lap param[0]
 	0x31, 0x04,                         // bnt [use global for show]
@@ -764,7 +846,6 @@ const uint16 kq6PatchInventoryStackFix[] = {
 	0x2f, 0x02,                         // bt [not first refresh] - saves 3 bytes in total
 	0x65, 0x1e,                         // aTop curIcon
 	0x00,                               // neg (either 2000 or 0000 in acc, this will create dfff or ffff) - saves 2 bytes
-//	0x34, PATCH_UINT16 + 0xff, 0xdf,    // ldi dfff
 	0x12,                               // and
 	0x65, 0x30,                         // aTop state
 	0x38,                               // pushi "show"
@@ -789,10 +870,10 @@ const uint16 kq6PatchInventoryStackFix[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                 adjust
-const SciScriptSignature kq6Signatures[] = {
-	{    481, "duplicate baby cry",                          1, PATCH_MAGICDWORD(0x83, 0x00, 0x31, 0x1e),     0, kq6SignatureDuplicateBabyCry, kq6PatchDuplicateBabyCry },
-	{    907, "inventory stack fix",                         1, PATCH_MAGICDWORD(0x65, 0x1e, 0x67, 0x30),   -11, kq6SignatureInventoryStackFix, kq6PatchInventoryStackFix },
+//    script, description,                                            signature                     patch
+SciScriptPatcherEntry kq6Signatures[] = {
+	{    481, "duplicate baby cry",                          1, 0, 0, kq6SignatureDuplicateBabyCry, kq6PatchDuplicateBabyCry },
+	{    907, "inventory stack fix",                         1, 0, 0, kq6SignatureInventoryStackFix, kq6PatchInventoryStackFix },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -805,7 +886,10 @@ const SciScriptSignature kq6Signatures[] = {
 // the function is undefined, thus kStrCat() that is called inside the function
 // reads a random pointer and crashes. We patch all of the 5 function calls
 // (one for each letter typed from "R", "O", "B", "I", "N") so that they are
-// the same as the English version. Fixes bug #3048054.
+// the same as the English version.
+// Applies to at least: German floppy
+// Responsible method: unknown
+// Fixes bug: #3048054
 const uint16 longbowSignatureShowHandCode[] = {
 	0x78,                            // push1
 	0x78,                            // push1
@@ -815,9 +899,10 @@ const uint16 longbowSignatureShowHandCode[] = {
 	0x02,                            // perform the call above with 2 parameters
 	0x36,                            // push
 	0x40, SIG_ADDTOOFFSET +2,        // call
+	SIG_MAGICDWORD,
 	0x02,                            // perform the call above with 2 parameters
-	0x38, SIG_UINT16 + 0x1c, 0x01,   // pushi 011c (setMotion)
-	0x39, 0x04,                      // pushi 04 (x)
+	0x38, SIG_SELECTOR16 + SELECTOR_setMotion, // pushi "setMotion" (0x11c in Longbow German)
+	0x39, SIG_SELECTOR8 + SELECTOR_x, // pushi "x" (0x04 in Longbow German)
 	0x51, 0x1e,                      // class MoveTo
 	SIG_END
 };
@@ -832,9 +917,9 @@ const uint16 longbowPatchShowHandCode[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature longbowSignatures[] = {
-	{    210, "hand code crash",                             5, PATCH_MAGICDWORD(0x02, 0x38, 0x1c, 0x01),   -14, longbowSignatureShowHandCode, longbowPatchShowHandCode },
+//    script, description,                                            signature                     patch
+SciScriptPatcherEntry longbowSignatures[] = {
+	{    210, "hand code crash",                             5, 0, 0, longbowSignatureShowHandCode, longbowPatchShowHandCode },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -852,11 +937,12 @@ const SciScriptSignature longbowSignatures[] = {
 //  "worked" in SSCI, but ScummVM/SCI doesn't allow that.
 // That's why those points weren't granted here at all.
 // We patch the script to use global 90, which seems to be unused in the whole game.
+// Applies to at least: English floppy
 // Responsible method: rm63Script::handleEvent
-// Fixes bug #3614419
+// Fixes bug: #3614419
 const uint16 larry2SignatureWearParachutePoints[] = {
 	0x35, 0x01,                      // ldi 01
-	0xa1, 0x8e,                      // sag 8e
+	0xa1, SIG_MAGICDWORD, 0x8e,      // sag 8e
 	0x80, SIG_UINT16 + 0xe0, 0x01,   // lag 1e0
 	0x18,                            // not
 	0x30, SIG_UINT16 + 0x0f, 0x00,   // bnt [don't give points]
@@ -873,9 +959,9 @@ const uint16 larry2PatchWearParachutePoints[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature larry2Signatures[] = {
-	{     63, "plane: no points for wearing plane",          1, PATCH_MAGICDWORD(0x8e, 0x80, 0xe0, 0x01),    -3, larry2SignatureWearParachutePoints, larry2PatchWearParachutePoints },
+//    script, description,                                            signature                           patch
+SciScriptPatcherEntry larry2Signatures[] = {
+	{     63, "plane: no points for wearing plane",          1, 0, 0, larry2SignatureWearParachutePoints, larry2PatchWearParachutePoints },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -887,7 +973,10 @@ const SciScriptSignature larry2Signatures[] = {
 //  doesn't happen anymore. We would otherwise get a crash
 //  calling for invalid views (this happens of course also
 //  in sierra sci)
+// Applies to at least: German PC-CD
+// Responsible method: unknown
 const uint16 larry6SignatureDeathDialog[] = {
+	SIG_MAGICDWORD,
 	0x3e, SIG_UINT16 + 0x33, 0x01,   // link 0133 (offset 0x20)
 	0x35, 0xff,                      // ldi ff
 	0xa3, 0x00,                      // sal 00
@@ -921,18 +1010,21 @@ const uint16 larry6PatchDeathDialog[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature larry6Signatures[] = {
-	{     82, "death dialog memory corruption",              1, PATCH_MAGICDWORD(0x3e, 0x33, 0x01, 0x35),     0, larry6SignatureDeathDialog, larry6PatchDeathDialog },
+//    script, description,                                      magic DWORD adjust signature                   patch
+SciScriptPatcherEntry larry6Signatures[] = {
+	{     82, "death dialog memory corruption",              1,          0,     0, larry6SignatureDeathDialog, larry6PatchDeathDialog },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
 // ===========================================================================
 // rm560::doit was supposed to close the painting, when Heimlich enters the
-//  room. The code is buggy, so it actually closes the painting, when heimlich
+//  room. The code is buggy. It actually closes the painting, when heimlich
 //  is not in the room. We fix that.
+// Applies to at least: English floppy
+// Responsible method: rm560::doit
 const uint16 laurabow2SignaturePaintingClosing[] = {
 	0x4a, 0x04,                         // send 04 - read aHeimlich::room
+	SIG_MAGICDWORD,
 	0x36,                               // push
 	0x81, 0x0b,                         // lag global[11d] -> current room
 	0x1c,                               // ne?
@@ -951,9 +1043,9 @@ const uint16 laurabow2PatchPaintingClosing[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature laurabow2Signatures[] = {
-	{    560, "painting closing immediately",                1, PATCH_MAGICDWORD(0x36, 0x81, 0x0b, 0x1c),    -2, laurabow2SignaturePaintingClosing, laurabow2PatchPaintingClosing },
+//    script, description,                                            signature                          patch
+SciScriptPatcherEntry laurabow2Signatures[] = {
+	{    560, "painting closing immediately",                1, 0, 0, laurabow2SignaturePaintingClosing, laurabow2PatchPaintingClosing },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -964,7 +1056,7 @@ const SciScriptSignature laurabow2Signatures[] = {
 //  We set the savedgame-id directly right after restoring in kRestoreGame.
 const uint16 mothergoose256SignatureReplay[] = {
 	0x36,                            // push
-	0x35, 0x20,                      // ldi 20
+	0x35, SIG_MAGICDWORD, 0x20,      // ldi 20
 	0x04,                            // sub
 	0xa1, 0xb3,                      // sag global[b3]
 	SIG_END
@@ -979,9 +1071,9 @@ const uint16 mothergoose256PatchReplay[] = {
 // when saving, it also checks if the savegame ID is below 13.
 //  we change this to check if below 113 instead
 const uint16 mothergoose256SignatureSaveLimit[] = {
-	0x89, 0xb3,       // lsg global[b3]
-	0x35, 0x0d,       // ldi 0d
-	0x20,             // ge?
+	0x89, SIG_MAGICDWORD, 0xb3,      // lsg global[b3]
+	0x35, 0x0d,                      // ldi 0d
+	0x20,                            // ge?
 	SIG_END
 };
 
@@ -991,11 +1083,11 @@ const uint16 mothergoose256PatchSaveLimit[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature mothergoose256Signatures[] = {
-	{      0, "replay save issue",                           1, PATCH_MAGICDWORD(0x20, 0x04, 0xa1, 0xb3),    -2, mothergoose256SignatureReplay,    mothergoose256PatchReplay },
-	{      0, "save limit dialog (SCI1.1)",                  1, PATCH_MAGICDWORD(0xb3, 0x35, 0x0d, 0x20),    -1, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit },
-	{    994, "save limit dialog (SCI1)",                    1, PATCH_MAGICDWORD(0xb3, 0x35, 0x0d, 0x20),    -1, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit },
+//    script, description,                                      magic DWORD adjust signature                         patch
+SciScriptPatcherEntry mothergoose256Signatures[] = {
+	{      0, "replay save issue",                           1, 0, 0, mothergoose256SignatureReplay,    mothergoose256PatchReplay },
+	{      0, "save limit dialog (SCI1.1)",                  1, 0, 0, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit },
+	{    994, "save limit dialog (SCI1)",                    1, 0, 0, mothergoose256SignatureSaveLimit, mothergoose256PatchSaveLimit },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -1009,14 +1101,16 @@ const SciScriptSignature mothergoose256Signatures[] = {
 //  SSCI.
 // This patch changes the code, so that the gun is actually given away
 //  when the 2 seconds have passed and the locker got closed.
+// Applies to at least: English floppy
 // Responsible method: putGun::changeState (script 341)
-// Fixes bug #3036933 / #3303802
+// Fixes bug: #3036933 / #3303802
 const uint16 pq1vgaSignaturePutGunInLockerBug[] = {
 	0x35, 0x00,                      // ldi 00
 	0x1a,                            // eq?
 	0x31, 0x25,                      // bnt [next state check]
 	SIG_ADDTOOFFSET +22,             // [skip 22 bytes]
-	0x38, SIG_UINT16 + 0x5f, 0x01,   // pushi 15fh
+	SIG_MAGICDWORD,
+	0x38, SIG_SELECTOR16 + SELECTOR_put, // pushi "put"
 	0x78,                            // push1
 	0x76,                            // push0
 	0x81, 0x00,                      // lag 00
@@ -1028,7 +1122,7 @@ const uint16 pq1vgaSignaturePutGunInLockerBug[] = {
 	0x35, 0x01,                      // ldi 01
 	0x1a,                            // eq?
 	0x31, 0x08,                      // bnt [end of method]
-	0x39, 0x6f,                      // pushi 6fh
+	0x39, SIG_SELECTOR8 + SELECTOR_dispose, // pushi "dispose"
 	0x76,                            // push0
 	0x72, SIG_UINT16 + 0x88, 0x00,   // lofsa 0088
 	0x4a, 0x04,                      // send 04 - locker::dispose
@@ -1046,7 +1140,7 @@ const uint16 pq1vgaPatchPutGunInLockerBug[] = {
 	0x35, 0x01,                      // ldi 01
 	0x1a,                            // eq?
 	0x31, 0x11,                      // bnt [end of method]
-	0x38, SIG_UINT16 + 0x5f, 0x01,   // pushi 15fh
+	0x38, PATCH_SELECTOR16 + SELECTOR_put, // pushi "put"
 	0x78,                            // push1
 	0x76,                            // push0
 	0x81, 0x00,                      // lag 00
@@ -1054,9 +1148,9 @@ const uint16 pq1vgaPatchPutGunInLockerBug[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature pq1vgaSignatures[] = {
-	{    341, "put gun in locker bug",                       1, PATCH_MAGICDWORD(0x38, 0x5f, 0x01, 0x78),   -27, pq1vgaSignaturePutGunInLockerBug, pq1vgaPatchPutGunInLockerBug },
+//    script, description,                                            signature                         patch
+SciScriptPatcherEntry pq1vgaSignatures[] = {
+	{    341, "put gun in locker bug",                       1, 0, 0, pq1vgaSignaturePutGunInLockerBug, pq1vgaPatchPutGunInLockerBug },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -1069,8 +1163,11 @@ const SciScriptSignature pq1vgaSignatures[] = {
 //   not nearly as bad as in our sci, but these differences may be caused by
 //   timing.
 //   We just reuse the active event, thus removing the duplicate kGetEvent call.
+// Applies to at least: English floppy
+// Responsible method: pointBox::doit
 const uint16 qfg1vgaSignatureFightEvents[] = {
-	0x39, 0x6d,                         // pushi 6d (selector new)
+	0x39, SIG_MAGICDWORD,
+	SIG_SELECTOR8 + SELECTOR_new,       // pushi "new"
 	0x76,                               // push0
 	0x51, 0x07,                         // class Event
 	0x4a, 0x04,                         // send 04 - call Event::new
@@ -1090,7 +1187,7 @@ const uint16 qfg1vgaSignatureFightEvents[] = {
 };
 
 const uint16 qfg1vgaPatchFightEvents[] = {
-	0x38, PATCH_UINT16 + 0x5a, 0x01, // pushi 15a (selector curEvent)
+	0x38, PATCH_SELECTOR16 + SELECTOR_curEvent, // pushi 15a (selector curEvent)
 	0x76,                            // push0
 	0x81, 0x50,                      // lag global[50]
 	0x4a, 0x04,                      // send 04 - read User::curEvent -> needs one byte more than previous code
@@ -1119,6 +1216,7 @@ const uint16 qfg1vgaPatchFightEvents[] = {
 
 // Patch 1: Increase temp space
 const uint16 qfg1vgaSignatureTempSpace[] = {
+	SIG_MAGICDWORD,
 	0x3f, 0xba,                         // link 0xba
 	0x87, 0x00,                         // lap 0
 	SIG_END
@@ -1131,6 +1229,7 @@ const uint16 qfg1vgaPatchTempSpace[] = {
 
 // Patch 2: Move the pointer used for the window header a little bit
 const uint16 qfg1vgaSignatureDialogHeader[] = {
+	SIG_MAGICDWORD,
 	0x5b, 0x04, 0x80,                   // lea temp[0x80]
 	0x36,                               // push
 	SIG_END
@@ -1151,6 +1250,7 @@ const uint16 qfg1vgaPatchDialogHeader[] = {
 // to 85, 165, which is not an edge case thus the freeze is avoided.
 // Fixes bug #3585189.
 const uint16 qfg1vgaSignatureMoveToCrusher[] = {
+	SIG_MAGICDWORD,
 	0x51, 0x1f,                         // class Motion
 	0x36,                               // push
 	0x39, 0x4f,                         // pushi 4f (79 - x)
@@ -1169,6 +1269,7 @@ const uint16 qfg1vgaPatchMoveToCrusher[] = {
 // spot when sneaking. In GuardsTrumpet::changeState, we change the final
 // location where Ego is moved from 111, 111 to 114, 114. Fixes bug #3604939.
 const uint16 qfg1vgaSignatureMoveToCastleGate[] = {
+	SIG_MAGICDWORD,
 	0x51, 0x1f,                         // class MoveTo
 	0x36,                               // push
 	0x39, 0x6f,                         // pushi 6f (111 - x)
@@ -1186,9 +1287,11 @@ const uint16 qfg1vgaPatchMoveToCastleGate[] = {
 // Typo in the original Sierra scripts
 // Looking at a cheetaur resulted in a text about a Saurus Rex
 // The code treats both monster types the same.
+// Applies to at least: English floppy
 // Responsible method: smallMonster::doVerb
 // Fixes bug #3604943.
 const uint16 qfg1vgaSignatureCheetaurDescription[] = {
+	SIG_MAGICDWORD,
 	0x34, SIG_UINT16 + 0xb8, 0x01,      // ldi 01b8
 	0x1a,                               // eq?
 	0x31, 0x16,                         // bnt 16
@@ -1216,6 +1319,7 @@ const uint16 qfg1vgaPatchCheetaurDescription[] = {
 // Local 5 of that room is a timer, that closes the door (object door11).
 // Setting it to 1 during happyFace::changeState(0) stops door11::doit from
 //  calling goTo6::init, so the whole issue is stopped from happening.
+// Applies to at least: English floppy
 // Responsible method: happyFace::changeState, door11::doit
 // Fixes bug #3585793
 const uint16 qfg1vgaSignatureFunnyRoomFix[] = {
@@ -1225,6 +1329,7 @@ const uint16 qfg1vgaSignatureFunnyRoomFix[] = {
 	0x35, 0x00,                         // ldi 00
 	0x1a,                               // eq?
 	0x30, SIG_UINT16 + 0x25, 0x00,      // bnt 0025 [-> next state]
+	SIG_MAGICDWORD,
 	0x35, 0x01,                         // ldi 01
 	0xa3, 0x4e,                         // sal 4e
 	SIG_END
@@ -1240,16 +1345,16 @@ const uint16 qfg1vgaPatchFunnyRoomFix[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature qfg1vgaSignatures[] = {
-	{    215, "fight event issue",                           1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07),    -1, qfg1vgaSignatureFightEvents,         qfg1vgaPatchFightEvents },
-	{    216, "weapon master event issue",                   1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07),    -1, qfg1vgaSignatureFightEvents,         qfg1vgaPatchFightEvents },
-	{    814, "window text temp space",                      1, PATCH_MAGICDWORD(0x3f, 0xba, 0x87, 0x00),     0, qfg1vgaSignatureTempSpace,           qfg1vgaPatchTempSpace },
-	{    814, "dialog header offset",                        3, PATCH_MAGICDWORD(0x5b, 0x04, 0x80, 0x36),     0, qfg1vgaSignatureDialogHeader,        qfg1vgaPatchDialogHeader },
-	{    331, "moving to crusher",                           1, PATCH_MAGICDWORD(0x51, 0x1f, 0x36, 0x39),     0, qfg1vgaSignatureMoveToCrusher,       qfg1vgaPatchMoveToCrusher },
-	{     41, "moving to castle gate",                       1, PATCH_MAGICDWORD(0x51, 0x1f, 0x36, 0x39),     0, qfg1vgaSignatureMoveToCastleGate,    qfg1vgaPatchMoveToCastleGate },
-	{    210, "cheetaur description fixed",                  1, PATCH_MAGICDWORD(0x34, 0xb8, 0x01, 0x1a),     0, qfg1vgaSignatureCheetaurDescription, qfg1vgaPatchCheetaurDescription },
-	{     96, "funny room script bug fixed",                 1, PATCH_MAGICDWORD(0x35, 0x01, 0xa3, 0x4e),   -10, qfg1vgaSignatureFunnyRoomFix,        qfg1vgaPatchFunnyRoomFix },
+//    script, description,                                      magic DWORD adjust signature                            patch
+SciScriptPatcherEntry qfg1vgaSignatures[] = {
+	{    215, "fight event issue",                           1, 0, 0, qfg1vgaSignatureFightEvents,         qfg1vgaPatchFightEvents },
+	{    216, "weapon master event issue",                   1, 0, 0, qfg1vgaSignatureFightEvents,         qfg1vgaPatchFightEvents },
+	{    814, "window text temp space",                      1, 0, 0, qfg1vgaSignatureTempSpace,           qfg1vgaPatchTempSpace },
+	{    814, "dialog header offset",                        3, 0, 0, qfg1vgaSignatureDialogHeader,        qfg1vgaPatchDialogHeader },
+	{    331, "moving to crusher",                           1, 0, 0, qfg1vgaSignatureMoveToCrusher,       qfg1vgaPatchMoveToCrusher },
+	{     41, "moving to castle gate",                       1, 0, 0, qfg1vgaSignatureMoveToCastleGate,    qfg1vgaPatchMoveToCastleGate },
+	{    210, "cheetaur description fixed",                  1, 0, 0, qfg1vgaSignatureCheetaurDescription, qfg1vgaPatchCheetaurDescription },
+	{     96, "funny room script bug fixed",                 1, 0, 0, qfg1vgaSignatureFunnyRoomFix,        qfg1vgaPatchFunnyRoomFix },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -1268,7 +1373,7 @@ const SciScriptSignature qfg1vgaSignatures[] = {
 // crashes because of these constant quick object reallocations. Fixes bug
 // #3037996.
 const uint16 qfg2SignatureImportDialog[] = {
-	0x63, 0x20,                         // pToa text
+	0x63, SIG_MAGICDWORD, 0x20,         // pToa text
 	0x30, SIG_UINT16 + 0x0b, 0x00,      // bnt [next state]
 	0x7a,                               // push2
 	0x39, 0x03,                         // pushi 03
@@ -1285,16 +1390,16 @@ const uint16 qfg2PatchImportDialog[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature qfg2Signatures[] = {
-	{    944, "import dialog continuous calls",                 1, PATCH_MAGICDWORD(0x20, 0x30, 0x0b, 0x00),  -1, qfg2SignatureImportDialog, qfg2PatchImportDialog },
+//    script, description,                                            signature                  patch
+SciScriptPatcherEntry qfg2Signatures[] = {
+	{    944, "import dialog continuous calls",              1, 0, 0, qfg2SignatureImportDialog, qfg2PatchImportDialog },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
 // ===========================================================================
 // Patch for the import screen in QFG3, same as the one for QFG2 above
 const uint16 qfg3SignatureImportDialog[] = {
-	0x63, 0x2a,                         // pToa text
+	0x63, SIG_MAGICDWORD, 0x2a,         // pToa text
 	0x31, 0x0b,                         // bnt [next state]
 	0x7a,                               // push2
 	0x39, 0x03,                         // pushi 03
@@ -1326,8 +1431,10 @@ const uint16 qfg3PatchImportDialog[] = {
 // hero::solvePuzzle (0xfffc) which does a ret afterwards without going to
 // Teller::doChild. We jump to this call of hero::solvePuzzle to get that same
 // behaviour.
-
+// Applies to at least: English, German, Italian, French, Spanish Floppy
+// Responsible method: unknown
 const uint16 qfg3SignatureWooDialog[] = {
+	SIG_MAGICDWORD,
 	0x67, 0x12,                         // pTos 12 (query)
 	0x35, 0xb6,                         // ldi b6
 	0x1a,                               // eq?
@@ -1336,7 +1443,7 @@ const uint16 qfg3SignatureWooDialog[] = {
 	0x35, 0x9b,                         // ldi 9b
 	0x1a,                               // eq?
 	0x31, 0x0c,                         // bnt 0c
-	0x38, SIG_UINT16 + 0x97, 0x02,      // pushi 0297
+	0x38, SIG_SELECTOR16 + SELECTOR_solvePuzzle, // pushi 0297
 	0x7a,                               // push2
 	0x38, SIG_UINT16 + 0x0c, 0x01,      // pushi 010c
 	0x7a,                               // push2
@@ -1353,10 +1460,10 @@ const uint16 qfg3PatchWooDialog[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature qfg3Signatures[] = {
-	{    944, "import dialog continuous calls",                 1, PATCH_MAGICDWORD(0x2a, 0x31, 0x0b, 0x7a),  -1, qfg3SignatureImportDialog,         qfg3PatchImportDialog },
-	{    440, "dialog crash when asking about Woo",             1, PATCH_MAGICDWORD(0x67, 0x12, 0x35, 0xb5),  -26, qfg3SignatureWooDialog,         qfg3PatchWooDialog },
+//    script, description,                                            signature                  patch
+SciScriptPatcherEntry qfg3Signatures[] = {
+	{    944, "import dialog continuous calls",              1, 0, 0, qfg3SignatureImportDialog, qfg3PatchImportDialog },
+	{    440, "dialog crash when asking about Woo",          1, 0, 0, qfg3SignatureWooDialog,    qfg3PatchWooDialog },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -1369,19 +1476,10 @@ const SciScriptSignature qfg3Signatures[] = {
 //   but I think just patching it out is cleaner (bug #3037938)
 const uint16 sq4FloppySignatureEndlessFlight[] = {
 	0x39, 0x04,                         // pushi 04 (selector x)
+	SIG_MAGICDWORD,
 	0x78,                               // push1
 	0x67, 0x08,                         // pTos 08 (property x)
-	0x63, 0x44,                         // pToa 44 (invalid property)
-	0x02,                               // add
-	SIG_END
-};
-
-// Similar to the above, for the German version (bug #3110215)
-const uint16 sq4FloppySignatureEndlessFlightGerman[] = {
-	0x39, 0x04,                         // pushi 04 (selector x)
-	0x78,                               // push1
-	0x67, 0x08,                         // pTos 08 (property x)
-	0x63, 0x4c,                         // pToa 4c (invalid property)
+	0x63, SIG_ADDTOOFFSET + 1,          // pToa (invalid property) - 44h for English floppy, 4ch for German floppy
 	0x02,                               // add
 	SIG_END
 };
@@ -1399,6 +1497,7 @@ const uint16 sq4FloppyPatchEndlessFlight[] = {
 // This is patched to add the "Both" text resource (i.e. we end up with
 // "Speech", "Text" and "Both")
 const uint16 sq4CdSignatureTextOptionsButton[] = {
+	SIG_MAGICDWORD,
 	0x35, 0x01,                         // ldi 0x01
 	0xa1, 0x53,                         // sag 0x53
 	0x39, 0x03,                         // pushi 0x03
@@ -1418,6 +1517,7 @@ const uint16 sq4CdPatchTextOptionsButton[] = {
 // (e.g. the two guys from Andromeda) shown when dying/quitting.
 // Fixes bug #3538418.
 const uint16 sq4CdSignatureBabbleIcon[] = {
+	SIG_MAGICDWORD,
 	0x89, 0x5a,                         // lsg 5a
 	0x35, 0x02,                         // ldi 02
 	0x1a,                               // eq?
@@ -1438,6 +1538,7 @@ const uint16 sq4CdPatchBabbleIcon[] = {
 // Refer to the patch above for additional details.
 // iconTextSwitch::doit (called when the text options button is clicked)
 const uint16 sq4CdSignatureTextOptions[] = {
+	SIG_MAGICDWORD,
 	0x89, 0x5a,                         // lsg 0x5a (load global 90 to stack)
 	0x3c,                               // dup
 	0x35, 0x01,                         // ldi 0x01
@@ -1453,7 +1554,7 @@ const uint16 sq4CdSignatureTextOptions[] = {
 	0x35, 0x01,                         // ldi 0x01
 	0xa1, 0x5a,                         // sag 0x5a (save acc to global 90)
 	0x3a,                               // toss
-	0x38, SIG_UINT16 + 0xd9, 0x00,      // pushi 0x00d9
+	0x38, SIG_SELECTOR16 + SELECTOR_show, // pushi 0x00d9
 	0x76,                               // push0
 	0x54, 0x04,                         // self 0x04
 	0x48,                               // ret
@@ -1479,13 +1580,12 @@ const uint16 sq4CdPatchTextOptions[] = {
 	PATCH_END
 };
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature sq4Signatures[] = {
-	{    298, "Floppy: endless flight",                      1, PATCH_MAGICDWORD(0x67, 0x08, 0x63, 0x44),    -3,       sq4FloppySignatureEndlessFlight, sq4FloppyPatchEndlessFlight },
-	{    298, "Floppy (German): endless flight",             1, PATCH_MAGICDWORD(0x67, 0x08, 0x63, 0x4c),    -3, sq4FloppySignatureEndlessFlightGerman, sq4FloppyPatchEndlessFlight },
-	{    818, "CD: Speech and subtitles option",             1, PATCH_MAGICDWORD(0x89, 0x5a, 0x3c, 0x35),     0,             sq4CdSignatureTextOptions,       sq4CdPatchTextOptions },
-	{      0, "CD: Babble icon speech and subtitles fix",    1, PATCH_MAGICDWORD(0x89, 0x5a, 0x35, 0x02),     0,              sq4CdSignatureBabbleIcon,        sq4CdPatchBabbleIcon },
-	{    818, "CD: Speech and subtitles option button",      1, PATCH_MAGICDWORD(0x35, 0x01, 0xa1, 0x53),     0,       sq4CdSignatureTextOptionsButton, sq4CdPatchTextOptionsButton },
+//    script, description,                                      magic DWORD adjust signature                        patch
+SciScriptPatcherEntry sq4Signatures[] = {
+	{    298, "Floppy: endless flight",                      1, 0, 0, sq4FloppySignatureEndlessFlight,       sq4FloppyPatchEndlessFlight },
+	{    818, "CD: Speech and subtitles option",             1, 0, 0, sq4CdSignatureTextOptions,             sq4CdPatchTextOptions },
+	{      0, "CD: Babble icon speech and subtitles fix",    1, 0, 0, sq4CdSignatureBabbleIcon,              sq4CdPatchBabbleIcon },
+	{    818, "CD: Speech and subtitles option button",      1, 0, 0, sq4CdSignatureTextOptionsButton,       sq4CdPatchTextOptionsButton },
 	SCI_SIGNATUREENTRY_TERMINATOR
 };
 
@@ -1501,7 +1601,8 @@ const SciScriptSignature sq4Signatures[] = {
 // We simply set the correct starting cel number to fix the bug.
 // Responsible method: robotIntoShip::changeState(9)
 const uint16 sq1vgaSignatureUlenceFlatsTimepodGfxGlitch[] = {
-	0x39, 0x07,                         // pushi 07 (ship::cel)
+	0x39, 
+	SIG_MAGICDWORD, SIG_SELECTOR8 + SELECTOR_cel, // pushi "cel"
 	0x78,                               // push1
 	0x39, 0x0a,                         // pushi 0x0a (set ship::cel to 10)
 	0x38, SIG_UINT16 + 0xa0, 0x00,      // pushi 0x00a0 (ship::setLoop)
@@ -1515,9 +1616,10 @@ const uint16 sq1vgaPatchUlenceFlatsTimepodGfxGlitch[] = {
 };
 
 const uint16 sq1vgaSignatureEgoShowsCard[] = {
-	0x38, SIG_UINT16 + 0x46, 0x02,      // push 0x246 (set up send frame to set timesShownID)
+	SIG_MAGICDWORD,
+	0x38, SIG_SELECTOR16 + SELECTOR_timesShownID, // push "timesShownID"
 	0x78,                               // push1
-	0x38, SIG_UINT16 + 0x46, 0x02,      // push 0x246 (set up send frame to get timesShownID)
+	0x38, SIG_SELECTOR16 + SELECTOR_timesShownID, // push "timesShownID"
 	0x76,                               // push0
 	0x51, 0x7c,                         // class DeltaurRegion
 	0x4a, 0x04,                         // send 0x04 (get timesShownID)
@@ -1536,7 +1638,7 @@ const uint16 sq1vgaSignatureEgoShowsCard[] = {
 // Note that this script patch is merely a reordering of the
 // instructions in the original script.
 const uint16 sq1vgaPatchEgoShowsCard[] = {
-	0x38, PATCH_UINT16 + 0x46, 0x02,    // push 0x246 (set up send frame to get timesShownID)
+	0x38, PATCH_SELECTOR16 + SELECTOR_timesShownID, // push "timesShownID"
 	0x76,                               // push0
 	0x51, 0x7c,                         // class DeltaurRegion
 	0x4a, 0x04,                         // send 0x04 (get timesShownID)
@@ -1544,7 +1646,7 @@ const uint16 sq1vgaPatchEgoShowsCard[] = {
 	0x35, 0x01,                         // ldi 1
 	0x02,                               // add
 	0x36,                               // push (this push corresponds to the wrong one above)
-	0x38, PATCH_UINT16 + 0x46, 0x02,    // push 0x246 (set up send frame to set timesShownID)
+	0x38, PATCH_SELECTOR16 + SELECTOR_timesShownID, // push "timesShownID"
 	0x78,                               // push1
 	0x36,                               // push
 	0x51, 0x7c,                         // class DeltaurRegion
@@ -1555,18 +1657,19 @@ const uint16 sq1vgaPatchEgoShowsCard[] = {
 };
 
 
-//    script, description,                                      magic DWORD,                                  adjust
-const SciScriptSignature sq1vgaSignatures[] = {
-	{     45, "Ulence Flats: timepod graphic glitch",        1, PATCH_MAGICDWORD( 0x07, 0x78, 0x39, 0x0a ),  -1,       sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch },
-	{     58, "Sarien armory droid zapping ego first time",  1, PATCH_MAGICDWORD( 0x72, 0x88, 0x15, 0x36 ), -70,       sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard },
-
+//    script, description,                                            signature                                   patch
+SciScriptPatcherEntry sq1vgaSignatures[] = {
+	{     45, "Ulence Flats: timepod graphic glitch",        1, 0, 0, sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch },
+	{     58, "Sarien armory droid zapping ego first time",  1, 0, 0, sq1vgaSignatureEgoShowsCard,                sq1vgaPatchEgoShowsCard },
 	SCI_SIGNATUREENTRY_TERMINATOR};
 
 // will actually patch previously found signature area
-void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, const bool isMacSci11) {
+void Script::patcherApplyPatch(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;
-	uint16 patchWord = *patch;
+	uint16 patchWord = *patchEntry->patchData;
+	uint16 patchSelector = 0;
 
 	// Copy over original bytes from script
 	uint32 orgDataSize = scriptSize - offset;
@@ -1575,8 +1678,9 @@ void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scri
 	memcpy(&orgData, &scriptData[offset], orgDataSize);
 
 	while (patchWord != PATCH_END) {
+		uint16 patchCommand = patchWord & PATCH_COMMANDMASK;
 		uint16 patchValue = patchWord & PATCH_VALUEMASK;
-		switch (patchWord & PATCH_COMMANDMASK) {
+		switch (patchCommand) {
 		case PATCH_ADDTOOFFSET: {
 			// add value to offset
 			offset += patchValue;
@@ -1585,7 +1689,7 @@ void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scri
 		case PATCH_GETORIGINALBYTE: {
 			// get original byte from script
 			if (patchValue >= orgDataSize)
-				error("patching: can not get requested original byte from script");
+				error("Script-Patcher: can not get requested original byte from script");
 			scriptData[offset] = orgData[patchValue];
 			offset++;
 			break;
@@ -1593,38 +1697,37 @@ void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scri
 		case PATCH_GETORIGINALBYTEADJUST: {
 			// get original byte from script and adjust it
 			if (patchValue >= orgDataSize)
-				error("patching: can not get requested original byte from script");
+				error("Script-Patcher: can not get requested original byte from script");
 			byte orgByte = orgData[patchValue];
 			int16 adjustValue;
-			patch++; adjustValue = (int16)(*patch);
+			patchData++; adjustValue = (int16)(*patchData);
 			scriptData[offset] = orgByte + adjustValue;
 			offset++;
 			break;
 		}
-		case PATCH_ADJUSTWORD: {
-			// Adjust word right before current position
-			byte *adjustPtr = &scriptData[offset - 2];
-			uint16 adjustWord = READ_LE_UINT16(adjustPtr);
-			adjustWord += patchValue;
-			WRITE_LE_UINT16(adjustPtr, adjustWord);
-			break;
-		}
-		case PATCH_ADJUSTWORD_NEG: {
-			// Adjust word right before current position (negative way)
-			byte *adjustPtr = &scriptData[offset - 2];
-			uint16 adjustWord = READ_LE_UINT16(adjustPtr);
-			adjustWord -= patchValue;
-			WRITE_LE_UINT16(adjustPtr, adjustWord);
-			break;
-		}
-		case PATCH_UINT16: {
-			byte byte1 = patchValue & PATCH_BYTEMASK;
+		case PATCH_UINT16:
+		case PATCH_SELECTOR16: {
+			byte byte1;
 			byte byte2;
-			patch++; patchWord = *patch;
-			if (patchWord & PATCH_COMMANDMASK) {
-				error("Patch inconsistent");
+						
+			switch (patchCommand) {
+			case PATCH_UINT16: {
+				byte1 = patchValue & PATCH_BYTEMASK;
+				patchData++; patchWord = *patchData;
+				if (patchWord & PATCH_COMMANDMASK)
+					error("Script-Patcher: Patch inconsistent");
+				byte2 = patchWord & PATCH_BYTEMASK;
+				break;
+			}
+			case PATCH_SELECTOR16: {
+				patchSelector = selectorTable[patchValue].id;
+				byte1 = patchSelector & 0xFF;
+				byte2 = patchSelector >> 8;
+				break;
+			}
+			default:
+				byte1 = 0; byte2 = 0;
 			}
-			byte2 = patchWord & PATCH_BYTEMASK;
 			if (!isMacSci11) {
 				scriptData[offset++] = byte1;
 				scriptData[offset++] = byte2;
@@ -1635,49 +1738,74 @@ void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scri
 			}
 			break;
 		}
-		default:
+		case PATCH_SELECTOR8: {
+			patchSelector = selectorTable[patchValue].id;
+			if (patchSelector & 0xFF00)
+				error("Script-Patcher: 8 bit selector required, game uses 16 bit selector");
+			scriptData[offset] = patchSelector & 0xFF;
+			offset++;
+			break;
+		}
+		case PATCH_BYTE:
 			scriptData[offset] = patchValue & PATCH_BYTEMASK;
 			offset++;
 		}
-		patch++;
-		patchWord = *patch;
+		patchData++;
+		patchWord = *patchData;
 	}
 }
 
 // will return -1 if no match was found, otherwise an offset to the start of the signature match
-int32 Script::findSignature(const SciScriptSignature *signature, const byte *scriptData, const uint32 scriptSize, const bool isMacSci11) {
+int32 Script::patcherFindSignature(const SciScriptPatcherEntry *patchEntry, 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 = signature->magicDWord; // is platform-specific BE/LE form, so that the later match will work
+	const uint32 magicDWord = patchEntry->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 + signature->magicOffset;
+			uint32 offset = DWordOffset + patchEntry->magicOffset;
 			uint32 byteOffset = offset;
-			const uint16 *signatureData = signature->data;
-			
+			const uint16 *signatureData = patchEntry->signatureData;
+			uint16 sigSelector = 0;
+
 			uint16 sigWord = *signatureData;
 			while (sigWord != SIG_END) {
-				uint16 sigValue = sigWord & PATCH_VALUEMASK;
-				switch (sigWord & SIG_COMMANDMASK) {
+				uint16 sigCommand = sigWord & SIG_COMMANDMASK;
+				uint16 sigValue = sigWord & SIG_VALUEMASK;
+				switch (sigCommand) {
 				case SIG_ADDTOOFFSET: {
 					// add value to offset
 					byteOffset += sigValue;
 					break;
 				}
-				case PATCH_UINT16: {
+				case SIG_UINT16:
+				case SIG_SELECTOR16: {
 					if ((byteOffset + 1) < scriptSize) {
-						byte byte1 = sigValue & SIG_BYTEMASK;
+						byte byte1;
 						byte byte2;
-						signatureData++; sigWord = *signatureData;
-						if (sigWord & SIG_COMMANDMASK) {
-							error("Patch inconsistent");
+
+						switch (sigCommand) {
+						case SIG_UINT16: {
+							byte1 = sigValue & SIG_BYTEMASK;
+							signatureData++; sigWord = *signatureData;
+							if (sigWord & SIG_COMMANDMASK)
+								error("Script-Patcher: signature inconsistent\nFaulty patch: '%s'", patchEntry->description);
+							byte2 = sigWord & SIG_BYTEMASK;
+							break;
+						}
+						case SIG_SELECTOR16: {
+							sigSelector = selectorTable[sigValue].id;
+							byte1 = sigSelector & 0xFF;
+							byte2 = sigSelector >> 8;
+							break;
+						}
+						default:
+							byte1 = 0; byte2 = 0;
 						}
-						byte2 = sigWord & SIG_BYTEMASK;
 						if (!isMacSci11) {
 							if ((scriptData[byteOffset] != byte1) || (scriptData[byteOffset + 1] != byte2))
 								sigWord = SIG_MISMATCH;
@@ -1692,15 +1820,27 @@ int32 Script::findSignature(const SciScriptSignature *signature, const byte *scr
 					}
 					break;
 				}
-				default:
+				case SIG_SELECTOR8: {
+					if (byteOffset < scriptSize) {
+						sigSelector = selectorTable[sigValue].id;
+						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))
+							sigWord = SIG_MISMATCH;
+						byteOffset++;
+					} else {
+						sigWord = SIG_MISMATCH; // out of bounds
+					}
+					break;
+				}
+				case SIG_BYTE:
 					if (byteOffset < scriptSize) {
 						if (scriptData[byteOffset] != sigWord)
 							sigWord = SIG_MISMATCH;
+						byteOffset++;
 					} else {
-						// out of bounds
-						sigWord = SIG_MISMATCH;
+						sigWord = SIG_MISMATCH; // out of bounds
 					}
-					byteOffset++;
 				}
 				
 				if (sigWord == SIG_MISMATCH)
@@ -1719,8 +1859,139 @@ int32 Script::findSignature(const SciScriptSignature *signature, const byte *scr
 	return -1;
 }
 
-void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {
-	const SciScriptSignature *signatureTable = NULL;
+// 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) {
+	SciScriptPatcherEntry *curEntry = patchTable;
+	SciScriptPatcherSelector *curSelector = NULL;
+	int step;
+	int magicOffset;
+	byte magicDWord[4];
+	int magicDWordLeft = 0;
+    const uint16 *curData;
+    uint16 curWord;
+    uint16 curCommand;
+    uint32 curValue;
+    byte byte1;
+    byte byte2;
+
+    while (curEntry->signatureData) {
+		// process signature
+		memset(magicDWord, 0, sizeof(magicDWord));
+
+		for (step = 0; step < 2; step++) {
+			switch (step) {
+			case 0: curData = curEntry->signatureData; break;
+			case 1: curData = curEntry->patchData; break;
+			}
+		
+			curWord = *curData;
+			magicOffset = 0;
+			while (curWord != SIG_END) {
+				curCommand = curWord & SIG_COMMANDMASK;
+				curValue   = curWord & SIG_VALUEMASK;
+				switch (curCommand) {
+				case SIG_MAGICDWORD: {
+					if (step == 0) {
+						if ((curEntry->magicDWord) || (magicDWordLeft))
+							error("Script-Patcher: Magic-DWORD specified multiple times in signature\nFaulty patch: '%s'", curEntry->description);
+						magicDWordLeft = 4;
+						curEntry->magicOffset = magicOffset;
+					}
+					break;
+				}
+				case SIG_ADDTOOFFSET: {
+					magicOffset -= curValue;
+					if (magicDWordLeft)
+						error("Script-Patcher: Magic-DWORD contains AddToOffset command\nFaulty patch: '%s'", curEntry->description);
+					break;
+				}
+				case SIG_UINT16:
+				case SIG_SELECTOR16: {
+					// UINT16 or 1
+					switch (curCommand) {
+					case SIG_UINT16: {
+						curData++; curWord = *curData;
+						if (curWord & SIG_COMMANDMASK)
+							error("Script-Patcher: signature entry inconsistent\nFaulty patch: '%s'", curEntry->description);
+						if (!isMacSci11) {
+							byte1 = curValue;
+							byte2 = curWord & SIG_BYTEMASK;
+						} else {
+							byte1 = curWord & SIG_BYTEMASK;
+							byte2 = curValue;
+						}
+						break;
+					}
+					case SIG_SELECTOR16: {
+						curSelector = &selectorTable[curValue];
+						if (curSelector->id == -1)
+							curSelector->id = g_sci->getKernel()->findSelector(curSelector->name);
+						if (!isMacSci11) {
+							byte1 = curSelector->id & 0x00FF;
+							byte2 = curSelector->id >> 8;
+						} else {
+							byte1 = curSelector->id >> 8;
+							byte2 = curSelector->id & 0x00FF;
+						}
+						break;
+					}
+					}
+					magicOffset -= 2;
+					if (magicDWordLeft) {
+						// Remember current word for Magic DWORD
+						magicDWord[4 - magicDWordLeft] = byte1;
+						magicDWordLeft--;
+						if (magicDWordLeft) {
+							magicDWord[4 - magicDWordLeft] = byte2;
+							magicDWordLeft--;
+						}
+						if (!magicDWordLeft) {
+							curEntry->magicDWord = READ_LE_UINT32(magicDWord);
+						}
+					}
+					break;
+				}
+				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)
+									error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", curEntry->description);
+							}
+						}
+						curValue = curSelector->id;
+					}
+					magicOffset--;
+					if (magicDWordLeft) {
+						// Remember current byte for Magic DWORD
+						magicDWord[4 - magicDWordLeft] = (byte)curValue;
+						magicDWordLeft--;
+						if (!magicDWordLeft) {
+							curEntry->magicDWord = READ_LE_UINT32(magicDWord);
+						}
+					}
+				}
+				}
+				curData++;
+				curWord = *curData;
+			}
+		}
+		if (magicDWordLeft)
+			error("Script-Patcher: Magic-DWORD beyond End-Of-Signature\nFaulty patch: '%s'", curEntry->description);
+		if (!curEntry->magicDWord)
+			error("Script-Patcher: Magic-DWORD not specified in signature\nFaulty patch: '%s'", curEntry->description);
+    
+		curEntry++;
+    }
+}
+
+void Script::patcherProcessScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {
+	SciScriptPatcherEntry *signatureTable = NULL;
+
 	switch (g_sci->getGameId()) {
 	case GID_CAMELOT:
 		signatureTable = camelotSignatures;
@@ -1789,17 +2060,22 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
 
 	if (signatureTable) {
 		bool isMacSci11 = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1);
+
+		if (!signatureTable->magicDWord) {
+			// signature table needs to get initialized (Magic DWORD set, selector table set)
+			patcherInitSignature(signatureTable, isMacSci11);
+		}
 	
-		while (signatureTable->data) {
+		while (signatureTable->signatureData) {
 			if (scriptNr == signatureTable->scriptNr) {
 				int32 foundOffset = 0;
 				int16 applyCount = signatureTable->applyCount;
 				do {
-					foundOffset = findSignature(signatureTable, scriptData, scriptSize, isMacSci11);
+					foundOffset = patcherFindSignature(signatureTable, scriptData, scriptSize, isMacSci11);
 					if (foundOffset != -1) {
 						// found, so apply the patch
-						debugC(kDebugLevelScriptPatcher, "matched and patched %s on script %d offset %d", signatureTable->description, scriptNr, foundOffset);
-						applyPatch(signatureTable->patch, scriptData, scriptSize, foundOffset, isMacSci11);
+						debugC(kDebugLevelScriptPatcher, "Script-Patcher: '%s' on script %d offset %d", signatureTable->description, scriptNr, foundOffset);
+						patcherApplyPatch(signatureTable, scriptData, scriptSize, foundOffset, isMacSci11);
 					}
 					applyCount--;
 				} while ((foundOffset != -1) && (applyCount));


Commit: de0151a26dbc5abf5c4aa80ae3cf4f073bd138b0
    https://github.com/scummvm/scummvm/commit/de0151a26dbc5abf5c4aa80ae3cf4f073bd138b0
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2013-11-03T14:50:33-08:00

Commit Message:
Merge branch 'master' of github.com:scummvm/scummvm

Changed paths:
    engines/fullpipe/behavior.cpp
    engines/fullpipe/behavior.h
    engines/fullpipe/constants.h
    engines/fullpipe/fullpipe.h
    engines/fullpipe/input.cpp
    engines/fullpipe/lift.cpp
    engines/fullpipe/scenes.cpp
    engines/fullpipe/scenes.h
    engines/tsage/ringworld2/ringworld2_scenes1.cpp
    engines/tsage/ringworld2/ringworld2_scenes1.h









More information about the Scummvm-git-logs mailing list