[Scummvm-git-logs] scummvm master -> 97329525d686722b34136e391dc7503e1745c35d

neuromancer noreply at scummvm.org
Tue Jun 2 21:20:42 UTC 2026


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

Summary:
97329525d6 SCUMM: RA2: avoid crash in level 11


Commit: 97329525d686722b34136e391dc7503e1745c35d
    https://github.com/scummvm/scummvm/commit/97329525d686722b34136e391dc7503e1745c35d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-02T23:20:28+02:00

Commit Message:
SCUMM: RA2: avoid crash in level 11

Changed paths:
    engines/scumm/insane/rebel2/iact.cpp
    engines/scumm/smush/rebel/smush_player_ra2.cpp


diff --git a/engines/scumm/insane/rebel2/iact.cpp b/engines/scumm/insane/rebel2/iact.cpp
index fef48209da6..af30f749a81 100644
--- a/engines/scumm/insane/rebel2/iact.cpp
+++ b/engines/scumm/insane/rebel2/iact.cpp
@@ -2358,16 +2358,19 @@ bool InsaneRebel2::loadLevel2Background(byte *animData, int32 size, byte *render
 			debug("Rebel2 loadLevel2Background: Found FOBJ: codec=%d pos=(%d,%d) size=%dx%d",
 				codec, fobjX, fobjY, fobjW, fobjH);
 
-			// Decode codec 3 (RLE) into background buffer.
-			// Use smushDecodeRLEOpaque to write ALL colors including color 0 (black).
+			// Decode codec 3 (RLE) into the original 320x200 background buffer.
+			// FUN_0041CADB/FUN_00401234 draw these resources into a fixed buffer
+			// and clip them there; Level 11 backgrounds extend past the right edge.
 			if (codec == 3 && fobjX >= 0 && fobjY >= 0 && fobjW > 0 && fobjH > 0 &&
-					fobjX + fobjW <= 320 && fobjY + fobjH <= 200 && stream.pos() < subDataEnd) {
+					fobjX < 320 && fobjY < 200 && stream.pos() < subDataEnd) {
+				int drawW = MIN<int>(fobjW, 320 - fobjX);
+				int drawH = MIN<int>(fobjH, 200 - fobjY);
 				const byte *rleData = animData + stream.pos();
-				smushDecodeRLEOpaque(_level2Background, rleData, fobjX, fobjY, fobjW, fobjH, 320,
+				smushDecodeRLEOpaque(_level2Background, rleData, fobjX, fobjY, drawW, drawH, 320,
 					(int)(subDataEnd - stream.pos()));
 
-				debug("Rebel2 loadLevel2Background: Decoded Level 2 background (%dx%d at %d,%d)",
-					fobjW, fobjH, fobjX, fobjY);
+				debug("Rebel2 loadLevel2Background: Decoded Level 2 background (%dx%d at %d,%d, clipped to %dx%d)",
+					fobjW, fobjH, fobjX, fobjY, drawW, drawH);
 				_level2BackgroundLoaded = true;
 				foundBackground = true;
 
diff --git a/engines/scumm/smush/rebel/smush_player_ra2.cpp b/engines/scumm/smush/rebel/smush_player_ra2.cpp
index 5f22d5dc428..e24b8f56d3c 100644
--- a/engines/scumm/smush/rebel/smush_player_ra2.cpp
+++ b/engines/scumm/smush/rebel/smush_player_ra2.cpp
@@ -115,6 +115,11 @@ void SmushPlayerRebel2::initGameVideoState() {
 	// Since play() resets _palDirtyMin/Max, the palette would never be pushed otherwise.
 	setDirtyColors(0, 255);
 
+	// SmushPlayer::init() resets _dst to the virtual screen. Use matching
+	// screen dimensions until AHDR/FOBJ selects a larger gameplay surface.
+	_width = _vm->_screenWidth;
+	_height = _vm->_screenHeight;
+
 	// Handle background preservation between videos:
 	// - Cinematic videos (flags 0x20) clear the buffer for a fresh start
 	// - Gameplay videos (flags 0x08) preserve the existing screen content
@@ -441,10 +446,9 @@ void SmushPlayerRebel2::ra2HandleDeltaPalette(int32 subSize, Common::SeekableRea
 	setDirtyColors(0, 255);
 }
 
-/**
- * RA2-specific handleAnimHeader fixup: when AHDR reports 0x0 dimensions,
- * use screen dimensions instead.
- */
+// RA2-specific AHDR handling. AHDR metadata can describe the original SMUSH
+// backing bitmap, but active low-res gameplay dimensions are selected later by
+// IACT/FOBJ state; keep the virtual-screen pitch safe until then.
 bool SmushPlayerRebel2::handleGameAnimHeader(byte *headerContent) {
 	int width = READ_LE_UINT16(&headerContent[4]);
 	int height = READ_LE_UINT16(&headerContent[6]);
@@ -453,10 +457,22 @@ bool SmushPlayerRebel2::handleGameAnimHeader(byte *headerContent) {
 		_width = _vm->_screenWidth;
 		_height = _vm->_screenHeight;
 		debugC(DEBUG_SMUSH, "SmushPlayerRebel2::handleGameAnimHeader: RA2 AHDR has 0x0 dims - using screen size %dx%d", _width, _height);
+	} else if (width != _vm->_screenWidth || height != _vm->_screenHeight) {
+		// FUN_00407FCB/FUN_0040C3CC update the active frame descriptor from
+		// IACT opcode 6. In ScummVM's low-res path the descriptor remains
+		// 320x200 and perspective is applied through FUN_00424510-equivalent
+		// FOBJ offsets. Do not let AHDR alone change pitch while _dst still
+		// points at the virtual screen; FOBJ selection will allocate a larger
+		// surface when an actual oversized frame object is decoded.
+		_width = _vm->_screenWidth;
+		_height = _vm->_screenHeight;
+		debugC(DEBUG_SMUSH, "SmushPlayerRebel2::handleGameAnimHeader: RA2 AHDR %dx%d - using screen size until FOBJ selects a surface",
+			width, height);
 	} else {
 		_width = width;
 		_height = height;
 	}
+
 	return true;
 }
 
@@ -757,9 +773,24 @@ bool SmushPlayerRebel2::handleGameFrameBufferSelect(int codec, int width, int he
 
 bool SmushPlayerRebel2::handleGameDimensionOverride(int codec, int width, int height) {
 	if ((height != _vm->_screenHeight) || (width != _vm->_screenWidth)) {
-		// RA2: preserve _width/_height set during buffer allocation
-		return true;
+		if (_insane != nullptr) {
+			InsaneRebel2 *rebel2 = static_cast<InsaneRebel2 *>(_insane);
+			if (rebel2->getHandler() != 0) {
+				// RA2 gameplay preserves the dimensions selected by the
+				// current frame target instead of the individual FOBJ.
+				return true;
+			}
+		}
+
+		if (_dst == _specialBuffer && _specialBuffer != nullptr) {
+			return true;
+		}
+
+		// Handler-zero videos are menus/cinematics. Let the base player restore
+		// normal screen dimensions so menu overlays do not inherit gameplay pitch.
+		return false;
 	}
+
 	return false;
 }
 




More information about the Scummvm-git-logs mailing list