[Scummvm-git-logs] scummvm master -> 12c0e7e2cd6348b67c2faafb0dc3edce1f5dc83c
neuromancer
noreply at scummvm.org
Thu Jun 4 17:01:09 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:
f0bd302f43 SCUMM: RA1: added missing overlay in level 1 (part 2)
1138603703 SCUMM: RA1: fixed ordering of rendering for indicators, shoots, overlays and cockpit
12c0e7e2cd SCUMM: RA1: correctly render the opening line in the intro
Commit: f0bd302f430d8a741f44258e7de27dc1506e0aa3
https://github.com/scummvm/scummvm/commit/f0bd302f430d8a741f44258e7de27dc1506e0aa3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-04T17:22:54+02:00
Commit Message:
SCUMM: RA1: added missing overlay in level 1 (part 2)
Changed paths:
engines/scumm/insane/rebel1/rebel.h
engines/scumm/insane/rebel1/render.cpp
diff --git a/engines/scumm/insane/rebel1/rebel.h b/engines/scumm/insane/rebel1/rebel.h
index 26dc27c6014..5ed007bb059 100644
--- a/engines/scumm/insane/rebel1/rebel.h
+++ b/engines/scumm/insane/rebel1/rebel.h
@@ -247,7 +247,8 @@ private:
void handleLevel14Play2BSplice(int32 curFrame, int32 maxFrame);
void renderLevel7RouteOverlays(byte *dst, int pitch, int width, int height);
void renderLevel5Part2Overlay(byte *dst, int pitch, int width, int height, int32 curFrame);
- void renderLevel11HitsOverlay(byte *dst, int pitch, int width, int height);
+ void renderLevelHitsOverlay(byte *dst, int pitch, int width, int height, int y,
+ bool screenSpace);
void resetEnemyShotSlots();
void renderLevel13EnemyShots(byte *dst, int pitch, int width, int height);
void getTurretShipCenter(int16 &x, int16 &y) const;
diff --git a/engines/scumm/insane/rebel1/render.cpp b/engines/scumm/insane/rebel1/render.cpp
index 1a17b10eb9f..e52794dde7d 100644
--- a/engines/scumm/insane/rebel1/render.cpp
+++ b/engines/scumm/insane/rebel1/render.cpp
@@ -800,8 +800,11 @@ void InsaneRebel1::procPostRendering(byte *renderBitmap, int32 codecparam, int32
if (_currentLevel == 4 && _levelGameplayPhase == 2)
renderLevel5Part2Overlay(renderBitmap, pitch, width, height, curFrame);
+ if (_currentLevel == 0 && _flyControlMode == 2)
+ renderLevelHitsOverlay(renderBitmap, pitch, width, height, 0x04, true);
+
if (_currentLevel == 10)
- renderLevel11HitsOverlay(renderBitmap, pitch, width, height);
+ renderLevelHitsOverlay(renderBitmap, pitch, width, height, 0x16, false);
// Level 8 (Imperial Walkers) â walker-specific state update + UI overlay.
// In the original, RunLevel8Flow runs the walker logic inline in the per-frame
@@ -1017,16 +1020,23 @@ void InsaneRebel1::renderGostSlots(byte *dst, int pitch, int width, int height)
}
}
-// renderLevel11HitsOverlay â RunLevel11Flow (0x19F9F) calls FormatAndDrawText
-// each L11PLAY frame with "<<HITS %02d" at (0x119, 0x16). This helper is a
-// ScummVM-side extraction; the original keeps the draw call inline in the loop.
-void InsaneRebel1::renderLevel11HitsOverlay(byte *dst, int pitch, int width, int height) {
+// renderLevelHitsOverlay â RunLevel1Flow (0x16421-0x16438) and RunLevel11Flow
+// (0x1A07A-0x1A090) call FormatAndDrawText with "<<HITS %02d" at x=0x119.
+void InsaneRebel1::renderLevelHitsOverlay(byte *dst, int pitch, int width, int height, int y,
+ bool screenSpace) {
if (_hudFontBank.numSprites <= 0 && _techFontBank.numSprites <= 0)
return;
+ int drawX = 0x119;
+ int drawY = y;
+ if (screenSpace && _player) {
+ drawX += ra1Player()->_ra1ViewportOffsetX;
+ drawY += ra1Player()->_ra1ViewportOffsetY;
+ }
+
char hitsStr[16];
Common::sprintf_s(hitsStr, "<<HITS %02d", (int)_killCount);
- drawFontBankString(dst, pitch, width, height, 0x119, 0x16, hitsStr);
+ drawFontBankString(dst, pitch, width, height, drawX, drawY, hitsStr);
}
// renderLevel5Part2Overlay â RunLevel5Flow (0x176D0-0x1777E) draws the
Commit: 113860370310e60708cdf42a127f50a851c9b9bd
https://github.com/scummvm/scummvm/commit/113860370310e60708cdf42a127f50a851c9b9bd
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-04T17:59:33+02:00
Commit Message:
SCUMM: RA1: fixed ordering of rendering for indicators, shoots, overlays and cockpit
Changed paths:
engines/scumm/insane/rebel1/iact.cpp
engines/scumm/insane/rebel1/rebel.cpp
engines/scumm/insane/rebel1/rebel.h
engines/scumm/insane/rebel1/render.cpp
engines/scumm/smush/rebel/smush_player_ra1.cpp
diff --git a/engines/scumm/insane/rebel1/iact.cpp b/engines/scumm/insane/rebel1/iact.cpp
index 48f1ff485ee..71106907a37 100644
--- a/engines/scumm/insane/rebel1/iact.cpp
+++ b/engines/scumm/insane/rebel1/iact.cpp
@@ -2433,7 +2433,8 @@ void InsaneRebel1::handleGameCounterOpcode(uint32 opcode, int32 subSize, Common:
// handleGameChunk â FUN_1BE1B (0x1BE1B). Central GAME opcode dispatcher.
// Reads 7x32-bit BE integers from GAME chunk, routes to per-opcode handlers.
-void InsaneRebel1::handleGameChunk(int32 subSize, Common::SeekableReadStream &b) {
+void InsaneRebel1::handleGameChunk(int32 subSize, Common::SeekableReadStream &b,
+ byte *renderBitmap, int width, int height) {
if (subSize < 8)
return;
@@ -2484,6 +2485,7 @@ void InsaneRebel1::handleGameChunk(int32 subSize, Common::SeekableReadStream &b)
case 0x0B:
handleGameOpcode0BFirstPerson(subSize, b, param1);
+ renderGameOp0BOverlayDuringChunk(renderBitmap, width, width, height);
break;
case 0x5A:
diff --git a/engines/scumm/insane/rebel1/rebel.cpp b/engines/scumm/insane/rebel1/rebel.cpp
index 4fd79f1c7eb..eb886e24bae 100644
--- a/engines/scumm/insane/rebel1/rebel.cpp
+++ b/engines/scumm/insane/rebel1/rebel.cpp
@@ -295,6 +295,7 @@ InsaneRebel1::InsaneRebel1(ScummEngine_v7 *scumm) : Insane(), _vm(scumm) {
_frameHasGameChunk = false;
_frameDispatchFlags = 0;
_gameOp0BPhysicsUpdatedThisFrame = false;
+ _gameOp0BOverlayRenderedThisFrame = false;
_health = kMaxHealth;
_lives = 3;
diff --git a/engines/scumm/insane/rebel1/rebel.h b/engines/scumm/insane/rebel1/rebel.h
index 5ed007bb059..1db04a43a5b 100644
--- a/engines/scumm/insane/rebel1/rebel.h
+++ b/engines/scumm/insane/rebel1/rebel.h
@@ -103,7 +103,8 @@ public:
int16 par1, int16 par2, int16 par3, int16 par4) override;
void procSKIP(int32 subSize, Common::SeekableReadStream &b) override;
- void handleGameChunk(int32 subSize, Common::SeekableReadStream &b);
+ void handleGameChunk(int32 subSize, Common::SeekableReadStream &b,
+ byte *renderBitmap = nullptr, int width = 0, int height = 0);
bool isInteractiveVideoActive() const { return _interactiveVideoActive; }
// True on touchscreen devices (e.g. Android). RA1 skips DOS-style cursor
// warping/locking there; direct touch uses absolute aiming, while on-screen
@@ -243,7 +244,8 @@ private:
int16 centerX, int16 centerY, int16 frame);
void renderLaserShots(byte *dst, int pitch, int width, int height);
void renderShotOverlayPipeline(byte *dst, int pitch, int width, int height,
- bool drawTargetBoxes);
+ bool drawTargetBoxes, bool drawTargeting = true);
+ void renderGameOp0BOverlayDuringChunk(byte *dst, int pitch, int width, int height);
void handleLevel14Play2BSplice(int32 curFrame, int32 maxFrame);
void renderLevel7RouteOverlays(byte *dst, int pitch, int width, int height);
void renderLevel5Part2Overlay(byte *dst, int pitch, int width, int height, int32 curFrame);
@@ -447,6 +449,7 @@ private:
bool _frameHasGameChunk;
uint16 _frameDispatchFlags;
bool _gameOp0BPhysicsUpdatedThisFrame;
+ bool _gameOp0BOverlayRenderedThisFrame;
// Difficulty (0=easy, 1=normal, 2=hard) â matches original DAT_22BC
int _difficulty;
diff --git a/engines/scumm/insane/rebel1/render.cpp b/engines/scumm/insane/rebel1/render.cpp
index e52794dde7d..44b888c2cd1 100644
--- a/engines/scumm/insane/rebel1/render.cpp
+++ b/engines/scumm/insane/rebel1/render.cpp
@@ -524,6 +524,7 @@ void InsaneRebel1::procPreRendering(byte *renderBitmap) {
_frameDispatchFlags = 0;
_hudRenderFlag = 0;
_gameOp0BPhysicsUpdatedThisFrame = false;
+ _gameOp0BOverlayRenderedThisFrame = false;
_turretFrameShipCenterValid = false;
_frameObjectHitRevealPending = false;
@@ -630,6 +631,8 @@ void InsaneRebel1::procPostRendering(byte *renderBitmap, int32 codecparam, int32
(allowImplicitGameplayMode &&
(_activeGameOpcode == 0x07 || _activeGameOpcode == 0x09));
bool shotOverlayHandled = false;
+ bool drawShipAfterGameplayOverlays = false;
+ bool drawGameOp0BTargetingAfterFetch = false;
if (gameOp0BMode) {
// GAME 0x0B scrolling cockpit/surface handler â FUN_1CDA7.
if (!_gameOp0BPhysicsUpdatedThisFrame) {
@@ -647,6 +650,9 @@ void InsaneRebel1::procPostRendering(byte *renderBitmap, int32 codecparam, int32
_vm->_smushVideoShouldFinish = true;
return;
}
+
+ shotOverlayHandled = _gameOp0BOverlayRenderedThisFrame;
+ drawGameOp0BTargetingAfterFetch = _gameOp0BOverlayRenderedThisFrame;
} else if (onFootMode) {
// On-foot handler â opcodes 0x19/0x1A (Level 9 Stormtroopers)
if (_currentLevel == 8 && onFootAimMode && !onFootSequenceMode && _killCount > 0) {
@@ -721,9 +727,9 @@ void InsaneRebel1::procPostRendering(byte *renderBitmap, int32 codecparam, int32
return;
}
- // Ship sprite is present in both flight (0x07 family) and 0x08 turret path.
- if (flightMode || turretMode)
- renderShip(renderBitmap, pitch, width, height);
+ // The paired GAME 0x09/0x0A handlers draw target boxes, shots and
+ // reticles before the 0x07/0x08 ship/cockpit pass.
+ drawShipAfterGameplayOverlays = (flightMode || turretMode);
}
// GAME handlers in the original update FUN_224FD during the same frame that
@@ -795,6 +801,13 @@ void InsaneRebel1::procPostRendering(byte *renderBitmap, int32 codecparam, int32
renderLevel7RouteOverlays(renderBitmap, pitch, width, height);
renderExplosions(renderBitmap, pitch, width, height);
+
+ if (drawShipAfterGameplayOverlays)
+ renderShip(renderBitmap, pitch, width, height);
+
+ if (drawGameOp0BTargetingAfterFetch)
+ renderTargeting(renderBitmap, pitch, width, height);
+
handleLevel14Play2BSplice(curFrame, maxFrame);
if (_currentLevel == 4 && _levelGameplayPhase == 2)
@@ -823,9 +836,11 @@ void InsaneRebel1::procPostRendering(byte *renderBitmap, int32 codecparam, int32
// ScummVM helper that groups the common shot/lock overlay calls used by the
// original GAME handlers. GAME 0x1A uses the same pipeline without the target
-// box draw; 0x09/0x0A/0x0B include DrawTargetIndicators first.
+// box draw; 0x09/0x0A/0x0B include DrawTargetIndicators first. GAME 0x0B
+// defers FUN_1CB22 targeting until post-render so FTCH can restore cockpit
+// pixels over shots/boxes while the lock/fire indicator remains visible.
void InsaneRebel1::renderShotOverlayPipeline(byte *dst, int pitch, int width, int height,
- bool drawTargetBoxes) {
+ bool drawTargetBoxes, bool drawTargeting) {
if (drawTargetBoxes) {
renderTargetBoxes(dst, pitch, width, height);
} else {
@@ -842,7 +857,16 @@ void InsaneRebel1::renderShotOverlayPipeline(byte *dst, int pitch, int width, in
_shotSlots[i].timer--;
}
renderGostSlots(dst, pitch, width, height);
- renderTargeting(dst, pitch, width, height);
+ if (drawTargeting)
+ renderTargeting(dst, pitch, width, height);
+}
+
+void InsaneRebel1::renderGameOp0BOverlayDuringChunk(byte *dst, int pitch, int width, int height) {
+ if (_gameOp0BOverlayRenderedThisFrame || !dst || width <= 0 || height <= 0 || _health < 0)
+ return;
+
+ renderShotOverlayPipeline(dst, pitch, width, height, true, false);
+ _gameOp0BOverlayRenderedThisFrame = true;
}
// renderTargetBoxes â FUN_1C940 (0x1C940). Per-target green box overlays.
diff --git a/engines/scumm/smush/rebel/smush_player_ra1.cpp b/engines/scumm/smush/rebel/smush_player_ra1.cpp
index 19add73b0d5..d3343270d9a 100644
--- a/engines/scumm/smush/rebel/smush_player_ra1.cpp
+++ b/engines/scumm/smush/rebel/smush_player_ra1.cpp
@@ -740,7 +740,7 @@ void SmushPlayerRebel1::ra1HandleFrameAudioChunk(int32 subSize, Common::Seekable
void SmushPlayerRebel1::ra1HandleGameFrameChunk(int32 subSize, Common::SeekableReadStream &b, bool fastForwarding) {
if (!fastForwarding && _insane) {
InsaneRebel1 *rebel1 = (InsaneRebel1 *)_insane;
- rebel1->handleGameChunk(subSize, b);
+ rebel1->handleGameChunk(subSize, b, _dst, _width, _height);
}
}
Commit: 12c0e7e2cd6348b67c2faafb0dc3edce1f5dc83c
https://github.com/scummvm/scummvm/commit/12c0e7e2cd6348b67c2faafb0dc3edce1f5dc83c
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-04T19:00:49+02:00
Commit Message:
SCUMM: RA1: correctly render the opening line in the intro
Changed paths:
engines/scumm/insane/rebel1/runlevels.cpp
engines/scumm/smush/rebel/smush_player_ra1.cpp
diff --git a/engines/scumm/insane/rebel1/runlevels.cpp b/engines/scumm/insane/rebel1/runlevels.cpp
index 215fe75864f..8ef89b85847 100644
--- a/engines/scumm/insane/rebel1/runlevels.cpp
+++ b/engines/scumm/insane/rebel1/runlevels.cpp
@@ -144,7 +144,6 @@ static int calculateThresholdBonus(int kills, int perfectThreshold, int perKillT
// ---------------------------------------------------------------------------
// Play a passive cinematic (no game callback, skippable).
-// Reuses RA2's pattern: reset handler, set cinematic flags, play video.
// startFrame > 0: fast-forward (decode without display/audio) to that frame.
void InsaneRebel1::playCinematic(const char *filename, int32 startFrame) {
debugC(DEBUG_INSANE, "InsaneRebel1::playCinematic('%s', startFrame=%d)", filename, startFrame);
@@ -156,7 +155,7 @@ void InsaneRebel1::playCinematic(const char *filename, int32 startFrame) {
restoreScreenFlashPalette();
_interactiveVideoActive = false;
_vm->_smushVideoShouldFinish = false;
- splayer->setCurVideoFlags(0x28); // Cinematic mode + buffer preserve
+ splayer->setCurVideoFlags(0x420);
splayer->setFastForwardFromFrame(0);
splayer->setFastForwardToFrame(startFrame > 0 ? startFrame : 0);
splayer->play(filename, 15);
@@ -320,7 +319,6 @@ void InsaneRebel1::playIntroSequence() {
playCinematic("OPEN/O1LOGO.ANM");
if (shouldAbortGameFlow())
return;
- clearVideoBuffer();
// Star Wars opening crawl (original: PUSH 0x5800, CALL FUN_1BA32)
playCinematic("OPEN/O1OPEN.ANM");
diff --git a/engines/scumm/smush/rebel/smush_player_ra1.cpp b/engines/scumm/smush/rebel/smush_player_ra1.cpp
index d3343270d9a..54d4f029003 100644
--- a/engines/scumm/smush/rebel/smush_player_ra1.cpp
+++ b/engines/scumm/smush/rebel/smush_player_ra1.cpp
@@ -41,6 +41,8 @@
namespace Scumm {
enum {
+ kRA1DecodeWidth = 384,
+ kRA1DecodeHeight = 242,
kRA1PresentationBorder = 4,
kRA1PresentationScreenWidth = 320,
kRA1PresentationScreenHeight = 200,
@@ -326,12 +328,17 @@ bool SmushPlayerRebel1::handleGameTextResource(uint32 subType, int32 subSize, Co
if (subType != MKTAG('T','E','X','T'))
return false;
- // RA1 dialogue subtitles. Only render them when subtitles are enabled â this honors
- // both ScummVM's global "subtitles" setting and the in-game DIALOGUE TEXT toggle
- // (which writes the same ConfMan key). Still return true so the base handler doesn't
- // try to parse RA1's custom TEXT format. Querying ConfMan per chunk also lets the
- // setting take effect mid-video.
- if (ConfMan.getBool("subtitles"))
+ bool forceText = false;
+ if (subSize > 8) {
+ const int64 textStart = b.pos();
+ b.seek(textStart + 8, SEEK_SET);
+ forceText = (b.readByte() == '.');
+ b.seek(textStart, SEEK_SET);
+ }
+
+ // Original FUN_1FDBC draws RA1 TEXT when the text starts with '.' regardless
+ // of the DIALOGUE TEXT option. O1OPEN uses that path for the opening lines.
+ if (forceText || ConfMan.getBool("subtitles"))
ra1HandleText(subSize, b);
return true;
}
@@ -479,9 +486,9 @@ void SmushPlayerRebel1::ra1HandleFade(int32 subSize, Common::SeekableReadStream
bool SmushPlayerRebel1::handleGameAnimHeader(byte *headerContent) {
(void)headerContent;
- _width = 0;
- _height = 0;
- const int bufSize = 384 * 242;
+ _width = kRA1DecodeWidth;
+ _height = kRA1DecodeHeight;
+ const int bufSize = kRA1DecodeWidth * kRA1DecodeHeight;
if (_specialBuffer == nullptr || bufSize > _specialBufferSize) {
free(_specialBuffer);
_specialBuffer = (byte *)calloc(bufSize, 1);
@@ -499,7 +506,7 @@ void SmushPlayerRebel1::handleGameParseNextFrame() {
bool SmushPlayerRebel1::handleGameFrameBufferSelect(int codec, int width, int height) {
// RA1 sub-fullscreen frames render into _specialBuffer at their (left, top) offset position.
- int bufSize = 384 * 242;
+ int bufSize = kRA1DecodeWidth * kRA1DecodeHeight;
if (_specialBuffer == nullptr || bufSize > _specialBufferSize) {
free(_specialBuffer);
_specialBuffer = (byte *)calloc(bufSize, 1);
@@ -512,10 +519,8 @@ bool SmushPlayerRebel1::handleGameFrameBufferSelect(int codec, int width, int he
bool SmushPlayerRebel1::handleGameDimensionOverride(int codec, int width, int height) {
if (_dst == _specialBuffer) {
// RA1: sub-fullscreen FOBJs should not override the 384x242 dimensions.
- if (_width == 0 || _height == 0) {
- _width = 384;
- _height = 242;
- }
+ _width = kRA1DecodeWidth;
+ _height = kRA1DecodeHeight;
return true;
}
return false;
More information about the Scummvm-git-logs
mailing list