[Scummvm-git-logs] scummvm branch-2-9 -> 92cb377b4d44ed041928ade78509608f70f97dde

sluicebox noreply at scummvm.org
Tue Apr 29 17:41:20 UTC 2025


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

Summary:
e106e0ebc0 SCI: Update `validate_property` comments and static usage
24c2a1a23a SCI32: Fix GK1 day 5 phone lockup in all game versions
f1ed765f26 SCI32: Remove QFG4 Thieves' Guild script patch
f22925bf89 SCI: Add detection for BRAIN1 French fan translation
92cb377b4d SCI: Fix picture vector patterns at right edge of screen


Commit: e106e0ebc05a78538ffef8bb82ad38f6495a3a81
    https://github.com/scummvm/scummvm/commit/e106e0ebc05a78538ffef8bb82ad38f6495a3a81
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2025-04-29T10:40:42-07:00

Commit Message:
SCI: Update `validate_property` comments and static usage

This change should not alter any game behavior, because no game scripts
are known to contain an instruction that alters an invalid property.

If such a script does exist, it is now handled correctly.

Changed paths:
    engines/sci/engine/vm.cpp


diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index d9e0c9189fb..f99d6d0731f 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -52,8 +52,8 @@ const reg_t TRUE_REG = {0, 1};
 static reg_t &validate_property(EngineState *s, Object *obj, int index) {
 	// A static dummy reg_t, which we return if obj or index turn out to be
 	// invalid. Note that we cannot just return NULL_REG, because client code
-	// may modify the value of the returned reg_t.
-	static reg_t dummyReg = NULL_REG;
+	// may modify the reference. Instead, we reset it to NULL_REG each time.
+	static reg_t dummyReg;
 
 	// If this occurs, it means there's probably something wrong with the garbage
 	// collector, so don't hide it with fake return values
@@ -65,11 +65,15 @@ static reg_t &validate_property(EngineState *s, Object *obj, int index) {
 	else
 		index >>= 1;
 
+	// Validate the property index. SSCI does no validation; it just adds the offset
+	// to the object's address. If a script contains an invalid offset, usually due
+	// to the script compiler accepting an invalid property symbol, then OOB memory
+	// is used. Several games have an Actor:canBeHere method in script 998 with this
+	// bug, so it occurs immediately in their speed tests. (iceman, lsl3, qfg1, kq1)
 	if (index < 0 || (uint)index >= obj->getVarCount()) {
-		// This is same way sierra does it and there are some games, that contain such scripts like
-		//  iceman script 998 (fred::canBeHere, executed right at the start)
 		debugC(kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested from object %04x:%04x (%s)",
 			index, obj->getVarCount(), PRINT_REG(obj->getPos()), s->_segMan->getObjectName(obj->getPos()));
+		dummyReg = NULL_REG;
 		return dummyReg;
 	}
 


Commit: 24c2a1a23a6caaccd329b63718ed8de64b02fda9
    https://github.com/scummvm/scummvm/commit/24c2a1a23a6caaccd329b63718ed8de64b02fda9
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2025-04-29T10:40:43-07:00

Commit Message:
SCI32: Fix GK1 day 5 phone lockup in all game versions

Fixes bug #15857

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


diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index db8dd082531..3646ea7521a 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -3165,25 +3165,82 @@ static const uint16 gk1Day5DrumBookDialoguePatch[] = {
 	PATCH_END
 };
 
-// When Gabriel goes to the phone, the script softlocks at
-// `startOfDay5::changeState(32)`.
+// When day 5 starts, the game can lockup after the phone rings. All versions
+//  are affected, but the bug depends on combinations of machine speed, game
+//  version, and the game speed setting. This is a bug in the original game.
+//
+// After the phone rings, Gabriel is supposed to say "I got it!" while walking
+//  to the phone. The script sets ego's motion, waits 3 game cycles, and then
+//  says the message. bookStoreNarrator animates ego when one of his messages is
+//  said, but only when ego is standing still, otherwise movement would stop.
+//  bookStoreNarrator checks for this by testing if ego's loop is standing (8).
+//  When the phone script sets ego's motion, there is a delay before ego's loop
+//  changes from standing to walking. The delay depends on the game speed
+//  setting and game version; the CD version added a GKEgo:setHeading method
+//  that skips redundant turns. All of this is independent of the 3 cycle delay
+//  that it is based on machine speed. If "I got it!" starts before ego's loop
+//  changes, then bookStoreNarrator animates ego talking, the walk movement is
+//  interrupted, and the game is stuck waiting for ego to walk to the phone.
+//
+// We fix this by signaling bookStoreNarrator that it should not animate ego
+//  when displaying the "I got it!" message. We do this by setting an unused
+//  global in startOfDay5:changeState(32) and getTheVeve:changeState(24).
+//  In bookStoreNarrator:display, we test the global and reset it. We make room
+//  for this by overwriting a duplicated ego:view test.
+//
+// This patch is designed to be compatible with NRS patches. The NRS technique
+//  changes delays in cycles to ticks, which fixes the CD version but not the
+//  floppy versions when the game speed is lowered. The timing is different due
+//  to the CD version's GKEgo:setHeading method. Our patch does not depend on
+//  timing, so it is compatible with both types of delays.
 //
-// Applies to at least: English PC-CD, German PC-CD, English Mac
-static const uint16 gk1Day5PhoneFreezeSignature[] = {
-	0x4a,                             // send ...
-	SIG_MAGICDWORD, SIG_UINT16(0x0c), // ... $c
-	0x35, 0x03,                       // ldi 3
-	0x65, SIG_ADDTOOFFSET(+1),        // aTop cycles
-	0x32, SIG_ADDTOOFFSET(+2),        // jmp [end]
-	0x3c,                             // dup
-	0x35, 0x21,                       // ldi $21
+// Applies to: All versions
+// Responsible methods: bookStoreNarrator:display, startOfDay5:changeState(32),
+//                      getTheVeve:changeState(24)
+// Fixes bug: #15857
+static const uint16 gk1Day5PhoneLockupSignature1[] = {
+	SIG_MAGICDWORD,
+	0x35, 0x08,                         // ldi 08
+	0x1a,                               // eq? [ GKEgo:loop == 8 ]
+	0x30, SIG_ADDTOOFFSET(+2),          // bnt [ skip talk animation ]
+	0x39, SIG_SELECTOR8(view),          // pushi view
+	0x76,                               // push0
+	0x81, 0x00,                         // lag 00
+	0x4a, SIG_UINT16(0x0004),           // send 04 [ GKEgo view: ]
+	0x36,                               // push
+	0x34, SIG_UINT16(0x0385),           // ldi 0385
+	0x1a,                               // eq? [ GKEgo:view == 901 (duplicated test from earlier) ]
+	0x2f,                               // bt [ talk animation ]
 	SIG_END
 };
 
-static const uint16 gk1Day5PhoneFreezePatch[] = {
-	PATCH_ADDTOOFFSET(+3),                     // send $c
-	0x35, 0x06,                                // ldi 6
-	0x65, PATCH_GETORIGINALBYTEADJUST(+6, +6), // aTop ticks
+static const uint16 gk1Day5PhoneLockupPatch1[] = {
+	PATCH_ADDTOOFFSET(+6),
+	0x81, 0xd1,                         // lag d1 [ read global. acc = 0 to animate, 1 to skip ]
+	0x38, PATCH_UINT16(0x0000),         // pushi 0000
+	0xa9, 0xd1,                         // ssg d1 [ reset global to 0 ]
+	0x2e, PATCH_GETORIGINALUINT16ADJUST(4, -10), // bt [ skip talk animation if global is set ]
+	0x34, PATCH_UINT16(0x0001),         // ldi 0001 [ acc = 1 to branch to talk animation ]
+	PATCH_END
+};
+
+// startOfDay5:changeState(32), getTheVeve:changeState(24)
+static const uint16 gk1Day5PhoneLockupSignature2[] = {
+	SIG_MAGICDWORD,
+	0x38, SIG_UINT16(0x0115),           // pushi 0115
+	0x39, 0x6a,                         // pushi 6a
+	0x7c,                               // pushSelf
+	0x81, 0x00,                         // lag 00
+	0x4a, SIG_UINT16(0x000c),           // send 0c [ GKEgo setMotion: PolyPath 277 106 self ]
+	SIG_ADDTOOFFSET(+4),                // [ cycles = 3, NRS patch: ticks = 6 ]
+	0x32,                               // jmp [ end of switch ]
+	SIG_END
+};
+
+static const uint16 gk1Day5PhoneLockupPatch2[] = {
+	PATCH_ADDTOOFFSET(+15),
+	0x78,                               // push1
+	0xa9, 0xd1,                         // ssg d1 [ global209 = 1 (skip talk animation) ]
 	PATCH_END
 };
 
@@ -4489,10 +4546,11 @@ static const SciScriptPatcherEntry gk1Signatures[] = {
 	{  false,   24, "mac: fix missing talisman view",              1, gk1MacTalismanInsetSignature,     gk1MacTalismanInsetPatch },
 	{  true,    51, "fix interrogation bug",                       1, gk1InterrogationBugSignature,     gk1InterrogationBugPatch },
 	{  true,    93, "fix inventory on restart",                    1, gk1RestartInventorySignature,     gk1RestartInventoryPatch },
+	{  true,   210, "fix day 5 phone lockup (1/2)",                1, gk1Day5PhoneLockupSignature1,     gk1Day5PhoneLockupPatch1 },
+	{  true,   212, "fix day 5 phone lockup (2/2)",                2, gk1Day5PhoneLockupSignature2,     gk1Day5PhoneLockupPatch2 },
 	{  true,   210, "fix day 6 envelope lockup",                   2, gk1Day6EnvelopeSignature,         gk1Day6EnvelopePatch },
 	{  true,   211, "fix day 1 grace phone speech timing",         1, gk1Day1GracePhoneSignature,       gk1Day1GracePhonePatch },
 	{  true,   212, "fix day 5 drum book dialogue error",          1, gk1Day5DrumBookDialogueSignature, gk1Day5DrumBookDialoguePatch },
-	{  true,   212, "fix day 5 phone softlock",                    1, gk1Day5PhoneFreezeSignature,      gk1Day5PhoneFreezePatch },
 	{  true,   220, "fix ego phone position",                      2, gk1EgoPhonePositionSignature,     gk1EgoPhonePositionPatch },
 	{  true,   230, "fix day 6 police beignet timer issue (1/2)",  1, gk1Day6PoliceBeignetSignature1,   gk1Day6PoliceBeignetPatch1 },
 	{  true,   230, "fix day 6 police beignet timer issue (2/2)",  1, gk1Day6PoliceBeignetSignature2,   gk1Day6PoliceBeignetPatch2 },


Commit: f1ed765f2639ceada5ce2e54c624ca12a53fa470
    https://github.com/scummvm/scummvm/commit/f1ed765f2639ceada5ce2e54c624ca12a53fa470
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2025-04-29T10:40:43-07:00

Commit Message:
SCI32: Remove QFG4 Thieves' Guild script patch

Fixes bug #15776

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


diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 3646ea7521a..17a951c145b 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -111,7 +111,7 @@ static const char *const selectorNameTable[] = {
 	"localize",     // Freddy Pharkas
 	"roomFlags",    // Iceman
 	"put",          // Police Quest 1 VGA
-	"approachVerbs", // Police Quest 1 VGA, QFG4
+	"approachVerbs", // Police Quest 1 VGA
 	"newRoom",      // Police Quest 3, GK1
 	"register",     // Quest For Glory 1 EGA, QFG4
 	"changeState",  // Quest For Glory 1 VGA, QFG4
@@ -161,7 +161,7 @@ static const char *const selectorNameTable[] = {
 	"delete",       // EcoQuest 1
 	"size",         // EcoQuest 1
 	"signal",       // EcoQuest 1, GK1
-	"obstacles",    // EcoQuest 1, QFG4
+	"obstacles",    // EcoQuest 1
 	"handleEvent",  // EcoQuest 2, Shivers
 	"view",         // King's Quest 4, RAMA benchmarking, GK1, QFG4
 	"tWindow",      // Camelot
@@ -199,7 +199,6 @@ static const char *const selectorNameTable[] = {
 	"readWord",     // LSL7, Phant1, Torin
 	"points",       // PQ4
 	"select",       // PQ4
-	"addObstacle",  // QFG4
 	"saveFilePtr",  // RAMA
 	"priority",     // RAMA
 	"plane",        // RAMA
@@ -344,7 +343,6 @@ enum ScriptPatcherSelectors {
 	SELECTOR_readWord,
 	SELECTOR_points,
 	SELECTOR_select,
-	SELECTOR_addObstacle,
 	SELECTOR_saveFilePtr,
 	SELECTOR_priority,
 	SELECTOR_plane,
@@ -18940,254 +18938,6 @@ static const uint16 qfg4StuckDoorPatch[] = {
 	PATCH_END
 };
 
-// In the thieves' guild (room 430), the tunnel is not immediately walkable
-// when it is revealed (by moving a barrel and solving a puzzle). Hero must
-// re-enter the room to update the polygon.
-//
-// Curing Chief *will* immediately replace the polygon. However, most players
-// will lack the item necessary on the first visit. Meeting Chief is how they
-// learn about the item. If they go get it, they'll re-enter the room.
-//
-// The room's init has a cond block to check plot flags and declare one of 3
-// polygons. The 3rd condition also inits secritExit, an invisible Feature
-// that sends hero out of town when walked upon.
-//
-// Patch 1: Other patches ensure the passage will be walkable the moment it is
-//  revealed. Chief is standing inside it. We skip the original code that would
-//  set up the passage as he gets cured. It is redundant now. If hero can reach
-//  him, the passage is already revealed. We won't let secritExit init twice.
-//
-// Patch 2: We free bytes in rm340::init() by condensing Feature inits with a
-//  loop. Stack up their addresses. Pop & send repeatedly. Then we declare a
-//  subroutine that disposes any existing obstacles, jumps into the cond block
-//  to declare the 3rd poly, jumps back, passes it to addObstacles(), and inits
-//  secritExit.
-//
-//  When the cond block's 3rd condition runs, we immediately call our
-//  subroutine to do everything and end the cond, leaving the original polygon
-//  declaration intact below the jump.
-//
-// Patch 3: The passage starts opening at sBarrelMove state 8. We need more
-//  room than case 8 can offer, so we arrange for *multiple* cases to run
-//  during state 8 - by omitting the final jump that would short-circuit.
-//
-//  Cases 1-5 have derelict code, once intended to move the barrel back and
-//  forth, now only left. This is because barrel::doVerb(4) schedules
-//  sBarrelMove in the absence of flag 254 and sets register=1 if the barrel is
-//  in the left position already. Case 0 uses the same criteria in deciding to
-//  skip to state 6. Thus cases 1-5 never see register==1. The barrel never
-//  moves back, and bytes predicated on register==1 are available.
-//
-//  We reduce case 2 to only the necessary ops and splice in a new case that
-//  runs during state 8 as a prologue to the original case 8. Our prologue
-//  calls the subroutine to add the 3rd polygon. This patch has two variants,
-//  toggled to match the detected edition with enablePatch() below. Aside from
-//  the call offset, they are identical.
-//
-// Applies to at least: English CD, English floppy, German floppy
-// Responsible method: sChangeThief::changeState() in script 340
-// Fixes bug: #9894
-static const uint16 qfg4GuildWalkSignature1[] = {
-	0x38, SIG_SELECTOR16(dispose),      // pushi dispose
-	SIG_ADDTOOFFSET(+20),               // ... (dispose and null global[2]'s "obstacles" property)
-	0x4a, SIG_UINT16(0x0006),           // send 6d
-	SIG_ADDTOOFFSET(+85),               // ...
-	SIG_ADDTOOFFSET(+238),              // ... (secritExit init and addObstacle)
-	SIG_MAGICDWORD,
-	0x4a, SIG_UINT16(0x00a6),           // send 166d (polygon init)
-	0x36,                               // push
-	SIG_ADDTOOFFSET(+5),                // ... (global[2] addObstacle: polygon)
-	SIG_END
-};
-
-static const uint16 qfg4GuildWalkPatch1[] = {
-	0x32, PATCH_UINT16(0x0017),         // jmp 23d (skip obstacles disposal)
-	PATCH_ADDTOOFFSET(+108),
-	0x32, PATCH_UINT16(0x00f4),         // jmp 244d (skip secritExit and polygon)
-	PATCH_END
-};
-
-// Responsible method: rm340::init() in script 340
-static const uint16 qfg4GuildWalkSignature2[] = {
-	0x38, SIG_SELECTOR16(init),          // pushi init
-	0x76,                                // push0
-	0x38, SIG_SELECTOR16(approachVerbs), // pushi approachVerbs
-	0x78,                                // push1
-	0x39, 0x04,                          // pushi 4d
-	0x72, SIG_ADDTOOFFSET(+2),           // lofsa steps1
-	0x4a, SIG_UINT16(0x000a),            // send 10d
-
-	SIG_ADDTOOFFSET(+10),               // ... (similar inits follow)
-	0x72, SIG_ADDTOOFFSET(+2),          // lofsa steps2
-	SIG_ADDTOOFFSET(+13),               // ...
-	0x72, SIG_ADDTOOFFSET(+2),          // lofsa barrels1
-	SIG_ADDTOOFFSET(+13),               // ...
-	0x72, SIG_ADDTOOFFSET(+2),          // lofsa barrels2
-	SIG_ADDTOOFFSET(+13),               // ...
-	0x72, SIG_ADDTOOFFSET(+2),          // lofsa crack1
-	SIG_ADDTOOFFSET(+13),               // ...
-	0x72, SIG_ADDTOOFFSET(+2),          // lofsa crack2
-	SIG_ADDTOOFFSET(+13),               // ...
-	0x72, SIG_ADDTOOFFSET(+2),          // lofsa pillar
-	SIG_ADDTOOFFSET(+3),                // ...
-
-	SIG_ADDTOOFFSET(+26),               // ... (global[78]::add() steps1 and steps2)
-
-	SIG_ADDTOOFFSET(+459),              // ... (cond block for polygons)
-	SIG_MAGICDWORD,
-	0x32, SIG_UINT16(0x00f7),           // jmp 247d [end the cond] (2nd condition done)
-
-										// (else condition)
-	0x38, SIG_SELECTOR16(init),         // pushi init
-	0x76,                               // push0
-	0x72, SIG_ADDTOOFFSET(+2),          // lofsa secritExit
-	0x4a, SIG_UINT16(0x0004),           // send 4d
-	SIG_ADDTOOFFSET(+4),                // ... (addObstacle and its arg count)
-	SIG_ADDTOOFFSET(+228),              // ... (3rd Polygon type, init, and push)
-	SIG_ADDTOOFFSET(+5),                // ... (end of the polygons cond)
-
-	0x38, SIG_SELECTOR16(init),         // pushi init (super init:)
-	SIG_END
-};
-
-static const uint16 qfg4GuildWalkPatch2[] = {
-	0x3f, 0x02,                         // link 02 (set up loop vars, op affects the stack)
-	0x74, PATCH_GETORIGINALUINT16(11),  // lofss steps1
-	0x74, PATCH_GETORIGINALUINT16(27),  // lofss steps2
-	0x74, PATCH_GETORIGINALUINT16(43),  // lofss barrels1
-	0x74, PATCH_GETORIGINALUINT16(59),  // lofss barrels2
-	0x74, PATCH_GETORIGINALUINT16(75),  // lofss crack1
-	0x74, PATCH_GETORIGINALUINT16(91),  // lofss crack2
-	0x74, PATCH_GETORIGINALUINT16(107), // lofss pillar
-										//
-	0x35, 0x08,                         // ldi 8d (decrement and send 7 times, while != 0)
-	0xa5, 0x00,                         // sat temp[0]
-										//
-	0xe5, 0x00,                         // -at temp[0]
-	0x31, 0x13,                         // bnt 19d [on 0, end the loop]
-	0xad, 0x01,                            // sst temp[1] (pop the next object into a temp var)
-	0x38, PATCH_SELECTOR16(init),          // pushi init
-	0x76,                                  // push0
-	0x38, PATCH_SELECTOR16(approachVerbs), // pushi approachVerbs
-	0x78,                                  // push1
-	0x39, 0x04,                            // pushi 4d
-	0x85, 0x01,                            // lat temp[1] (accumulate the object)
-	0x4a, PATCH_UINT16(0x000a),            // send 10d
-	0x33, 0xe9,                         // jmp -23d [loop]
-
-	0x33, 0x33,                         // jmp 51d [skip subroutine declaration]
-	0x38, PATCH_SELECTOR16(obstacles),  // pushi obstacles (look up "obstacles", might be null)
-	0x76,                               // push0
-	0x81, 0x02,                         // lag global[2]
-	0x4a, PATCH_UINT16(0x0004),         // send 4d
-	0x31, 0x11,                         // bnt 17d [skip disposal and nulling]
-	0x38, PATCH_SELECTOR16(dispose),    // pushi dispose
-	0x76,                               // push0
-	0x4a, PATCH_UINT16(0x0004),         // send 4d ((global[2] obstacles?) dispose:)
-										//
-	0x38, PATCH_SELECTOR16(obstacles),  // pushi obstacles (null the "obstacles" property)
-	0x78,                               // push1
-	0x76,                               // push0
-	0x81, 0x02,                         // lag global[2]
-	0x4a, PATCH_UINT16(0x0006),         // send 6d
-										//
-	0x38, PATCH_SELECTOR16(addObstacle), // pushi addObstacle
-	0x78,                               // push1
-	0x32, PATCH_UINT16(0x020f),         // jmp 527d [3rd polygon type, init, and push]
-										// (That will jmp back here)
-	0x81, 0x02,                         // lag global[2]
-	0x4a, PATCH_UINT16(0x0006),         // send 6d
-										//
-	0x38, PATCH_SELECTOR16(init),       // pushi init
-	0x76,                               // push0
-	0x72, PATCH_GETORIGINALUINT16(605), // lofsa secritExit
-	0x4a, PATCH_UINT16(0x0004),         // send 4d
-	0x48,                               // ret
-
-	0x33, 0x07,                         // jmp 7d [skip waste bytes, to (global[78] add: steps1)]
-	0x5c,                               // selfID (waste 1 byte)
-	PATCH_ADDTOOFFSET(+494),            // ...
-	0x76,                               // push0 (0 call args, clobber the old secritExit init)
-	0x40, PATCH_UINT16(0xfdd6), PATCH_UINT16(0x0000), // call 0d [-554] (the subroutine does everything)
-	0x32, PATCH_UINT16(0x00ee),         // jmp 238d [end the cond]
-	0x5c,                               // selfID (waste 1 byte)
-	PATCH_ADDTOOFFSET(+4),              // ...
-	PATCH_ADDTOOFFSET(+228),            // ... (3rd polygon type, init, and push)
-	0x32, PATCH_UINT16(0xfd0a),         // jmp -758d [back into the subroutine]
-	0x35, 0x00,                         // ldi 0 (erase 2 bytes to keep disasm aligned)
-	PATCH_END
-};
-
-// Applies to at least: English CD
-// Responsible method: sBarrelMove::changeState(2) in script 340
-static const uint16 qfg4GuildWalkCDSignature3[] = {
-	SIG_MAGICDWORD,
-	0x30, SIG_UINT16(0x0032),           // bnt 50d [next case]
-	0x35, 0x02,                         // ldi 2d (case 2 label)
-	SIG_ADDTOOFFSET(+26),               // ... (register branch and derelict say())
-	SIG_ADDTOOFFSET(+19),               // ... (else, the rest of case 2 is a necessary say())
-	0x32, SIG_ADDTOOFFSET(+2),          // jmp ?? [end the switch]
-	SIG_END
-};
-
-static const uint16 qfg4GuildWalkCDPatch3[] = {
-	0x31, 0x15,                         // bnt 21d [next case]
-	0x38, PATCH_SELECTOR16(say),        // pushi say
-	0x39, 0x05,                         // pushi 5d
-	0x39, 0x06,                         // pushi 6d
-	0x39, 0x04,                         // pushi 4d
-	0x39, 0x13,                         // pushi 19d
-	0x76,                               // push0
-	0x7c,                               // pushSelf
-	0x81, 0x5b,                         // lag global[91]
-	0x4a, PATCH_UINT16(0x000e),         // send 14d
-	0x32, PATCH_GETORIGINALUINT16ADJUST(51, +30), // jmp ?? [end the switch]
-
-	0x3c,                               // dup (case 8 prologue)
-	0x35, 0x08,                         // ldi 8d
-	0x1a,                               // eq?
-	0x31, 0x06,                         // bnt 6d [next case]
-	0x76,                               // push0 (0 call args)
-	0x40, PATCH_UINT16(0xf592), PATCH_UINT16(0x0000), // call [-2670], 0d (patch 2's subroutine)
-	0x33, 0x10,                         // jmp 16d [skip waste bytes]
-	PATCH_END                           // (don't end the switch, keep testing cases)
-};
-
-// Applies to at least: English floppy, German floppy
-// Responsible method: sBarrelMove::changeState(2) in script 340
-static const uint16 qfg4GuildWalkFloppySignature3[] = {
-	SIG_MAGICDWORD,
-	0x30, SIG_UINT16(0x0032),           // bnt 50d [next case]
-	0x35, 0x02,                         // ldi 2d (case 2 label)
-	SIG_ADDTOOFFSET(+26),               // ... (register branch and derelict say())
-	SIG_ADDTOOFFSET(+19),               // ... (else, the rest of case 2 is a necessary say())
-	0x32, SIG_ADDTOOFFSET(+2),          // jmp ?? [end the switch]
-	SIG_END
-};
-
-static const uint16 qfg4GuildWalkFloppyPatch3[] = {
-	0x31, 0x15,                         // bnt 21d [next case]
-	0x38, PATCH_SELECTOR16(say),        // pushi say
-	0x39, 0x05,                         // pushi 5d
-	0x39, 0x06,                         // pushi 6d
-	0x39, 0x04,                         // pushi 4d
-	0x39, 0x13,                         // pushi 19d
-	0x76,                               // push0
-	0x7c,                               // pushSelf
-	0x81, 0x5b,                         // lag global[91]
-	0x4a, PATCH_UINT16(0x000e),         // send 14d
-	0x32, PATCH_GETORIGINALUINT16ADJUST(51, +30), // jmp ?? [end the switch]
-
-	0x3c,                               // dup (case 8 prologue)
-	0x35, 0x08,                         // ldi 8d
-	0x1a,                               // eq?
-	0x31, 0x06,                         // bnt 6d [next case]
-	0x76,                               // push0 (0 call args)
-	0x40, PATCH_UINT16(0xf5a8), PATCH_UINT16(0x0000), // call [-2648], 0d (patch 2's subroutine)
-	0x33, 0x10,                         // jmp 16d [skip waste bytes]
-	PATCH_END                           // (don't end the switch, keep testing cases)
-};
-
 // Rations are not properly decremented by daily scheduled meal consumption.
 // Rations are consumed periodically as time advances. If rations are the
 // active inventory item when the last of them is eaten, that icon will persist
@@ -21601,10 +21351,6 @@ static const SciScriptPatcherEntry qfg4Signatures[] = {
 	{  true,   320, "fix talking to absent innkeeper",             1, qfg4AbsentInnkeeperSignature,  qfg4AbsentInnkeeperPatch },
 	{  true,   320, "CD: fix domovoi never appearing",             1, qfg4DomovoiInnSignature,       qfg4DomovoiInnPatch },
 	{  true,   324, "CD: fix domovoi never appearing",             1, qfg4DomovoiInnSignature,       qfg4DomovoiInnPatch },
-	{  true,   340, "CD/Floppy: fix guild tunnel access (1/3)",    1, qfg4GuildWalkSignature1,       qfg4GuildWalkPatch1 },
-	{  true,   340, "CD/Floppy: fix guild tunnel access (2/3)",    1, qfg4GuildWalkSignature2,       qfg4GuildWalkPatch2 },
-	{  false,  340, "CD: fix guild tunnel access (3/3)",           1, qfg4GuildWalkCDSignature3,     qfg4GuildWalkCDPatch3 },
-	{  false,  340, "Floppy: fix guild tunnel access (3/3)",       1, qfg4GuildWalkFloppySignature3, qfg4GuildWalkFloppyPatch3 },
 	{  true,   440, "fix setLooper calls (1/2)",                   1, qfg4SetLooperSignature1,       qfg4SetLooperPatch1 },
 	{  true,   475, "fix tarot 3 queen card",                      1, qfg4Tarot3QueenSignature,      qfg4Tarot3QueenPatch },
 	{  true,   475, "fix tarot 3 death card",                      1, qfg4Tarot3DeathSignature,      qfg4Tarot3DeathPatch },
@@ -26738,11 +26484,9 @@ void ScriptPatcher::processScript(uint16 scriptNr, SciSpan<byte> scriptData) {
 					enablePatch(signatureTable, "CD: fix rope during Igor rescue (2/2)");
 
 					// Similar signatures that patch with different addresses/offsets
-					enablePatch(signatureTable, "CD: fix guild tunnel access (3/3)");
 					enablePatch(signatureTable, "CD: fix crest bookshelf");
 					enablePatch(signatureTable, "CD: fix peer bats, upper door (2/2)");
 				} else {
-					enablePatch(signatureTable, "Floppy: fix guild tunnel access (3/3)");
 					enablePatch(signatureTable, "Floppy: fix crest bookshelf");
 					enablePatch(signatureTable, "Floppy: fix peer bats, upper door (2/2)");
 				}


Commit: f22925bf89de6a80f51a2ca50b078235119bd91a
    https://github.com/scummvm/scummvm/commit/f22925bf89de6a80f51a2ca50b078235119bd91a
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2025-04-29T10:40:43-07:00

Commit Message:
SCI: Add detection for BRAIN1 French fan translation

Trac #15875

Changed paths:
    engines/sci/detection_tables.h


diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 25b51b8353f..4ef5c15d7b5 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -151,16 +151,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
 		AD_LISTEND},
 		Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO_STD16	},
 
-	// Castle of Dr. Brain - Korean fan translation, based on English DOS Floppy 1.1
-	{"castlebrain", "", {
-		{"resource.map", 0, "f77728304c70017c54793eb6ca648174", 2745},
-		{"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 347071},
-		{"resource.001", 0, "13e81e1839cd7b216d2bb5615c1ca160", 796776},
-		{"resource.002", 0, "930e416bec196b9703a331d81b3d66f2", 1283812},
-		{"resource.msg", 0, "71c6f480e742a0dd3700ec7825962921", 49538},
-		AD_LISTEND},
-		Common::KO_KOR, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO_STD16	},
-
 	// Castle of Dr. Brain - English DOS Floppy 1.000
 	// Reported by graxer in bug report #5094
 	{"castlebrain", "", {
@@ -204,6 +194,31 @@ static const struct ADGameDescription SciGameDescriptions[] = {
 		AD_LISTEND},
 		Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO_STD16_HIRES	},
 
+	// Castle of Dr. Brain - French fan translation, based on English DOS Floppy 1.000
+	{"castlebrain", "", {
+		{"resource.map", 0, "dd994a1e509542ca7060680371961d8f", 2665},
+		{"resource.000", 0, "6e125f4ce3f4f5c35f2617c7b66c6e21", 58916},
+		{"resource.001", 0, "4891faa2f6594c622e482f0ddce24fb4", 126120},
+		{"resource.002", 0, "aebb56d5d005557ca0d122a03aa85386", 353483},
+		{"resource.003", 0, "278ec1e6132c7be844d433dd23beb318", 335156},
+		{"resource.004", 0, "fca1c3f2be660185206f004bda09f4fb", 333549},
+		{"resource.005", 0, "9294e55da1e83708ad3104b2a3963e18", 327537},
+		{"resource.006", 0, "1d778a0c65cac9ddbab65495e50a94ee", 416394},
+		{"resource.007", 0, "063bb8ce4157c778cf30d1c912c006f1", 469925},
+		{"resource.008", 0, "735be4e58957180cfc807d5e18fdffcd", 356863},
+		AD_LISTEND},
+		Common::FR_FRA, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO_STD16	},
+
+	// Castle of Dr. Brain - Korean fan translation, based on English DOS Floppy 1.1
+	{"castlebrain", "", {
+		{"resource.map", 0, "f77728304c70017c54793eb6ca648174", 2745},
+		{"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 347071},
+		{"resource.001", 0, "13e81e1839cd7b216d2bb5615c1ca160", 796776},
+		{"resource.002", 0, "930e416bec196b9703a331d81b3d66f2", 1283812},
+		{"resource.msg", 0, "71c6f480e742a0dd3700ec7825962921", 49538},
+		AD_LISTEND},
+		Common::KO_KOR, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO_STD16	},
+
 	// Inside the Chest / Behind the Developer's Shield
 	// SCI interpreter version 2.000.000
 	// This demo would display a different title and logo depending on which batch


Commit: 92cb377b4d44ed041928ade78509608f70f97dde
    https://github.com/scummvm/scummvm/commit/92cb377b4d44ed041928ade78509608f70f97dde
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2025-04-29T10:40:44-07:00

Commit Message:
SCI: Fix picture vector patterns at right edge of screen

Fixes an inaccurate edge case when drawing patterns that border the
right edge of the screen. This was introduced when fixing inaccuracies
when drawing patterns that should appear beyond the right edge:
44b6050915ed6012f9e2e14c8ffa81d9e366529d

Fixes the first room in The Black Cauldron, bug #15876

Changed paths:
    engines/sci/graphics/picture.cpp


diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp
index ee4bfb4a2c6..a5004744cc6 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -1159,10 +1159,10 @@ void GfxPicture::vectorPattern(int16 x, int16 y, byte color, byte priority, byte
 	// texture and circle data can only be properly consumed by evaluating
 	// every pixel during drawing, even the pixels that are then skipped
 	// for being out of bounds. (Example: SQ3 picture 2)
-	if (box.right >= _screen->getScriptWidth()) {
-		box.moveTo(_screen->getScriptWidth() - box.width() + 1, box.top);
+	if (box.right > _screen->getScriptWidth() + 1) {
+		box.moveTo(_screen->getScriptWidth() + 1 - box.width(), box.top);
 	}
-	if (box.bottom >= _screen->getScriptHeight()) {
+	if (box.bottom > _screen->getScriptHeight()) {
 		box.moveTo(box.left, _screen->getScriptHeight() - box.height());
 	}
 	_screen->vectorAdjustCoordinate(&box.left, &box.top);




More information about the Scummvm-git-logs mailing list