[Scummvm-git-logs] scummvm master -> 73d44af9ba7286c489835f201ff3372972fcc21c

neuromancer noreply at scummvm.org
Thu Jun 11 13:12:17 UTC 2026


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

Summary:
54c2011ec5 FREESCAPE: trigger gamepad in ios only when gameplay starts
49286628a1 FREESCAPE: allow to skip screen or select character when touchpad is used
fc6aa9c014 SCUMM RA1: do not skip cutscene with fire button in gamepad
7e7a5d6ad9 SCUMM RA1: fixed game logic in L12
7cec74da68 SCUMM RA1: keep different volume settings on-sync
7769cde6dd SCUMM RA2: fixed crash at the end of L6
73d44af9ba SCUMM RA2: fixed invalid palette on gameplay when high resolution is used


Commit: 54c2011ec5f6330c283662d79532a1a350f31feb
    https://github.com/scummvm/scummvm/commit/54c2011ec5f6330c283662d79532a1a350f31feb
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-11T15:11:52+02:00

Commit Message:
FREESCAPE: trigger gamepad in ios only when gameplay starts

Changed paths:
    engines/freescape/freescape.cpp
    engines/freescape/freescape.h


diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 7273128bedf..100e95c826f 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -39,6 +39,36 @@ namespace Freescape {
 
 FreescapeEngine *g_freescape;
 
+#ifdef IPHONE
+static const char *const kIOSGamepadControllerKey = "gamepad_controller";
+static const char *const kIOSGamepadControllerMinimalLayoutKey = "gamepad_controller_minimal_layout";
+static const char *const kIOSGamepadControllerDirectionalInputKey = "gamepad_controller_directional_input";
+static const int kIOSGamepadControllerDirectionalInputDpad = 1;
+
+static void clearIOSGamepadControllerSetting(FreescapeEngine::IOSGamepadControllerSetting &setting) {
+	setting.present = false;
+	setting.value.clear();
+}
+
+static void saveIOSGamepadControllerSetting(FreescapeEngine::IOSGamepadControllerSetting &setting,
+		const Common::ConfigManager::Domain *domain, const char *key) {
+	setting.present = domain && domain->contains(key);
+	setting.value = setting.present ? domain->getVal(key) : Common::String();
+}
+
+static void restoreIOSGamepadControllerSettingValue(const FreescapeEngine::IOSGamepadControllerSetting &setting,
+		const Common::String &domainName, const char *key) {
+	Common::ConfigManager::Domain *domain = ConfMan.getDomain(domainName);
+	if (!domain)
+		return;
+
+	if (setting.present)
+		ConfMan.set(key, setting.value, domainName);
+	else if (domain->contains(key))
+		ConfMan.removeKey(key, domainName);
+}
+#endif
+
 bool isEncodedCPCDirectColor(uint8 index) {
 	return index >= 64 && index < 96;
 }
@@ -285,13 +315,11 @@ FreescapeEngine::FreescapeEngine(OSystem *syst, const ADGameDescription *gd)
 	_gameStateBits = 0;
 	_eventManager = new EventManagerWrapper(g_system->getEventManager());
 
-	// Workaround to make the game playable on iOS: remove when there
-	// is a better way to hint the best controls
 #ifdef IPHONE
-	const Common::String &gameDomain = ConfMan.getActiveDomainName();
-	ConfMan.setBool("gamepad_controller", true, gameDomain);
-	ConfMan.setBool("gamepad_controller_minimal_layout", true, gameDomain);
-	ConfMan.setInt("gamepad_controller_directional_input", 1 /* kDirectionalInputDpad */, gameDomain);
+	_iosGamepadControllerSettingsSaved = false;
+	clearIOSGamepadControllerSetting(_iosGamepadController);
+	clearIOSGamepadControllerSetting(_iosGamepadControllerMinimalLayout);
+	clearIOSGamepadControllerSetting(_iosGamepadControllerDirectionalInput);
 #endif
 	g_freescape = this;
 	g_debugger = new Debugger(g_freescape);
@@ -302,7 +330,55 @@ bool FreescapeEngine::isTouchscreenActive() const {
 	return _debugSimulateTouchscreen || g_system->hasFeature(OSystem::kFeatureTouchscreen);
 }
 
+void FreescapeEngine::setIOSGamepadControllerEnabled(bool enabled) {
+#ifdef IPHONE
+	if (!_iosGamepadControllerSettingsSaved) {
+		_iosGamepadControllerDomain = ConfMan.getActiveDomainName();
+		if (_iosGamepadControllerDomain.empty())
+			return;
+
+		const Common::ConfigManager::Domain *domain = ConfMan.getDomain(_iosGamepadControllerDomain);
+		saveIOSGamepadControllerSetting(_iosGamepadController, domain, kIOSGamepadControllerKey);
+		saveIOSGamepadControllerSetting(_iosGamepadControllerMinimalLayout, domain, kIOSGamepadControllerMinimalLayoutKey);
+		saveIOSGamepadControllerSetting(_iosGamepadControllerDirectionalInput, domain, kIOSGamepadControllerDirectionalInputKey);
+		_iosGamepadControllerSettingsSaved = true;
+	}
+
+	if (_iosGamepadControllerDomain.empty())
+		return;
+
+	ConfMan.setBool(kIOSGamepadControllerKey, enabled, _iosGamepadControllerDomain);
+	if (enabled) {
+		ConfMan.setBool(kIOSGamepadControllerMinimalLayoutKey, true, _iosGamepadControllerDomain);
+		ConfMan.setInt(kIOSGamepadControllerDirectionalInputKey, kIOSGamepadControllerDirectionalInputDpad, _iosGamepadControllerDomain);
+	}
+	g_system->applyBackendSettings();
+#else
+	(void)enabled;
+#endif
+}
+
+void FreescapeEngine::restoreIOSGamepadControllerSettings() {
+#ifdef IPHONE
+	if (!_iosGamepadControllerSettingsSaved)
+		return;
+
+	restoreIOSGamepadControllerSettingValue(_iosGamepadController, _iosGamepadControllerDomain, kIOSGamepadControllerKey);
+	restoreIOSGamepadControllerSettingValue(_iosGamepadControllerMinimalLayout, _iosGamepadControllerDomain, kIOSGamepadControllerMinimalLayoutKey);
+	restoreIOSGamepadControllerSettingValue(_iosGamepadControllerDirectionalInput, _iosGamepadControllerDomain, kIOSGamepadControllerDirectionalInputKey);
+	g_system->applyBackendSettings();
+
+	clearIOSGamepadControllerSetting(_iosGamepadController);
+	clearIOSGamepadControllerSetting(_iosGamepadControllerMinimalLayout);
+	clearIOSGamepadControllerSetting(_iosGamepadControllerDirectionalInput);
+	_iosGamepadControllerDomain.clear();
+	_iosGamepadControllerSettingsSaved = false;
+#endif
+}
+
 FreescapeEngine::~FreescapeEngine() {
+	restoreIOSGamepadControllerSettings();
+
 	removeTimers();
 	delete _rnd;
 
@@ -1082,6 +1158,7 @@ void FreescapeEngine::beforeStarting() {}
 
 Common::Error FreescapeEngine::run() {
 	_vsyncEnabled = g_system->getFeatureState(OSystem::kFeatureVSync);
+	setIOSGamepadControllerEnabled(false);
 	_frameLimiter = new Graphics::FrameLimiter(g_system, ConfMan.getInt("engine_speed"));
 	// Initialize graphics
 	//_screenW = g_system->getWidth();
@@ -1093,8 +1170,10 @@ Common::Error FreescapeEngine::run() {
 
 	// The following error code will force return to launcher
 	// but it will not force any other GUI message to be displayed
-	if (!_gfx)
+	if (!_gfx) {
+		restoreIOSGamepadControllerSettings();
 		return Common::kUserCanceled;
+	}
 
 	_gfx->init();
 
@@ -1136,6 +1215,7 @@ Common::Error FreescapeEngine::run() {
 			debugC(1, kFreescapeDebugMove, "Starting area %d", _currentArea->getAreaID());
 			beforeStarting();
 			_gameStateControl = kFreescapeGameStatePlaying;
+			setIOSGamepadControllerEnabled(true);
 		} else if (_gameStateControl == kFreescapeGameStateEnd)
 			endGame();
 
@@ -1174,6 +1254,7 @@ Common::Error FreescapeEngine::run() {
 	_eventManager->clearExitEvents();
 	CursorMan.showMouse(true);
 	g_system->lockMouse(false);
+	restoreIOSGamepadControllerSettings();
 	return Common::kNoError;
 }
 
@@ -1469,6 +1550,7 @@ Common::Error FreescapeEngine::loadGameStream(Common::SeekableReadStream *stream
 	}
 	assert(_playerHeight > 0);
 	_gameStateControl = kFreescapeGameStatePlaying;
+	setIOSGamepadControllerEnabled(true);
 	return loadGameStreamExtended(stream);
 }
 
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 7aabd4adf40..f17fe4fad25 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -369,6 +369,19 @@ public:
 	bool _useWASDControls;
 	bool _debugSimulateTouchscreen;
 	bool isTouchscreenActive() const;
+	void setIOSGamepadControllerEnabled(bool enabled);
+	void restoreIOSGamepadControllerSettings();
+#ifdef IPHONE
+	struct IOSGamepadControllerSetting {
+		bool present;
+		Common::String value;
+	};
+	bool _iosGamepadControllerSettingsSaved;
+	Common::String _iosGamepadControllerDomain;
+	IOSGamepadControllerSetting _iosGamepadController;
+	IOSGamepadControllerSetting _iosGamepadControllerMinimalLayout;
+	IOSGamepadControllerSetting _iosGamepadControllerDirectionalInput;
+#endif
 	// Player movement state
 	bool _moveForward;
 	bool _moveBackward;


Commit: 49286628a198fce090539ab6a0244c234d094f94
    https://github.com/scummvm/scummvm/commit/49286628a198fce090539ab6a0244c234d094f94
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-11T15:11:53+02:00

Commit Message:
FREESCAPE: allow to skip screen or select character when touchpad is used

Changed paths:
    engines/freescape/games/castle/amiga.cpp
    engines/freescape/games/castle/castle.cpp
    engines/freescape/games/dark/dark.cpp
    engines/freescape/games/eclipse/eclipse.cpp


diff --git a/engines/freescape/games/castle/amiga.cpp b/engines/freescape/games/castle/amiga.cpp
index 820a9ff2579..57011e8647b 100644
--- a/engines/freescape/games/castle/amiga.cpp
+++ b/engines/freescape/games/castle/amiga.cpp
@@ -998,8 +998,8 @@ private:
 			case Common::EVENT_LBUTTONDOWN:
 			case Common::EVENT_RBUTTONDOWN:
 				if (acceptSelection) {
-					int mouseX = kWidth * event.mouse.x / g_system->getWidth();
-					key = mouseX < selectionSplitX() ? 1 : 2;
+					Common::Point mouse = _engine->getNormalizedPosition(event.mouse);
+					key = mouse.x < selectionSplitX() ? 1 : 2;
 				} else if (acceptAnyKey) {
 					key = 3;
 				}
diff --git a/engines/freescape/games/castle/castle.cpp b/engines/freescape/games/castle/castle.cpp
index c410ad12703..01cab328349 100644
--- a/engines/freescape/games/castle/castle.cpp
+++ b/engines/freescape/games/castle/castle.cpp
@@ -2211,6 +2211,7 @@ void CastleEngine::selectCharacterScreen() {
 	// lines[5] = prince, lines[6] = princess for 8-bit text menus.
 	// For DOS, use riddle text line positions.
 	Common::Rect princeSelector, princessSelector;
+	Common::Rect princeHitArea, princessHitArea;
 	if (isSpectrum() || isCPC() || isC64() || isAmiga()) {
 		int x = _viewArea.left + 3;
 		int lineHeight = 12; // Castle Master line spacing in drawStringsInSurface
@@ -2225,6 +2226,8 @@ void CastleEngine::selectCharacterScreen() {
 			princeSelector = Common::Rect(x, princeY, x + selectorWidth, princeY + lineHeight);
 			princessSelector = Common::Rect(x, princessY, x + selectorWidth, princessY + lineHeight);
 		}
+		princeHitArea = Common::Rect(_viewArea.left, princeY, _viewArea.right, princeY + lineHeight);
+		princessHitArea = Common::Rect(_viewArea.left, princessY, _viewArea.right, princessY + lineHeight);
 	} else {
 		// DOS: text comes from _riddleList[21], calculate from actual riddle line positions
 		Common::Array<RiddleText> selectMessage = _riddleList[21]._lines;
@@ -2237,6 +2240,9 @@ void CastleEngine::selectCharacterScreen() {
 			else if (i == int(selectMessage.size()) - 1)
 				princessSelector = _font.getBoundingBox(selectMessage[i]._text, x, y);
 		}
+		int splitX = _fullscreenViewArea.left + _fullscreenViewArea.width() / 2;
+		princeHitArea = Common::Rect(_fullscreenViewArea.left, _fullscreenViewArea.top, splitX, _fullscreenViewArea.bottom);
+		princessHitArea = Common::Rect(splitX, _fullscreenViewArea.top, _fullscreenViewArea.right, _fullscreenViewArea.bottom);
 	}
 
 	// On touchscreen, highlight the tap areas with red outlines (expand 1px for readability)
@@ -2263,13 +2269,12 @@ void CastleEngine::selectCharacterScreen() {
 			case Common::EVENT_LBUTTONDOWN:
 				// fallthrough
 			case Common::EVENT_RBUTTONDOWN:
-				mouse.x = _screenW * event.mouse.x / g_system->getWidth();
-				mouse.y = _screenH * event.mouse.y / g_system->getHeight();
+				mouse = getNormalizedPosition(event.mouse);
 
-				if (princeSelector.contains(mouse)) {
+				if (princeHitArea.contains(mouse) || princeSelector.contains(mouse)) {
 					selected = true;
 					_selectedPrincess = false;
-				} else if (princessSelector.contains(mouse)) {
+				} else if (princessHitArea.contains(mouse) || princessSelector.contains(mouse)) {
 					selected = true;
 					_selectedPrincess = true;
 				}
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index e38695c5419..5b617b97d2b 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -1125,6 +1125,12 @@ void DarkEngine::drawInfoMenu() {
 			case Common::EVENT_SCREEN_CHANGED:
 				_gfx->computeScreenViewport();
 				break;
+			case Common::EVENT_RBUTTONDOWN:
+			// fallthrough
+			case Common::EVENT_LBUTTONDOWN:
+				if (isTouchscreenActive())
+					cont = false;
+				break;
 
 			default:
 				break;
diff --git a/engines/freescape/games/eclipse/eclipse.cpp b/engines/freescape/games/eclipse/eclipse.cpp
index 95c756865f8..57b2465bdbd 100644
--- a/engines/freescape/games/eclipse/eclipse.cpp
+++ b/engines/freescape/games/eclipse/eclipse.cpp
@@ -623,6 +623,12 @@ void EclipseEngine::drawInfoMenu() {
 			case Common::EVENT_SCREEN_CHANGED:
 				_gfx->computeScreenViewport();
 				break;
+			case Common::EVENT_RBUTTONDOWN:
+			// fallthrough
+			case Common::EVENT_LBUTTONDOWN:
+				if (isTouchscreenActive())
+					cont = false;
+				break;
 
 			default:
 				break;


Commit: fc6aa9c0149d3de550f1d2a2eb8abb26dd171902
    https://github.com/scummvm/scummvm/commit/fc6aa9c0149d3de550f1d2a2eb8abb26dd171902
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-11T15:11:53+02:00

Commit Message:
SCUMM RA1: do not skip cutscene with fire button in gamepad

Changed paths:
    engines/scumm/insane/rebel1/menu.cpp


diff --git a/engines/scumm/insane/rebel1/menu.cpp b/engines/scumm/insane/rebel1/menu.cpp
index 60fc7bdd138..da9adbc3a03 100644
--- a/engines/scumm/insane/rebel1/menu.cpp
+++ b/engines/scumm/insane/rebel1/menu.cpp
@@ -686,7 +686,7 @@ bool InsaneRebel1::notifyEvent(const Common::Event &event) {
 		return false;
 
 	if (isTouchscreenActive() && !_interactiveVideoActive && !_menuActive &&
-			(event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_LBUTTONUP)) {
+			event.type == Common::EVENT_LBUTTONDOWN) {
 		_vm->_smushVideoShouldFinish = true;
 		return true;
 	}
@@ -875,9 +875,7 @@ bool InsaneRebel1::notifyEvent(const Common::Event &event) {
 		}
 
 		if (isTouchscreenActive() && !_interactiveVideoActive && !_menuActive && pressed &&
-				(event.customType == kScummActionInsaneAttack ||
-				 event.customType == kScummActionInsaneSwitch ||
-				 event.customType == kScummActionInsaneSkip)) {
+				event.customType == kScummActionInsaneSkip) {
 			_vm->_smushVideoShouldFinish = true;
 			return true;
 		}


Commit: 7e7a5d6ad97d13c55b56195d6dd4b4d1be164783
    https://github.com/scummvm/scummvm/commit/7e7a5d6ad97d13c55b56195d6dd4b4d1be164783
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-11T15:11:53+02:00

Commit Message:
SCUMM RA1: fixed game logic in L12

Changed paths:
    engines/scumm/insane/rebel1/iact.cpp


diff --git a/engines/scumm/insane/rebel1/iact.cpp b/engines/scumm/insane/rebel1/iact.cpp
index 0c34182fe5a..92c798a81f0 100644
--- a/engines/scumm/insane/rebel1/iact.cpp
+++ b/engines/scumm/insane/rebel1/iact.cpp
@@ -97,6 +97,9 @@ const int16 kOnFootCursorMinX = 0;
 const int16 kOnFootCursorMaxX = 319;
 const int16 kOnFootCursorMinY = 0;
 const int16 kOnFootCursorMaxY = 199;
+const int16 kRA1Level12TargetA = 195;
+const int16 kRA1Level12TargetB = 197;
+const int16 kRA1Level12TargetC = 199;
 
 // Level 15 final approach 0x5D damage/event codes consumed by
 // RunLevel1GameLoop. The latch stores the raw GAME parameter; no translation is
@@ -1763,22 +1766,22 @@ void InsaneRebel1::updateGameOp0BPhysics() {
 	_frameCounter++;
 
 	if (_currentLevel == 11) {
-		// RunLevel12Flow checks DAT_761A bits 0x20, 0x08, and 0x02 at frame
-		// 0x550. These map to destroyed object IDs 211, 213, and 215 in the
-		// port's one-based frame-object helper. On failure the original keeps
+		// RunLevel12Flow checks the three attackers around frame 0x550. The
+		// event-mask bits map to L12PLAY's one-based FOBJ IDs 195, 197, and 199
+		// in the port's frame-object helper. On failure the original keeps
 		// pumping L12PLAY until frame 0x564, plays L12RETRY, then restarts
 		// L12PLAY without resetting health.
 		if (_levelGameplayPhase == 0 && _frameCounter == 0x550) {
-			const bool target211Destroyed = isFrameObjectPrimarySet(211);
-			const bool target213Destroyed = isFrameObjectPrimarySet(213);
-			const bool target215Destroyed = isFrameObjectPrimarySet(215);
-			if (!target211Destroyed || !target213Destroyed || !target215Destroyed) {
+			const bool targetADestroyed = isFrameObjectPrimarySet(kRA1Level12TargetA);
+			const bool targetBDestroyed = isFrameObjectPrimarySet(kRA1Level12TargetB);
+			const bool targetCDestroyed = isFrameObjectPrimarySet(kRA1Level12TargetC);
+			if (!targetADestroyed || !targetBDestroyed || !targetCDestroyed) {
 				_levelGameplayPhase = 1;
 				debugC(DEBUG_INSANE, "L12 retry armed: frame=0x%04x targets=(%d,%d,%d)",
 					_frameCounter,
-					target211Destroyed ? 1 : 0,
-					target213Destroyed ? 1 : 0,
-					target215Destroyed ? 1 : 0);
+					targetADestroyed ? 1 : 0,
+					targetBDestroyed ? 1 : 0,
+					targetCDestroyed ? 1 : 0);
 			}
 		}
 		if (_levelGameplayPhase == 1 && _frameCounter >= 0x564)


Commit: 7cec74da68d256115f2109a7a35fc15d00a91c26
    https://github.com/scummvm/scummvm/commit/7cec74da68d256115f2109a7a35fc15d00a91c26
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-11T15:11:53+02:00

Commit Message:
SCUMM RA1: keep different volume settings on-sync

Changed paths:
    engines/scumm/insane/rebel1/audio.cpp
    engines/scumm/insane/rebel1/menu.cpp
    engines/scumm/scumm.cpp


diff --git a/engines/scumm/insane/rebel1/audio.cpp b/engines/scumm/insane/rebel1/audio.cpp
index 95643e67f17..482a764db67 100644
--- a/engines/scumm/insane/rebel1/audio.cpp
+++ b/engines/scumm/insane/rebel1/audio.cpp
@@ -19,6 +19,7 @@
  *
  */
 
+#include "common/config-manager.h"
 #include "common/system.h"
 
 #include "scumm/file.h"
@@ -68,6 +69,16 @@ void InsaneRebel1::processAudioFrame(int16 feedSize) {
 }
 
 void InsaneRebel1::applyAudioOptions() {
+	const int musicVolume = ConfMan.getInt("music_volume");
+	const int sfxVolume = ConfMan.getInt("sfx_volume");
+	const int speechVolume = ConfMan.getInt("speech_volume");
+
+	_optVolume = CLIP<int>(musicVolume / 2, 0, 127);
+
+	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, musicVolume);
+	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, sfxVolume);
+	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, speechVolume);
+
 	_vm->_mixer->muteSoundType(Audio::Mixer::kMusicSoundType, !_optMusicEnabled);
 	_vm->_mixer->muteSoundType(Audio::Mixer::kSFXSoundType, !_optSfxEnabled);
 	_vm->_mixer->muteSoundType(Audio::Mixer::kSpeechSoundType, !_optSfxEnabled);
diff --git a/engines/scumm/insane/rebel1/menu.cpp b/engines/scumm/insane/rebel1/menu.cpp
index da9adbc3a03..cfa683a1f60 100644
--- a/engines/scumm/insane/rebel1/menu.cpp
+++ b/engines/scumm/insane/rebel1/menu.cpp
@@ -504,12 +504,16 @@ bool InsaneRebel1::handleMenuCommand(RA1MenuCommand command) {
 			_optionsSel = (_optionsSel + 1) % kOptionsItemCount;
 			return true;
 		case kRA1MenuCommandLeft:
-			if (_optionsSel == 7)
+			if (_optionsSel == 7) {
 				setRebel1Volume(_vm, _optVolume, -5);
+				applyAudioOptions();
+			}
 			return true;
 		case kRA1MenuCommandRight:
-			if (_optionsSel == 7)
+			if (_optionsSel == 7) {
 				setRebel1Volume(_vm, _optVolume, 5);
+				applyAudioOptions();
+			}
 			return true;
 		case kRA1MenuCommandCancel:
 			_optionsSel = 0;
@@ -1037,6 +1041,7 @@ void InsaneRebel1::renderHighScoresOverlay(byte *dst, int pitch, int width, int
 void InsaneRebel1::renderOptionsOverlay(byte *dst, int pitch, int width, int height) {
 	// --- Options submenu (matching original RunGameOptionsMenu) ---
 	_optTextEnabled = ConfMan.getBool("subtitles");
+	_optVolume = CLIP<int>(ConfMan.getInt("music_volume") / 2, 0, 127);
 
 	const char *kDiffNames[3] = { "EASY", "NORMAL", "HARD" };
 
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index ba18b97a5bf..f0bb1a53d36 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2696,6 +2696,14 @@ void ScummEngine_v7::syncSoundSettings() {
 		_imuseDigital->diMUSESetMusicGroupVol(ConfMan.getInt("music_volume") / 2);
 		_imuseDigital->diMUSESetVoiceGroupVol(ConfMan.getInt("speech_volume") / 2);
 		_imuseDigital->diMUSESetSFXGroupVol(ConfMan.getInt("sfx_volume") / 2);
+	} else if (_game.id == GID_REBEL1) {
+		const int musicVolume = ConfMan.getInt("music_volume");
+		const int sfxVolume = ConfMan.getInt("sfx_volume");
+		const int speechVolume = ConfMan.getInt("speech_volume");
+
+		_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, musicVolume);
+		_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, sfxVolume);
+		_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, speechVolume);
 	}
 }
 #endif


Commit: 7769cde6dd2e4bf1d2606a1c440ad3f23cecd9cc
    https://github.com/scummvm/scummvm/commit/7769cde6dd2e4bf1d2606a1c440ad3f23cecd9cc
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-11T15:11:53+02:00

Commit Message:
SCUMM RA2: fixed crash at the end of L6

Changed paths:
    engines/scumm/smush/rebel/smush_multi_font.cpp
    engines/scumm/smush/rebel/smush_multi_font.h
    engines/scumm/smush/rebel/smush_player_ra2.cpp


diff --git a/engines/scumm/smush/rebel/smush_multi_font.cpp b/engines/scumm/smush/rebel/smush_multi_font.cpp
index 47193e58a6e..88b5bd30b46 100644
--- a/engines/scumm/smush/rebel/smush_multi_font.cpp
+++ b/engines/scumm/smush/rebel/smush_multi_font.cpp
@@ -91,14 +91,18 @@ void SmushMultiFont::drawString(const char *str, byte *buffer, Common::Rect &cli
 }
 
 void SmushMultiFont::drawStringWrap(const char *str, byte *buffer, Common::Rect &clipRect, int x, int y, int16 col, TextStyleFlags flags) {
+	drawStringWrap(str, buffer, clipRect, x, y, _vm->_screenWidth, col, flags);
+}
+
+void SmushMultiFont::drawStringWrap(const char *str, byte *buffer, Common::Rect &clipRect, int x, int y, int pitch, int16 col, TextStyleFlags flags) {
 	// Reset to default font before drawing
 	_currentFont = _defaultFont;
 	if (_vm->_game.id == GID_REBEL2) {
 		Rebel2FontSet fontSet = getRebel2FontSet();
-		drawRebel2StringWrap(fontSet, str, strlen(str), buffer, clipRect, x, y, _vm->_screenWidth, col, flags);
+		drawRebel2StringWrap(fontSet, str, strlen(str), buffer, clipRect, x, y, pitch, col, flags);
 		return;
 	}
-	_textRenderer->drawStringWrap(str, buffer, clipRect, x, y, _vm->_screenWidth, col, flags);
+	_textRenderer->drawStringWrap(str, buffer, clipRect, x, y, pitch, col, flags);
 }
 
 int SmushMultiFont::draw2byte(byte *buffer, Common::Rect &clipRect, int x, int y, int pitch, int16 col, uint16 chr) {
diff --git a/engines/scumm/smush/rebel/smush_multi_font.h b/engines/scumm/smush/rebel/smush_multi_font.h
index 1f7fba58487..88e5a72b5d7 100644
--- a/engines/scumm/smush/rebel/smush_multi_font.h
+++ b/engines/scumm/smush/rebel/smush_multi_font.h
@@ -55,6 +55,7 @@ public:
 	void drawString(const char *str, byte *buffer, Common::Rect &clipRect, int x, int y, int16 col, TextStyleFlags flags);
 	void drawString(const char *str, byte *buffer, Common::Rect &clipRect, int x, int y, int pitch, int16 col, TextStyleFlags flags);
 	void drawStringWrap(const char *str, byte *buffer, Common::Rect &clipRect, int x, int y, int16 col, TextStyleFlags flags);
+	void drawStringWrap(const char *str, byte *buffer, Common::Rect &clipRect, int x, int y, int pitch, int16 col, TextStyleFlags flags);
 
 	// GlyphRenderer_v7 interface
 	int draw2byte(byte *buffer, Common::Rect &clipRect, int x, int y, int pitch, int16 col, uint16 chr) override;
diff --git a/engines/scumm/smush/rebel/smush_player_ra2.cpp b/engines/scumm/smush/rebel/smush_player_ra2.cpp
index dabef54a36e..8369dacbd63 100644
--- a/engines/scumm/smush/rebel/smush_player_ra2.cpp
+++ b/engines/scumm/smush/rebel/smush_player_ra2.cpp
@@ -841,10 +841,10 @@ void SmushPlayerRebel2::ra2HandleTextResource(const char *str, int fontId, int c
 
 	if (flg & kStyleWordWrap) {
 		Common::Rect clipRect(MAX<int>(0, left), MAX<int>(0, top), MIN<int>(left + width, _width), MIN<int>(top + height, _height));
-		_multiFont->drawStringWrap(str, _dst, clipRect, pos_x, pos_y, color, flg);
+		_multiFont->drawStringWrap(str, _dst, clipRect, pos_x, pos_y, _width, color, flg);
 	} else {
 		Common::Rect clipRect(0, 0, _width, _height);
-		_multiFont->drawString(str, _dst, clipRect, pos_x, pos_y, color, flg);
+		_multiFont->drawString(str, _dst, clipRect, pos_x, pos_y, _width, color, flg);
 	}
 }
 


Commit: 73d44af9ba7286c489835f201ff3372972fcc21c
    https://github.com/scummvm/scummvm/commit/73d44af9ba7286c489835f201ff3372972fcc21c
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-11T15:11:53+02:00

Commit Message:
SCUMM RA2: fixed invalid palette on gameplay when high resolution is used

Changed paths:
    engines/scumm/smush/rebel/smush_player_ra2.cpp


diff --git a/engines/scumm/smush/rebel/smush_player_ra2.cpp b/engines/scumm/smush/rebel/smush_player_ra2.cpp
index 8369dacbd63..1dec1a12192 100644
--- a/engines/scumm/smush/rebel/smush_player_ra2.cpp
+++ b/engines/scumm/smush/rebel/smush_player_ra2.cpp
@@ -869,7 +869,18 @@ bool SmushPlayerRebel2::ra2SelectFrameBuffer(int codec, int width, int height) {
 	if (codec == SMUSH_CODEC_RA2_BOMP) {
 		const bool highRes = ra2IsHighResMode();
 		const bool gameplayActive = isRebel2GameplayActive(_insane);
-		if (highRes && (!gameplayActive || !_ra2UsingGameplaySurface || _specialBuffer == nullptr)) {
+		const int64 currentSurfaceSize64 = (int64)_width * _height;
+		if (highRes && gameplayActive &&
+				_dst == _specialBuffer && _specialBuffer != nullptr &&
+				_width > 320 && _height > 200 &&
+				currentSurfaceSize64 > 0 && currentSurfaceSize64 <= _specialBufferSize) {
+			if (_ra2NativeFrameNeedsClear) {
+				ra2ClearCurrentTarget();
+				_ra2NativeFrameNeedsClear = false;
+			}
+			debugC(DEBUG_SMUSH, "SmushPlayerRebel2::ra2SelectFrameBuffer: Using current _specialBuffer %dx%d for high-res codec 45 mask",
+				_width, _height);
+		} else if (highRes && (!gameplayActive || !_ra2UsingGameplaySurface || _specialBuffer == nullptr)) {
 			if (!ra2EnsureLowResVideoBuffer())
 				return false;
 			_dst = _ra2LowResVideoBuffer;
@@ -946,6 +957,21 @@ bool SmushPlayerRebel2::ra2SelectFrameBuffer(int codec, int width, int height) {
 		surfaceHeight = MAX(surfaceHeight, _ra2FrameObjectSurfaceHeight);
 	}
 
+	const int64 currentSurfaceSize64 = (int64)_width * _height;
+	if (highRes && gameplayActive && !useGameplaySurface && !oversizedNative &&
+			width > 0 && height > 0 &&
+			_dst == _specialBuffer && _specialBuffer != nullptr &&
+			_width > 320 && _height > 200 &&
+			currentSurfaceSize64 > 0 && currentSurfaceSize64 <= _specialBufferSize) {
+		if (_ra2NativeFrameNeedsClear) {
+			ra2ClearCurrentTarget();
+			_ra2NativeFrameNeedsClear = false;
+		}
+		debugC(DEBUG_SMUSH, "SmushPlayerRebel2::ra2SelectFrameBuffer: Using current _specialBuffer %dx%d for high-res gameplay FOBJ %dx%d",
+			_width, _height, width, height);
+		return true;
+	}
+
 	if (highRes && !useGameplaySurface && !oversizedNative) {
 		if (width <= 0 || height <= 0) {
 			debugC(DEBUG_SMUSH, "SmushPlayerRebel2::ra2SelectFrameBuffer: Skipping invalid FOBJ dimensions %dx%d", width, height);




More information about the Scummvm-git-logs mailing list