[Scummvm-git-logs] scummvm master -> 135ed69a93619f80f86227f916cc58997bd06c26

neuromancer noreply at scummvm.org
Tue Jun 2 16:30:05 UTC 2026


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

Summary:
bfd9911cd8 SCUMM: RA2: better gamepad support for level 4
62fbbbba89 SCUMM: RA: sync subtitle support on real time with the ScummVM settings
135ed69a93 SCUMM: RA1: make sure touchpad and desktop users can skip cutscenes


Commit: bfd9911cd848f69d8e22dab04155e308cd07a366
    https://github.com/scummvm/scummvm/commit/bfd9911cd848f69d8e22dab04155e308cd07a366
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-02T18:29:45+02:00

Commit Message:
SCUMM: RA2: better gamepad support for level 4

Changed paths:
    engines/scumm/insane/rebel2/rebel.cpp


diff --git a/engines/scumm/insane/rebel2/rebel.cpp b/engines/scumm/insane/rebel2/rebel.cpp
index bfec3000e6a..f570cda54ca 100644
--- a/engines/scumm/insane/rebel2/rebel.cpp
+++ b/engines/scumm/insane/rebel2/rebel.cpp
@@ -602,11 +602,14 @@ bool InsaneRebel2::notifyEvent(const Common::Event &event) {
 	// every shot. We observe before ScummEngine (priority 1 > kEventManPriority), so
 	// dropping the event here prevents the clobber. Firing is driven by the
 	// kScummActionInsaneAttack action, not the pointer, so this does not affect shots.
-	// A genuine mouse/touch motion (nonzero relative delta) hands control back.
+	// A genuine mouse/touch motion (nonzero relative delta) normally hands control
+	// back; handler 0x26 keeps ownership until its gamepad reticle returns to center.
 	if (_gamepadAimActive && _gameState == kStateGameplay && !_menuInputActive) {
 		switch (event.type) {
 		case Common::EVENT_MOUSEMOVE:
 			if (event.relMouse.x != 0 || event.relMouse.y != 0) {
+				if (_rebelHandler == 0x26)
+					return true;
 				_gamepadAimActive = false; // real pointer motion takes over
 				break;
 			}
@@ -1623,35 +1626,71 @@ void InsaneRebel2::updateGameplayAimFromGamepad() {
 	if (_menuInputActive || _gameState != kStateGameplay)
 		return;
 
-	// The analog stick still reports the original joystick-style centered axis range
-	// [-127,127], while the dpad follows the original keyboard handler's normal
-	// movement step (FUN_405822: 3 units, or 5 with the DOS fast modifier).
-	int deltaX = 0;
-	int deltaY = 0;
-	bool activeGamepadAim = false;
-
 	const int dpadX = (_vm->getActionState(kScummActionInsaneRight) ? 1 : 0) -
 	                  (_vm->getActionState(kScummActionInsaneLeft) ? 1 : 0);
 	const int dpadY = (_vm->getActionState(kScummActionInsaneDown) ? 1 : 0) -
 	                  (_vm->getActionState(kScummActionInsaneUp) ? 1 : 0);
 
-	if (dpadX || dpadY) {
+	const int16 ax = applyRebel2AnalogDeadzone(_joystickAxisX);
+	const int16 ay = applyRebel2AnalogDeadzone(_joystickAxisY);
+	const int velX = CLIP<int>((int)ax * 127 / Common::JOYAXIS_MAX, -127, 127);
+	const int velY = CLIP<int>((int)ay * 127 / Common::JOYAXIS_MAX, -127, 127);
+
+	int deltaX = 0;
+	int deltaY = 0;
+	bool activeGamepadAim = false;
+
+	if (_rebelHandler == 0x26) {
+		// Retail RA2 maps joystick axes into a small centered handler 0x26 reticle box.
+		// ScummVM deliberately exposes the full 320x200 mouse aim range for gamepads
+		// too, but preserves the original joystick feel: curved response for precise
+		// center aiming, and automatic return to screen center when the stick is released.
+		int axisX = 0;
+		int axisY = 0;
+		if (dpadX || dpadY) {
+			axisX = dpadX * 127;
+			axisY = dpadY * 127;
+		} else {
+			axisX = velX;
+			axisY = velY;
+		}
+
+		if (axisX || axisY || _gamepadAimActive) {
+			const int centerX = 160;
+			const int centerY = 100;
+			const int absAxisX = ABS(axisX);
+			const int absAxisY = ABS(axisY);
+			const int curvedX = (absAxisX * absAxisX + 126) / 127;
+			const int curvedY = (absAxisY * absAxisY + 126) / 127;
+			const int targetX = axisX < 0 ?
+				centerX - curvedX * centerX / 127 :
+				centerX + curvedX * (319 - centerX) / 127;
+			const int targetY = axisY < 0 ?
+				centerY - curvedY * centerY / 127 :
+				centerY + curvedY * (199 - centerY) / 127;
+			const int maxStep = (axisX || axisY) ? 14 : 10;
+			const int distX = targetX - _vm->_mouse.x;
+			const int distY = targetY - _vm->_mouse.y;
+
+			if (distX || distY) {
+				deltaX = CLIP<int>(distX, -maxStep, maxStep);
+				deltaY = CLIP<int>(distY, -maxStep, maxStep);
+				activeGamepadAim = true;
+			} else {
+				_gamepadAimActive = (axisX || axisY);
+				return;
+			}
+		}
+	} else if (dpadX || dpadY) {
 		const int kOriginalDigitalStep = 3;
 		deltaX = dpadX * kOriginalDigitalStep;
 		deltaY = dpadY * kOriginalDigitalStep;
 		activeGamepadAim = true;
-	} else {
-		const int16 ax = applyRebel2AnalogDeadzone(_joystickAxisX);
-		const int16 ay = applyRebel2AnalogDeadzone(_joystickAxisY);
-		const int velX = CLIP<int>((int)ax * 127 / Common::JOYAXIS_MAX, -127, 127);
-		const int velY = CLIP<int>((int)ay * 127 / Common::JOYAXIS_MAX, -127, 127);
-
-		if (velX || velY) {
-			const int kAnalogMaxStep = 8;
-			deltaX = velX * kAnalogMaxStep / 127;
-			deltaY = velY * kAnalogMaxStep / 127;
-			activeGamepadAim = true;
-		}
+	} else if (velX || velY) {
+		const int kAnalogMaxStep = 8;
+		deltaX = velX * kAnalogMaxStep / 127;
+		deltaY = velY * kAnalogMaxStep / 127;
+		activeGamepadAim = true;
 	}
 
 	if (!activeGamepadAim)


Commit: 62fbbbba895d32abcd879424cbb079abba481fb7
    https://github.com/scummvm/scummvm/commit/62fbbbba895d32abcd879424cbb079abba481fb7
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-02T18:29:45+02:00

Commit Message:
SCUMM: RA: sync subtitle support on real time with the ScummVM settings

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


diff --git a/engines/scumm/insane/rebel1/menu.cpp b/engines/scumm/insane/rebel1/menu.cpp
index 2de991ea72b..56d9d11c8cb 100644
--- a/engines/scumm/insane/rebel1/menu.cpp
+++ b/engines/scumm/insane/rebel1/menu.cpp
@@ -900,6 +900,8 @@ 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");
+
 	const char *kDiffNames[3] = { "EASY", "NORMAL", "HARD" };
 
 	const int titleW = getFontBankStringWidth("GAME OPTIONS");
@@ -1203,7 +1205,7 @@ void InsaneRebel1::runOptionsMenu() {
 				_vm->_mixer->muteSoundType(Audio::Mixer::kSpeechSoundType, !_optSfxEnabled);
 				break;
 			case 4: // Toggle dialogue text
-				_optTextEnabled = !_optTextEnabled;
+				_optTextEnabled = !ConfMan.getBool("subtitles");
 				ConfMan.setBool("subtitles", _optTextEnabled);
 				break;
 			case 5: // Toggle enhanced/original input style
diff --git a/engines/scumm/insane/rebel2/menu.cpp b/engines/scumm/insane/rebel2/menu.cpp
index 20bd7ef213c..f785cd7159c 100644
--- a/engines/scumm/insane/rebel2/menu.cpp
+++ b/engines/scumm/insane/rebel2/menu.cpp
@@ -1907,7 +1907,7 @@ int InsaneRebel2::processOptionsInput() {
 					_vm->_mixer->muteSoundType(Audio::Mixer::kSpeechSoundType, !_optVoicesEnabled);
 					break;
 				case 3:  // Text toggle
-					_optTextEnabled = !_optTextEnabled;
+					_optTextEnabled = !ConfMan.getBool("subtitles");
 					ConfMan.setBool("subtitles", _optTextEnabled);
 					break;
 				case 4:  // Controls toggle
@@ -1961,6 +1961,8 @@ void InsaneRebel2::drawOptionsOverlay(byte *renderBitmap, int pitch, int width,
 	if (!splayer)
 		return;
 
+	_optTextEnabled = ConfMan.getBool("subtitles");
+
 	// Build items array from TRS strings based on current toggle states
 	// TRS 89: title, 90/91: music, 92/93: sfx, 94/95: voices,
 	// 96/97: text, 98/99: controls, 100/101: rapid fire, 103: volume, 107: back


Commit: 135ed69a93619f80f86227f916cc58997bd06c26
    https://github.com/scummvm/scummvm/commit/135ed69a93619f80f86227f916cc58997bd06c26
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-02T18:29:45+02:00

Commit Message:
SCUMM: RA1: make sure touchpad and desktop users can skip cutscenes

Changed paths:
    engines/scumm/insane/rebel1/iact.cpp
    engines/scumm/insane/rebel1/menu.cpp
    engines/scumm/insane/rebel1/rebel.h
    engines/scumm/insane/rebel1/runlevels.cpp
    engines/scumm/metaengine.cpp


diff --git a/engines/scumm/insane/rebel1/iact.cpp b/engines/scumm/insane/rebel1/iact.cpp
index db4c4593dc9..b5d28d028d7 100644
--- a/engines/scumm/insane/rebel1/iact.cpp
+++ b/engines/scumm/insane/rebel1/iact.cpp
@@ -857,20 +857,12 @@ void InsaneRebel1::preprocessMouseAxes(int16 &inputX, int16 &inputY, bool *usedJ
 		return;
 	}
 
-	// On touchscreen devices aiming comes from the on-screen gamepad (joystick), never the
-	// absolute touch/cursor position; and we must not recenter the system cursor
-	// (smush_warpMouse below), which would inject spurious motion and drift the reticle.
-	if (isTouchscreenActive()) {
-		inputX = 0;
-		inputY = 0;
-		_mouseVirtualValid = false;
-		return;
-	}
-
 	int16 logicalX = (int16)CLIP<int>(_vm->_mouse.x, 0, 319);
 	int16 logicalY = (int16)CLIP<int>(_vm->_mouse.y, 0, 199);
 
-	if (_optEnhancedControls) {
+	// Touchscreens cannot support the DOS recenter/warp model, so use the
+	// non-warping absolute axis path even when original input style is selected.
+	if (_optEnhancedControls || isTouchscreenActive()) {
 		_mouseVirtualValid = false;
 		_mouseBiasLatch = false;
 		_mouseBiasX = 0;
diff --git a/engines/scumm/insane/rebel1/menu.cpp b/engines/scumm/insane/rebel1/menu.cpp
index 56d9d11c8cb..4a88a5e9b92 100644
--- a/engines/scumm/insane/rebel1/menu.cpp
+++ b/engines/scumm/insane/rebel1/menu.cpp
@@ -612,12 +612,21 @@ bool InsaneRebel1::notifyEvent(const Common::Event &event) {
 	if (_vm->isPaused())
 		return false;
 
-	// On touchscreen devices, finger drags arrive as mouse-move events; do not let them
-	// hijack RA1 into absolute-cursor aiming (aiming there comes from the on-screen gamepad).
-	if (event.type == Common::EVENT_MOUSEMOVE && !_mouseRecentering && !isTouchscreenActive()) {
-		_activeInputSource = kInputSourceMouse;
+	if (isTouchscreenActive() && !_interactiveVideoActive && !_menuActive &&
+			(event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_LBUTTONUP)) {
+		_vm->_smushVideoShouldFinish = true;
+		return true;
 	}
 
+	if (event.type == Common::EVENT_MOUSEMOVE && !_mouseRecentering)
+		_activeInputSource = kInputSourceMouse;
+
+	// Android direct touch reports taps as left-clicks. Treat those as mouse input
+	// during gameplay so tap-to-aim-and-fire works even if a joystick event was last.
+	if (isTouchscreenActive() && _interactiveVideoActive && !_menuActive &&
+			event.type == Common::EVENT_LBUTTONDOWN && !_mouseRecentering)
+		_activeInputSource = kInputSourceMouse;
+
 	// ScummVM-exclusive feature: mouse navigation/clicking of the RA1 front-end menus.
 	if (handleMenuMouse(event))
 		return true;
@@ -730,6 +739,10 @@ bool InsaneRebel1::notifyEvent(const Common::Event &event) {
 		if (event.customType == kScummActionInsaneBack) {
 			if (!pressed)
 				return true;
+			if (_player && !_interactiveVideoActive && !_menuActive) {
+				_vm->_smushVideoShouldFinish = true;
+				return true;
+			}
 			if (_player) {
 				const bool wasPaused = _player->_paused;
 				if (!wasPaused)
@@ -749,6 +762,14 @@ bool InsaneRebel1::notifyEvent(const Common::Event &event) {
 			return true;
 		}
 
+		if (isTouchscreenActive() && !_interactiveVideoActive && !_menuActive && pressed &&
+				(event.customType == kScummActionInsaneAttack ||
+				 event.customType == kScummActionInsaneSwitch ||
+				 event.customType == kScummActionInsaneSkip)) {
+			_vm->_smushVideoShouldFinish = true;
+			return true;
+		}
+
 		if (pressed && handleControllerMenuAction((ScummAction)event.customType))
 			return true;
 
@@ -778,10 +799,14 @@ bool InsaneRebel1::notifyEvent(const Common::Event &event) {
 	// Shooting: mouse button during interactive gameplay — FUN_1CCA0 (0x1CCA0)
 	if (_interactiveVideoActive && !_menuActive) {
 		if (event.type == Common::EVENT_LBUTTONDOWN) {
+			_vm->_mouse.x = event.mouse.x;
+			_vm->_mouse.y = event.mouse.y;
 			_playerFired = true;
 			return true;
 		}
 		if (event.type == Common::EVENT_LBUTTONUP) {
+			_vm->_mouse.x = event.mouse.x;
+			_vm->_mouse.y = event.mouse.y;
 			_playerFired = false;
 			return true;
 		}
@@ -795,6 +820,11 @@ bool InsaneRebel1::notifyEvent(const Common::Event &event) {
 	}
 
 	if (event.type == Common::EVENT_MAINMENU) {
+		if (_player && !_interactiveVideoActive && !_menuActive) {
+			_vm->_smushVideoShouldFinish = true;
+			return true;
+		}
+
 		if (_menuActive || _highScoresActive)
 			return true;
 
diff --git a/engines/scumm/insane/rebel1/rebel.h b/engines/scumm/insane/rebel1/rebel.h
index eab04823b21..6081ec18aae 100644
--- a/engines/scumm/insane/rebel1/rebel.h
+++ b/engines/scumm/insane/rebel1/rebel.h
@@ -105,9 +105,9 @@ public:
 
 	void handleGameChunk(int32 subSize, Common::SeekableReadStream &b);
 	bool isInteractiveVideoActive() const { return _interactiveVideoActive; }
-	// True on touchscreen devices (e.g. Android). RA1 then aims from the on-screen gamepad
-	// joystick instead of the DOS absolute-mouse model, and skips cursor warping/locking,
-	// which otherwise inject spurious motion that drifts the reticle and on-screen buttons.
+	// True on touchscreen devices (e.g. Android). RA1 skips DOS-style cursor
+	// warping/locking there; direct touch uses absolute aiming, while on-screen
+	// gamepad/joystick input continues through the joystick path.
 	bool isTouchscreenActive() const;
 	void setFrameHasGameChunk(bool hasGameChunk) { _frameHasGameChunk = hasGameChunk; }
 	int getCurrentLevel() const { return _currentLevel; }
diff --git a/engines/scumm/insane/rebel1/runlevels.cpp b/engines/scumm/insane/rebel1/runlevels.cpp
index b1e4303c7f4..1a61b7ff307 100644
--- a/engines/scumm/insane/rebel1/runlevels.cpp
+++ b/engines/scumm/insane/rebel1/runlevels.cpp
@@ -1672,9 +1672,9 @@ void InsaneRebel1::captureInteractiveVideoInput() {
 	// Level 7 route splices happen inside one original gameplay loop, so keep
 	// the current input state instead of recentering between route clips.
 	if (!level7RouteSplice) {
-		// On touchscreen devices the DOS recenter-the-cursor aiming model does not apply
-		// (aiming uses the on-screen gamepad); warping/locking the system mouse there only
-		// injects spurious motion that drifts the reticle and on-screen buttons.
+		// On touchscreen devices the DOS recenter-the-cursor aiming model does not apply;
+		// warping/locking the system mouse there injects spurious motion that drifts
+		// direct touch aiming and on-screen controls.
 		if (!isTouchscreenActive())
 			smush_warpMouse(160, 100, -1);
 		_mouseVirtualRawX = 0x140;
diff --git a/engines/scumm/metaengine.cpp b/engines/scumm/metaengine.cpp
index 7c7a5d0396d..7a059404df5 100644
--- a/engines/scumm/metaengine.cpp
+++ b/engines/scumm/metaengine.cpp
@@ -1179,6 +1179,7 @@ Common::KeymapArray ScummMetaEngine::initKeymaps(const char *target) const {
 
 		act = new Action("RA1FIRE", _("Fire / select"));
 		act->setCustomEngineActionEvent(kScummActionInsaneAttack);
+		act->addDefaultInputMapping("MOUSE_LEFT");
 		act->addDefaultInputMapping("JOY_A");
 		rebel1Keymap->addAction(act);
 




More information about the Scummvm-git-logs mailing list