[Scummvm-git-logs] scummvm master -> 61d84074f729396526b43868bd5ae90796e70922

neuromancer noreply at scummvm.org
Sun Jun 7 21:08:07 UTC 2026


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

Summary:
8dc22ae389 SCUMM: RA2: added no damage game flag to help debugging
61d84074f7 SCUMM: RA1: make sure sound buffer is large enough


Commit: 8dc22ae389235c18eaeca97db34455f67476d32f
    https://github.com/scummvm/scummvm/commit/8dc22ae389235c18eaeca97db34455f67476d32f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-07T23:07:40+02:00

Commit Message:
SCUMM: RA2: added no damage game flag to help debugging

Changed paths:
    engines/scumm/detection.h
    engines/scumm/detection_tables.h
    engines/scumm/insane/rebel2/iact.cpp
    engines/scumm/insane/rebel2/rebel.cpp
    engines/scumm/insane/rebel2/rebel.h
    engines/scumm/insane/rebel2/render.cpp
    engines/scumm/metaengine.cpp
    engines/scumm/smush/rebel/smush_player_ra2.cpp
    engines/scumm/smush/rebel/smush_player_ra2.h


diff --git a/engines/scumm/detection.h b/engines/scumm/detection.h
index cd6dbfa9d43..29f49690434 100644
--- a/engines/scumm/detection.h
+++ b/engines/scumm/detection.h
@@ -41,6 +41,7 @@ namespace Scumm {
 #define GAMEOPTION_REBEL2_HIRES                              GUIO_GAMEOPTIONS10
 #define GAMEOPTION_REBEL2_UNLOCK_ALL                         GUIO_GAMEOPTIONS11
 #define GAMEOPTION_REBEL1_UNLOCK_ALL                         GUIO_GAMEOPTIONS12
+#define GAMEOPTION_REBEL2_NO_DAMAGE                          GUIO_GAMEOPTIONS13
 
 /**
  * Descriptor of a specific SCUMM game. Used internally to store
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 9c2260772c4..8e14a3c0152 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -230,8 +230,8 @@ static const GameSettings gameVariantsTable[] = {
 
 	{"rebel1", "", 0, GID_REBEL1, 7, 0, MDT_NONE, 0, Common::kPlatformDOS, GUIO2(GUIO_NOMIDI, GAMEOPTION_REBEL1_UNLOCK_ALL)},
 
-	{"rebel2", "", 0, GID_REBEL2, 7, 0, MDT_NONE, 0, Common::kPlatformDOS, GUIO3(GUIO_NOMIDI, GAMEOPTION_REBEL2_HIRES, GAMEOPTION_REBEL2_UNLOCK_ALL)},
-	{"rebel2", "Demo", 0, GID_REBEL2, 7, 0, MDT_NONE, GF_DEMO, Common::kPlatformDOS, GUIO3(GUIO_NOMIDI, GAMEOPTION_REBEL2_HIRES, GAMEOPTION_REBEL2_UNLOCK_ALL)},
+	{"rebel2", "", 0, GID_REBEL2, 7, 0, MDT_NONE, 0, Common::kPlatformDOS, GUIO4(GUIO_NOMIDI, GAMEOPTION_REBEL2_HIRES, GAMEOPTION_REBEL2_UNLOCK_ALL, GAMEOPTION_REBEL2_NO_DAMAGE)},
+	{"rebel2", "Demo", 0, GID_REBEL2, 7, 0, MDT_NONE, GF_DEMO, Common::kPlatformDOS, GUIO4(GUIO_NOMIDI, GAMEOPTION_REBEL2_HIRES, GAMEOPTION_REBEL2_UNLOCK_ALL, GAMEOPTION_REBEL2_NO_DAMAGE)},
 
 	{"dig",  "", 0, GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO5(GUIO_NOMIDI, GAMEOPTION_ENHANCEMENTS, GAMEOPTION_ORIGINALGUI, GAMEOPTION_LOWLATENCYAUDIO, GAMEOPTION_TTS)},
 	{"dig",  "Demo", 0, GID_DIG, 7, 0, MDT_NONE, GF_DEMO, UNK, GUIO4(GUIO_NOMIDI, GAMEOPTION_ORIGINALGUI, GAMEOPTION_LOWLATENCYAUDIO, GAMEOPTION_TTS)},
diff --git a/engines/scumm/insane/rebel2/iact.cpp b/engines/scumm/insane/rebel2/iact.cpp
index 8572dd26a67..4d484fdb487 100644
--- a/engines/scumm/insane/rebel2/iact.cpp
+++ b/engines/scumm/insane/rebel2/iact.cpp
@@ -484,15 +484,13 @@ void InsaneRebel2::iactRebel2Opcode3(Common::SeekableReadStream &b, int16 par2,
 				debug("Rebel2 Opcode3: probability=%d roll=%d (need roll < prob)", probability, roll);
 
 				if (roll < probability) {
-					if (!_rebelInvulnerable) {
-						int damageAmount = (params.shotDamage >= 0) ? params.shotDamage : 0;
-						_playerDamage += damageAmount;
-						if (_playerDamage > 255)
-							_playerDamage = 255;
+					int damageAmount = (params.shotDamage >= 0) ? params.shotDamage : 0;
+					if (applyPlayerDamage(damageAmount)) {
 						debug("Rebel2: H25 PROBABILISTIC damage from %d. Damage=%d total=%d",
 							srcIdBody1, damageAmount, _playerDamage);
 					}
-					initDamageFlash();
+					if (!_noDamage)
+						initDamageFlash();
 				}
 			} else {
 				debug("Rebel2 Opcode3: H25 par3=5 BLOCKED (damageLevel=%d isBitSet=%d)",
@@ -509,16 +507,14 @@ void InsaneRebel2::iactRebel2Opcode3(Common::SeekableReadStream &b, int16 par2,
 
 		// Direct damage: par4==100, separate from par3 branches (lines 99-111)
 		if (par4 == 100 && !isBitSet(srcIdBody0)) {
-			if (!_rebelInvulnerable) {
-				LevelDifficultyParams dparams = getDifficultyParams();
-				int directHitDamage = (dparams.missDamage >= 0) ? dparams.missDamage : 0;
-				_playerDamage += directHitDamage;
-				if (_playerDamage > 255)
-					_playerDamage = 255;
+			LevelDifficultyParams dparams = getDifficultyParams();
+			int directHitDamage = (dparams.missDamage >= 0) ? dparams.missDamage : 0;
+			if (applyPlayerDamage(directHitDamage)) {
 				debug("Rebel2: H25 DIRECT HIT par4=100 damage=%d total=%d",
 					directHitDamage, _playerDamage);
 			}
-			initDamageFlash();
+			if (!_noDamage)
+				initDamageFlash();
 		}
 	} else if (par3 == 1 || par3 == 2) {
 		// Non-Handler-25 direct hit path — FUN_4092D9 lines 209-227
@@ -546,14 +542,12 @@ void InsaneRebel2::iactRebel2Opcode3(Common::SeekableReadStream &b, int16 par2,
 				}
 
 				if (shouldDamage) {
-					if (!_rebelInvulnerable) {
-						_playerDamage += directHitDamage;
-						if (_playerDamage > 255)
-							_playerDamage = 255;
+					if (applyPlayerDamage(directHitDamage)) {
 						debug("Rebel2: DIRECT HIT damage from enemy %d. par3=%d par4=%d damage=%d total=%d",
 							srcId, par3, par4, directHitDamage, _playerDamage);
 					}
-					initDamageFlash();
+					if (!_noDamage)
+						initDamageFlash();
 				}
 			}
 		}
@@ -572,18 +566,17 @@ void InsaneRebel2::iactRebel2Opcode3(Common::SeekableReadStream &b, int16 par2,
 			debug("Rebel2 Opcode3: probability=%d roll=%d (need roll < prob)", probability, roll);
 
 			if (roll < probability) {
-				if (!_rebelInvulnerable) {
-					int damageAmount = (params.shotDamage >= 0) ? params.shotDamage : 0;
-					_playerDamage += damageAmount;
-					if (_playerDamage > 255)
-						_playerDamage = 255;
+				int damageAmount = (params.shotDamage >= 0) ? params.shotDamage : 0;
+				if (applyPlayerDamage(damageAmount)) {
 					debug("Rebel2: PROBABILISTIC damage from enemy %d. Damage=%d total=%d",
 						srcId, damageAmount, _playerDamage);
 				}
-				if (_rebelHandler == 8) {
-					triggerDamageEffect();
-				} else {
-					initDamageFlash();
+				if (!_noDamage) {
+					if (_rebelHandler == 8) {
+						triggerDamageEffect();
+					} else {
+						initDamageFlash();
+					}
 				}
 			}
 		}
@@ -985,12 +978,9 @@ void InsaneRebel2::handleOpcode6Handler7(Common::SeekableReadStream &b, int16 pa
 					_velocityHistory[i] = -127;
 				_hitCooldown = 10;
 				_spaceShotDirection = 1;
-				initDamageFlash();
-				if (!_rebelInvulnerable) {
-					_playerDamage += corridorWallDmg;
-					if (_playerDamage > 255)
-						_playerDamage = 255;
-				}
+				applyPlayerDamage(corridorWallDmg);
+				if (!_noDamage)
+					initDamageFlash();
 				_rebelHitCounter++;
 				playSfx(1, 127, 100);  // CRASH.SAD, right wall, pan right
 			}
@@ -1004,12 +994,9 @@ void InsaneRebel2::handleOpcode6Handler7(Common::SeekableReadStream &b, int16 pa
 					_velocityHistory[i] = 127;
 				_hitCooldown = 10;
 				_spaceShotDirection = 0;
-				initDamageFlash();
-				if (!_rebelInvulnerable) {
-					_playerDamage += corridorWallDmg;
-					if (_playerDamage > 255)
-						_playerDamage = 255;
-				}
+				applyPlayerDamage(corridorWallDmg);
+				if (!_noDamage)
+					initDamageFlash();
 				_rebelHitCounter++;
 				playSfx(1, 127, -100);  // CRASH.SAD, left wall, pan left
 			}
diff --git a/engines/scumm/insane/rebel2/rebel.cpp b/engines/scumm/insane/rebel2/rebel.cpp
index 7b8cb21dee8..e356621903c 100644
--- a/engines/scumm/insane/rebel2/rebel.cpp
+++ b/engines/scumm/insane/rebel2/rebel.cpp
@@ -187,6 +187,7 @@ InsaneRebel2::InsaneRebel2(ScummEngine_v7 *scumm) {
 	_playerShield = 255; // Full shields by default (255)
 	_playerLives = 3;
 	_playerScore = 0;
+	_noDamage = false;
 	_viewX = 0;
 	_viewY = 0;
 
@@ -491,6 +492,7 @@ InsaneRebel2::InsaneRebel2(ScummEngine_v7 *scumm) {
 	// Based on original debug mode (DAT_0047ab34 == 'd') from FUN_00415CF8
 	// Set to true to bypass normal unlock progression
 	_debugUnlockAll = ConfMan.getBool("rebel2_unlock_all");
+	_noDamage = ConfMan.getBool("rebel2_no_damage");
 
 	for (i = 0; i < 16; i++) {
 		// If debug unlock is enabled, unlock all chapters
@@ -1110,10 +1112,14 @@ bool InsaneRebel2::notifyEvent(const Common::Event &event) {
 			    _gameState == kStateGameplay &&
 			    _rebelHandler != 0 &&
 			    event.kbd.hasFlags(Common::KBD_SHIFT)) {
-				_playerDamage = 255;
-				_playerShield = 0;
-				debug("Rebel2: Shift+D pressed - forcing player death");
-				_vm->_smushVideoShouldFinish = true;
+				if (!_noDamage) {
+					_playerDamage = 255;
+					_playerShield = 0;
+					debug("Rebel2: Shift+D pressed - forcing player death");
+					_vm->_smushVideoShouldFinish = true;
+				} else {
+					debug("Rebel2: Shift+D pressed - no damage mode prevents forced death");
+				}
 				return true;  // Consume the event
 			}
 			break;
@@ -1311,6 +1317,17 @@ InsaneRebel2::LevelDifficultyParams InsaneRebel2::getDifficultyParams() const {
 	return kDifficultyTable[diff][lvIdx];
 }
 
+bool InsaneRebel2::applyPlayerDamage(int damage) {
+	if (_noDamage || _rebelInvulnerable || damage <= 0)
+		return false;
+
+	_playerDamage += damage;
+	if (_playerDamage > 255)
+		_playerDamage = 255;
+
+	return true;
+}
+
 // addScore -- Score system with bonus life awards (FUN_0041bf8d).
 void InsaneRebel2::addScore(int points) {
 	// Calculate bonus life threshold based on difficulty (DAT_0047a7fa)
diff --git a/engines/scumm/insane/rebel2/rebel.h b/engines/scumm/insane/rebel2/rebel.h
index 765ab1f4b22..9df2a13101b 100644
--- a/engines/scumm/insane/rebel2/rebel.h
+++ b/engines/scumm/insane/rebel2/rebel.h
@@ -149,6 +149,7 @@ public:
 	Common::String _passwordInput; // Current password input string (max 8 chars)
 	bool _chapterUnlocked[16];    // Which chapters are unlocked
 	bool _debugUnlockAll;         // Debug flag to unlock all chapters for testing
+	bool _noDamage;               // Game option: disable player damage
 
 	// Unlock all chapters for testing (debug mode)
 	// Call this to enable access to all chapters without passwords
@@ -870,6 +871,7 @@ public:
 	void applyHandler7ObstacleHit(const CollisionZone &zone, int zoneIndex);
 	void awardHandler7DodgeScore();
 	void checkHandler7ObstacleZones(uint16 &warningMask);
+	bool applyPlayerDamage(int damage);
 	bool applyHandler7WallDamage(int wallDamage);
 	void resetHandler7HorizontalVelocity(int16 velocity);
 	void checkHandler7TopBoundary(const CollisionZone &zone, int16 vMargin, int wallDamage, uint16 &warningMask);
diff --git a/engines/scumm/insane/rebel2/render.cpp b/engines/scumm/insane/rebel2/render.cpp
index 1c986483361..7a84b815bff 100644
--- a/engines/scumm/insane/rebel2/render.cpp
+++ b/engines/scumm/insane/rebel2/render.cpp
@@ -1781,15 +1781,13 @@ void InsaneRebel2::checkCollisionZones(byte *renderBitmap, int pitch, int width,
 				// Original: DAT_0047a7ec += DAT_0047e0f6[chapter * 0x242 + level * 0x22]
 				int collisionDamage = (dparams.dodgeDamage >= 0) ? dparams.dodgeDamage : 0;
 
-				if (!_rebelInvulnerable) {
-					_playerDamage += collisionDamage;
-					if (_playerDamage > 255)
-						_playerDamage = 255;
+				if (applyPlayerDamage(collisionDamage)) {
 					debug("Rebel2: COLLISION damage! zone=%d aim=(%d,%d) damage=%d total=%d",
 						i, aimX, aimY, collisionDamage, _playerDamage);
 				}
 				// Visual effect — FUN_00420515 (palette flash)
-				initDamageFlash();
+				if (!_noDamage)
+					initDamageFlash();
 				// TODO: FUN_0041189e sound based on collision direction
 			} else {
 				// Safely passed — award score bonus
@@ -1884,13 +1882,10 @@ void InsaneRebel2::applyHandler7ObstacleHit(const InsaneRebel2::CollisionZone &z
 
 	LevelDifficultyParams params = getDifficultyParams();
 	int collisionDamage = (params.dodgeDamage >= 0) ? params.dodgeDamage : 0;
-	if (!_rebelInvulnerable) {
-		_playerDamage += collisionDamage;
-		if (_playerDamage > 255)
-			_playerDamage = 255;
-	}
+	applyPlayerDamage(collisionDamage);
 	_rebelHitCounter++;
-	initDamageFlash();
+	if (!_noDamage)
+		initDamageFlash();
 	// Pan based on ship X position relative to screen center.
 	playSfx(1, 127, CLIP((_flyShipScreenX - 212) * 127 / 160, -127, 127));
 	debug("Rebel2: Handler7 Mode0/2 OBSTACLE HIT zone=%d ship=(%d,%d) damage=%d",
@@ -1946,12 +1941,10 @@ void InsaneRebel2::checkHandler7ObstacleZones(uint16 &warningMask) {
 
 bool InsaneRebel2::applyHandler7WallDamage(int wallDamage) {
 	if (_hitCooldown < 5 && !_rebelInvulnerable) {
-		_playerDamage += wallDamage;
-		if (_playerDamage > 255)
-			_playerDamage = 255;
+		const bool damageApplied = applyPlayerDamage(wallDamage);
 		_rebelHitCounter++;
 		_hitCooldown = 10;
-		return true;
+		return damageApplied;
 	}
 
 	return false;
@@ -1972,14 +1965,16 @@ void InsaneRebel2::checkHandler7TopBoundary(const InsaneRebel2::CollisionZone &z
 		int16 edgeY = (int16)((_flyShipScreenX - x1) * (y2 - y1) / (x2 - x1) + y1 + vMargin);
 		if (_flyShipScreenY < edgeY) {
 			// Ship above top wall - push down.
-			if (applyHandler7WallDamage(wallDamage)) {
+			const bool damageApplied = applyHandler7WallDamage(wallDamage);
+			if (damageApplied) {
 				debug("Rebel2: Handler7 Mode1/3 TOP WALL ship=(%d,%d) edgeY=%d damage=%d",
 					_flyShipScreenX, _flyShipScreenY, edgeY, wallDamage);
 			}
 			_spaceShotDirection = 2;  // Direction: pushed down
 			_flyShipScreenY = edgeY;  // Push-back
 			playSfx(1, 127, 0);  // CRASH.SAD, top wall -> center pan (always)
-			initDamageFlash();
+			if (!_noDamage)
+				initDamageFlash();
 		} else if (_flyShipScreenY < edgeY + 0x28) {
 			warningMask |= 4;
 		}
@@ -1996,14 +1991,16 @@ void InsaneRebel2::checkHandler7BottomBoundary(const InsaneRebel2::CollisionZone
 		_corridorBottomY = vMargin + edgeY;  // DAT_00443b10 update
 		if (edgeY < _flyShipScreenY) {
 			// Ship below bottom wall - push up.
-			if (applyHandler7WallDamage(wallDamage)) {
+			const bool damageApplied = applyHandler7WallDamage(wallDamage);
+			if (damageApplied) {
 				debug("Rebel2: Handler7 Mode1/3 BOTTOM WALL ship=(%d,%d) edgeY=%d damage=%d",
 					_flyShipScreenX, _flyShipScreenY, edgeY, wallDamage);
 			}
 			_spaceShotDirection = 3;  // Direction: pushed up
 			_flyShipScreenY = edgeY;  // Push-back
 			playSfx(1, 127, 0);  // CRASH.SAD, bottom wall -> center pan (always)
-			initDamageFlash();
+			if (!_noDamage)
+				initDamageFlash();
 		} else if (edgeY - 0x28 < _flyShipScreenY) {
 			warningMask |= 8;
 		}
@@ -2024,13 +2021,15 @@ void InsaneRebel2::checkHandler7LeftBoundary(const InsaneRebel2::CollisionZone &
 			// FUN_40E35E resets horizontal history to force immediate rightward correction.
 			resetHandler7HorizontalVelocity(127);
 
-			if (applyHandler7WallDamage(wallDamage)) {
+			const bool damageApplied = applyHandler7WallDamage(wallDamage);
+			if (damageApplied) {
 				debug("Rebel2: Handler7 Mode1/3 LEFT WALL ship=(%d,%d) edgeX=%d damage=%d",
 					_flyShipScreenX, _flyShipScreenY, edgeX, wallDamage);
 			}
 			_spaceShotDirection = 0;  // Direction: pushed right
 			playSfx(1, 127, -100);  // CRASH.SAD, left wall -> pan left (always)
-			initDamageFlash();
+			if (!_noDamage)
+				initDamageFlash();
 		}
 	}
 }
@@ -2049,13 +2048,15 @@ void InsaneRebel2::checkHandler7RightBoundary(const InsaneRebel2::CollisionZone
 			// FUN_40E35E resets horizontal history to force immediate leftward correction.
 			resetHandler7HorizontalVelocity(-127);
 
-			if (applyHandler7WallDamage(wallDamage)) {
+			const bool damageApplied = applyHandler7WallDamage(wallDamage);
+			if (damageApplied) {
 				debug("Rebel2: Handler7 Mode1/3 RIGHT WALL ship=(%d,%d) edgeX=%d damage=%d",
 					_flyShipScreenX, _flyShipScreenY, edgeX, wallDamage);
 			}
 			_spaceShotDirection = 1;  // Direction: pushed left
 			playSfx(1, 127, 100);  // CRASH.SAD, right wall -> pan right (always)
-			initDamageFlash();
+			if (!_noDamage)
+				initDamageFlash();
 		}
 	}
 }
diff --git a/engines/scumm/metaengine.cpp b/engines/scumm/metaengine.cpp
index 1bd84c7d668..8f899433929 100644
--- a/engines/scumm/metaengine.cpp
+++ b/engines/scumm/metaengine.cpp
@@ -896,6 +896,15 @@ static const ExtraGuiOption enableRebel2UnlockAll = {
 	0
 };
 
+static const ExtraGuiOption enableRebel2NoDamage = {
+	_s("No damage"),
+	_s("Disable player damage"),
+	"rebel2_no_damage",
+	false,
+	0,
+	0
+};
+
 const ExtraGuiOption enableRebel1UnlockAll = {
 	_s("Unlock all levels"),
 	_s("All levels will be available without requiring passwords"),
@@ -952,6 +961,9 @@ const ExtraGuiOptions ScummMetaEngine::getExtraGuiOptions(const Common::String &
 	if (target.empty() || guiOptions.contains(GAMEOPTION_REBEL2_UNLOCK_ALL)) {
 		options.push_back(enableRebel2UnlockAll);
 	}
+	if (target.empty() || guiOptions.contains(GAMEOPTION_REBEL2_NO_DAMAGE)) {
+		options.push_back(enableRebel2NoDamage);
+	}
 	if (target.empty() || guiOptions.contains(GAMEOPTION_REBEL1_UNLOCK_ALL)) {
 		options.push_back(enableRebel1UnlockAll);
 	}
diff --git a/engines/scumm/smush/rebel/smush_player_ra2.cpp b/engines/scumm/smush/rebel/smush_player_ra2.cpp
index b24ea74678c..222b4914574 100644
--- a/engines/scumm/smush/rebel/smush_player_ra2.cpp
+++ b/engines/scumm/smush/rebel/smush_player_ra2.cpp
@@ -45,6 +45,7 @@ namespace Scumm {
 constexpr int kRebel2LoadBufferSize = 400000;
 constexpr int kRebel2GameplaySurfaceWidth = 0x1a8;
 constexpr int kRebel2GameplaySurfaceHeight = 0x104;
+constexpr int kRebel2MusicTrackSize = 800000;
 
 bool isRebel2FullFrameDeltaCodec(int codec) {
 	return codec == SMUSH_CODEC_DELTA_BLOCKS || codec == SMUSH_CODEC_DELTA_GLYPHS;
@@ -96,6 +97,7 @@ void smushDecodeRA2Uncompressed(byte *dst, const byte *src, int left, int top,
 SmushPlayerRebel2::SmushPlayerRebel2(ScummEngine_v7 *scumm, IMuseDigital *imuseDigital, Insane *insane)
 	: SmushPlayer(scumm, imuseDigital, insane) {
 	initGamePlayerFields();
+	ra2InitAudioTrackSizes();
 }
 
 SmushPlayerRebel2::~SmushPlayerRebel2() {
@@ -157,6 +159,23 @@ void SmushPlayerRebel2::destroyGamePlayerFields() {
 	_loadBuffer = nullptr;
 }
 
+void SmushPlayerRebel2::ra2InitAudioTrackSizes() {
+	const int musicTrack = SMUSH_MAX_TRACKS - 1;
+	if (_smushNumTracks <= musicTrack || _smushTracks[musicTrack].blockSize >= kRebel2MusicTrackSize)
+		return;
+
+	uint8 *blockPtr = (uint8 *)realloc(_smushTracks[musicTrack].blockPtr, kRebel2MusicTrackSize);
+	if (!blockPtr) {
+		warning("SmushPlayerRebel2::ra2InitAudioTrackSizes: failed to allocate %d-byte music track",
+			kRebel2MusicTrackSize);
+		return;
+	}
+
+	_smushTracks[musicTrack].blockPtr = blockPtr;
+	_smushTracks[musicTrack].blockSize = kRebel2MusicTrackSize;
+	memset(_smushTracks[musicTrack].blockPtr, 127, _smushTracks[musicTrack].blockSize);
+}
+
 /**
  * RA2-specific initialization in SmushPlayer::init().
  * Re-pushes the SMUSH palette for videos that inherit it from the previous video,
diff --git a/engines/scumm/smush/rebel/smush_player_ra2.h b/engines/scumm/smush/rebel/smush_player_ra2.h
index ac4700919e8..81cb8ea62dd 100644
--- a/engines/scumm/smush/rebel/smush_player_ra2.h
+++ b/engines/scumm/smush/rebel/smush_player_ra2.h
@@ -75,6 +75,7 @@ private:
 	void ra2StoreFobjData(int codec, const byte *data, int32 dataSize,
 						  int left, int top, int width, int height);
 	void ra2HandleGost(int32 subSize, Common::SeekableReadStream &b);
+	void ra2InitAudioTrackSizes();
 
 	// LOAD chunk streaming buffer (embedded resource data)
 	byte *_loadBuffer;


Commit: 61d84074f729396526b43868bd5ae90796e70922
    https://github.com/scummvm/scummvm/commit/61d84074f729396526b43868bd5ae90796e70922
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-07T23:07:40+02:00

Commit Message:
SCUMM: RA1: make sure sound buffer is large enough

Changed paths:
    engines/scumm/smush/rebel/smush_player_ra1.cpp
    engines/scumm/smush/rebel/smush_player_ra1.h


diff --git a/engines/scumm/smush/rebel/smush_player_ra1.cpp b/engines/scumm/smush/rebel/smush_player_ra1.cpp
index 694e947c881..55667d15056 100644
--- a/engines/scumm/smush/rebel/smush_player_ra1.cpp
+++ b/engines/scumm/smush/rebel/smush_player_ra1.cpp
@@ -47,7 +47,8 @@ enum {
 	kRA1PresentationScreenWidth = 320,
 	kRA1PresentationScreenHeight = 200,
 	kRA1PresentationWidth = kRA1PresentationScreenWidth - kRA1PresentationBorder * 2,
-	kRA1PresentationHeight = kRA1PresentationScreenHeight - kRA1PresentationBorder * 2
+	kRA1PresentationHeight = kRA1PresentationScreenHeight - kRA1PresentationBorder * 2,
+	kRebel1LongAudioTrackSize = 500000
 };
 
 static void ra1ApplyCenteredFetchPlacement(InsaneRebel1 *rebel1, int width, int height, int &left, int &top) {
@@ -127,6 +128,7 @@ static void ra1RememberDisplayedFrame(byte *&buffer, int32 &bufferSize, int &sto
 SmushPlayerRebel1::SmushPlayerRebel1(ScummEngine_v7 *scumm, IMuseDigital *imuseDigital, Insane *insane)
 	: SmushPlayer(scumm, imuseDigital, insane) {
 	initGamePlayerFields();
+	ra1InitAudioTrackSizes();
 }
 
 SmushPlayerRebel1::~SmushPlayerRebel1() {
@@ -173,6 +175,23 @@ void SmushPlayerRebel1::destroyGamePlayerFields() {
 	_ra1FadeFrameSize = 0;
 }
 
+void SmushPlayerRebel1::ra1InitAudioTrackSizes() {
+	const int longAudioTrack = SMUSH_MAX_TRACKS - 1;
+	if (_smushNumTracks <= longAudioTrack || _smushTracks[longAudioTrack].blockSize >= kRebel1LongAudioTrackSize)
+		return;
+
+	uint8 *blockPtr = (uint8 *)realloc(_smushTracks[longAudioTrack].blockPtr, kRebel1LongAudioTrackSize);
+	if (!blockPtr) {
+		warning("SmushPlayerRebel1::ra1InitAudioTrackSizes: failed to allocate %d-byte long audio track",
+			kRebel1LongAudioTrackSize);
+		return;
+	}
+
+	_smushTracks[longAudioTrack].blockPtr = blockPtr;
+	_smushTracks[longAudioTrack].blockSize = kRebel1LongAudioTrackSize;
+	memset(_smushTracks[longAudioTrack].blockPtr, 127, _smushTracks[longAudioTrack].blockSize);
+}
+
 void SmushPlayerRebel1::resetGameVideoState() {
 	_ra1HasCleanFrame = false;
 	free(_ra1ObjOverlayData);
diff --git a/engines/scumm/smush/rebel/smush_player_ra1.h b/engines/scumm/smush/rebel/smush_player_ra1.h
index 95ec9485179..65570b04539 100644
--- a/engines/scumm/smush/rebel/smush_player_ra1.h
+++ b/engines/scumm/smush/rebel/smush_player_ra1.h
@@ -71,6 +71,7 @@ private:
 	bool ra1HandleUnknownFrameChunk(uint32 subType, int32 subSize);
 	bool ra1DispatchFrameChunk(uint32 subType, int32 subSize, int32 &frameSize,
 		Common::SeekableReadStream &b, bool fastForwarding);
+	void ra1InitAudioTrackSizes();
 
 	// RA1 clean frame buffer for delta source restoration
 	byte *_ra1CleanFrame;




More information about the Scummvm-git-logs mailing list