[Scummvm-git-logs] scummvm master -> ccd5a4ecac9740d11e2095da0c26dbe16a0d8746

neuromancer noreply at scummvm.org
Sat Jun 6 12:21:11 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:
aa8ea34af2 SCUMM: RA1: padding in level names in level selection menu
9bfbce7dd0 SCUMM: RA1: implement damage in L9
ccd5a4ecac SCUMM: RA1: better controls for L9


Commit: aa8ea34af20cbed6d6c16c9ad30afade426f2080
    https://github.com/scummvm/scummvm/commit/aa8ea34af20cbed6d6c16c9ad30afade426f2080
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-06T14:03:54+02:00

Commit Message:
SCUMM: RA1: padding in level names in level selection menu

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 7a67f39b3ac..f0613e5c408 100644
--- a/engines/scumm/insane/rebel1/menu.cpp
+++ b/engines/scumm/insane/rebel1/menu.cpp
@@ -1077,39 +1077,45 @@ void InsaneRebel1::renderLevelSelectOverlay(byte *dst, int pitch, int width, int
 	const int titleW = getFontBankStringWidth("LEVEL SELECT");
 	drawMenuTitleText(dst, pitch, width, height, getRebel1MenuCenteredX(titleW), 15, "LEVEL SELECT");
 
-	const char *kLevelItems[kRA1LevelSelectItemCount] = {
-		" 1 TRAINING",
-		" 2 ASTEROIDS",
-		" 3 KOLAADOR",
-		" 4 STAR DESTR",
-		" 5 TATOOINE",
-		" 6 AST CHASE",
-		" 7 PROBES",
-		" 8 WALKERS",
-		" 9 TROOPERS",
-		"10 TRANSPORT",
-		"11 YAVIN",
-		"12 TIE ATK",
+	const char *const kLevelItems[kRA1NumLevels] = {
+		"1  TRAINING  ",
+		"2  ASTEROIDS ",
+		"3  KOLAADOR  ",
+		"4  STAR DESTR",
+		"5  TATOOINE  ",
+		"6  AST CHASE ",
+		"7  PROBES    ",
+		"8  WALKERS   ",
+		"9  TROOPERS  ",
+		"10 TRANSPORT ",
+		"11 YAVIN     ",
+		"12 TIE ATK   ",
 		"13 DS SURFACE",
-		"14 CANNON",
-		"15 DS TRENCH",
-		"BACK"
+		"14 CANNON    ",
+		"15 DS TRENCH "
 	};
+	const char *const kBackItem = "BACK";
 
 	const int menuY = 0x2d;
 	const int leftFrameX = kRA1LevelSelectLeftX;
 	const int rightFrameX = kRA1LevelSelectRightX;
 	const int columnW = kRA1LevelSelectColW;
+	int levelTextW = 0;
+
+	for (int i = 0; i < kRA1NumLevels; i++)
+		levelTextW = MAX(levelTextW, getMenuTalkTextWidth(kLevelItems[i]));
 
 	for (int i = 0; i < kRA1LevelSelectItemCount; i++) {
 		const int col = i / kRA1LevelSelectRowsPerCol;
 		const int row = i % kRA1LevelSelectRowsPerCol;
 		const int frameX = (col == 0) ? leftFrameX : rightFrameX;
 		const int y = menuY + row * kRA1MenuRowH;
-		const int textW = getMenuTalkTextWidth(kLevelItems[i]);
+		const bool levelItem = i < kRA1NumLevels;
+		const char *text = levelItem ? kLevelItems[i] : kBackItem;
+		const int textW = levelItem ? levelTextW : getMenuTalkTextWidth(text);
 		const int textX = frameX + (columnW - textW) / 2;
 
-		drawMenuTalkText(dst, pitch, width, height, textX, y, kLevelItems[i]);
+		drawMenuTalkText(dst, pitch, width, height, textX, y, text);
 
 		if (i == _levelSelectSel)
 			drawRebel1MenuFrame(dst, pitch, width, height,


Commit: 9bfbce7dd0fdca768cf334b41fd473ceb827485d
    https://github.com/scummvm/scummvm/commit/9bfbce7dd0fdca768cf334b41fd473ceb827485d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-06T14:03:54+02:00

Commit Message:
SCUMM: RA1: implement damage in L9

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 41232a893bd..614338dd842 100644
--- a/engines/scumm/insane/rebel1/iact.cpp
+++ b/engines/scumm/insane/rebel1/iact.cpp
@@ -1907,9 +1907,11 @@ void InsaneRebel1::updateOnFootSequence() {
 			_shipDirIndex = 4;  // Walk left
 	}
 
-	// --- Scripted damage latches → damageFlags (matching FUN_1B297 pattern) ---
-	// GAME 0x5D/0x5F set latches; convert to damage flags before the check.
-	if (_gameLatch5D == 0xFFFF)
+	// --- Scripted damage latches → damageFlags ---
+	// L9 on-foot trooper shots use ordinary 0x5D event ids, gated by the
+	// 0x5D object bitmask handler, then consumed by FUN_1ED95 through 0x74D4.
+	// The ship loops keep narrower level-specific 0x5D damage rules.
+	if (_gameLatch5D != 0)
 		_damageFlags |= 0x40;
 	if (_gameLatch5F != 0 &&
 		_vm->_rnd.getRandomNumber((uint16)(_gameLatch5F - 1)) == 0)
@@ -1919,6 +1921,7 @@ void InsaneRebel1::updateOnFootSequence() {
 	// On-foot damage uses the same heavy-damage tuning byte as ship shot/collision
 	// damage in the original, not the miss penalty.
 	if (_damageFlags != 0 && _damageCooldown == 0 && _health >= 0 && _deathTimer < 1) {
+		const int16 oldHealth = _health;
 		_health -= _tuning.shot;
 		if (_health < 0) {
 			_deathTimer = 15;
@@ -1928,6 +1931,8 @@ void InsaneRebel1::updateOnFootSequence() {
 		_damageCooldown = 3;
 		playSfx(kSfxBoom, 127, 0);
 		_screenFlash = 5;
+		debugC(DEBUG_INSANE, "RA1 on-foot player hit: frame=%u latch=%u flags=0x%02x health=%d->%d",
+			(unsigned)(uint16)_gameCounter, (unsigned)_gameLatch5D, _damageFlags, oldHealth, _health);
 	}
 }
 


Commit: ccd5a4ecac9740d11e2095da0c26dbe16a0d8746
    https://github.com/scummvm/scummvm/commit/ccd5a4ecac9740d11e2095da0c26dbe16a0d8746
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-06T14:03:54+02:00

Commit Message:
SCUMM: RA1: better controls for L9

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


diff --git a/engines/scumm/insane/rebel1/iact.cpp b/engines/scumm/insane/rebel1/iact.cpp
index 614338dd842..61b7a30e28e 100644
--- a/engines/scumm/insane/rebel1/iact.cpp
+++ b/engines/scumm/insane/rebel1/iact.cpp
@@ -88,6 +88,14 @@ const int kRA1Op0BVerticalAxisMax = 100;
 const int kRA1EnhancedFlightDirectMaxX = 64;
 const int kRA1EnhancedFlightDirectMaxY = 40;
 const int kRA1ControlPadAxisStep = 0x1E;
+const int16 kOnFootCenterX = 0xA3;  // g_perspectiveX in HandleGameOp19
+const int16 kOnFootCenterY = 0x82;  // g_perspectiveY in HandleGameOp19
+const int16 kOnFootCursorBaseY = kOnFootCenterY - 0x32;
+const int16 kOnFootGamepadStep = 7;
+const int16 kOnFootCursorMinX = 0;
+const int16 kOnFootCursorMaxX = 319;
+const int16 kOnFootCursorMinY = 0;
+const int16 kOnFootCursorMaxY = 199;
 
 // Level 15 final approach 0x5D damage/event codes consumed by
 // RunLevel1GameLoop. The latch stores the raw GAME parameter; no translation is
@@ -1837,9 +1845,6 @@ bool InsaneRebel1::isTorpedoModeActive() const {
 //   g_perspectiveX/Y  = crosshair center (on-foot targeting)
 // Our _perspectiveX/_perspectiveY maps to the camera offset (DAT_000041a0/41a2).
 // The crosshair center (0xA3, 0x82) is a separate constant for on-foot mode.
-const int16 kOnFootCenterX = 0xA3;  // g_perspectiveX in HandleGameOp19
-const int16 kOnFootCenterY = 0x82;  // g_perspectiveY in HandleGameOp19
-
 // Port split matching HandleGameOp19_OnFootSequence. The helper name is new to
 // this implementation; the original code dispatches the opcode handler directly.
 void InsaneRebel1::initOnFootSequence() {
@@ -1861,6 +1866,74 @@ void InsaneRebel1::initOnFootSequence() {
 	}
 }
 
+void InsaneRebel1::preprocessOnFootAim(int16 &inputX, int16 &inputY, bool *usedJoystick) {
+	if (usedJoystick)
+		*usedJoystick = false;
+
+	const int dpadX =
+		(_vm->getActionState(kScummActionInsaneRight) ? 1 : 0) -
+		(_vm->getActionState(kScummActionInsaneLeft) ? 1 : 0);
+	int dpadY =
+		(_vm->getActionState(kScummActionInsaneDown) ? 1 : 0) -
+		(_vm->getActionState(kScummActionInsaneUp) ? 1 : 0);
+
+	const int16 analogAxisX = applyRebel1AnalogDeadzone(_joystickAxisX);
+	int16 analogAxisY = applyRebel1AnalogDeadzone(_joystickAxisY);
+	if (_optControlsYFlip) {
+		dpadY = -dpadY;
+		analogAxisY = (int16)-analogAxisY;
+	}
+
+	int deltaX = 0;
+	int deltaY = 0;
+	bool activeGamepadAim = false;
+
+	if (dpadX || dpadY) {
+		deltaX = dpadX * kOnFootGamepadStep;
+		deltaY = dpadY * kOnFootGamepadStep;
+		activeGamepadAim = true;
+	} else if (_activeInputSource == kInputSourceJoystickAnalog && (analogAxisX || analogAxisY)) {
+		const int analogX = CLIP<int32>(((int32)analogAxisX * kRA1CenteredAxisMax) / Common::JOYAXIS_MAX,
+			-kRA1CenteredAxisMax, kRA1CenteredAxisMax);
+		const int analogY = CLIP<int32>(((int32)analogAxisY * kRA1CenteredAxisMax) / Common::JOYAXIS_MAX,
+			-kRA1CenteredAxisMax, kRA1CenteredAxisMax);
+		deltaX = stepRebel1Op0BReticleAxis(analogX);
+		deltaY = stepRebel1Op0BReticleAxis(analogY);
+		activeGamepadAim = (deltaX != 0 || deltaY != 0);
+	}
+
+	if (activeGamepadAim) {
+		if (!_gamepadAimActive) {
+			_gamepadAimAxisX = CLIP<int16>(_shipPosX, kOnFootCursorMinX, kOnFootCursorMaxX);
+			_gamepadAimAxisY = CLIP<int16>(_shipPosY, kOnFootCursorMinY, kOnFootCursorMaxY);
+		}
+
+		_gamepadAimAxisX = CLIP<int16>((int16)(_gamepadAimAxisX + deltaX), kOnFootCursorMinX, kOnFootCursorMaxX);
+		_gamepadAimAxisY = CLIP<int16>((int16)(_gamepadAimAxisY + deltaY), kOnFootCursorMinY, kOnFootCursorMaxY);
+		_gamepadAimActive = true;
+
+		if (usedJoystick)
+			*usedJoystick = true;
+		inputX = (int16)(_gamepadAimAxisX - kOnFootCenterX);
+		inputY = (int16)(_gamepadAimAxisY - kOnFootCursorBaseY);
+		return;
+	}
+
+	if (_gamepadAimActive && _activeInputSource != kInputSourceMouse) {
+		if (usedJoystick)
+			*usedJoystick = true;
+		inputX = (int16)(_gamepadAimAxisX - kOnFootCenterX);
+		inputY = (int16)(_gamepadAimAxisY - kOnFootCursorBaseY);
+		return;
+	}
+
+	_gamepadAimActive = false;
+	const int16 logicalX = (int16)CLIP<int>(_vm->_mouse.x, kOnFootCursorMinX, kOnFootCursorMaxX);
+	const int16 logicalY = (int16)CLIP<int>(_vm->_mouse.y, kOnFootCursorMinY, kOnFootCursorMaxY);
+	inputX = (int16)(logicalX - kOnFootCenterX);
+	inputY = (int16)(logicalY - kOnFootCursorBaseY);
+}
+
 // Port split matching HandleGameOp19_OnFootSequence. The helper name is new to
 // this implementation; the original code dispatches the opcode handler directly.
 void InsaneRebel1::updateOnFootSequence() {
@@ -1899,8 +1972,10 @@ void InsaneRebel1::updateOnFootSequence() {
 	} else {
 		// Walking based on input direction. The 3DO second held button skips the
 		// early aim-pose branch above and reaches these walk tests immediately.
-		int16 inputX = 0, inputY = 0;
-		preprocessMouseAxes(inputX, inputY);
+		int16 inputX = (int16)(_shipPosX - kOnFootCenterX);
+		int16 inputY = (int16)(_shipPosY - kOnFootCursorBaseY);
+		if (!hasFrameGameOpcode(0x1A))
+			preprocessOnFootAim(inputX, inputY);
 		if (inputX > 0x1E && _onFootCharX < 0x73)
 			_shipDirIndex = 6;  // Walk right
 		else if (inputX < -0x1E && _onFootCharX > -0x73)
@@ -1940,13 +2015,13 @@ void InsaneRebel1::updateOnFootSequence() {
 // this implementation; the original code dispatches the opcode handler directly.
 void InsaneRebel1::updateOnFootAimVariant() {
 	// --- 0x1A: Crosshair positioning (HandleGameOp1A_OnFootVariant) ---
-	// shipPosX/Y = mouse_input + crosshair_center + character_offset
+	// DOS used virtual-mouse axes relative to the character offset. ScummVM's
+	// mouse and gamepad reticle are screen-space controls so the cursor remains
+	// able to cross the whole playfield while Luke is standing at either side.
 	int16 inputX = 0, inputY = 0;
-	preprocessMouseAxes(inputX, inputY);
-	inputX = CLIP<int16>(inputX, -100, 100);
-	int16 inputYNeg = CLIP<int16>((int16)(-inputY), -0x4B, 0x0F);
-	_shipPosX = inputX + kOnFootCenterX + _onFootCharX;
-	_shipPosY = inputYNeg + kOnFootCenterY + _onFootCharY - 0x32;
+	preprocessOnFootAim(inputX, inputY);
+	_shipPosX = CLIP<int16>((int16)(inputX + kOnFootCenterX), kOnFootCursorMinX, kOnFootCursorMaxX);
+	_shipPosY = CLIP<int16>((int16)(inputY + kOnFootCursorBaseY), kOnFootCursorMinY, kOnFootCursorMaxY);
 }
 
 void InsaneRebel1::finishOnFootFrame() {
diff --git a/engines/scumm/insane/rebel1/rebel.h b/engines/scumm/insane/rebel1/rebel.h
index b191854248b..041a528e978 100644
--- a/engines/scumm/insane/rebel1/rebel.h
+++ b/engines/scumm/insane/rebel1/rebel.h
@@ -386,6 +386,7 @@ private:
 
 	// 0x19/0x1A on-foot handler (Level 9 Stormtroopers)
 	void initOnFootSequence();
+	void preprocessOnFootAim(int16 &inputX, int16 &inputY, bool *usedJoystick = nullptr);
 	void updateOnFootSequence();
 	void updateOnFootAimVariant();
 	void finishOnFootFrame();




More information about the Scummvm-git-logs mailing list