[Scummvm-git-logs] scummvm master -> 36bedd9b41f28bcde89ec009407d296ce6f5af69
neuromancer
noreply at scummvm.org
Sat Sep 5 11:01:14 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:
a8e95537b4 SCUMM: RA1: allow to select both paths in L8
36bedd9b41 SCUMM: RA1: make sure cutscenes fill the screen
Commit: a8e95537b47613ca620c45eb01a9e9ef5515f3bd
https://github.com/scummvm/scummvm/commit/a8e95537b47613ca620c45eb01a9e9ef5515f3bd
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-09-05T12:33:52+02:00
Commit Message:
SCUMM: RA1: allow to select both paths in L8
Changed paths:
engines/scumm/insane/rebel1/iact.cpp
engines/scumm/insane/rebel1/render.cpp
engines/scumm/insane/rebel1/runlevels.cpp
diff --git a/engines/scumm/insane/rebel1/iact.cpp b/engines/scumm/insane/rebel1/iact.cpp
index e9d38369534..1a799bbbbf7 100644
--- a/engines/scumm/insane/rebel1/iact.cpp
+++ b/engines/scumm/insane/rebel1/iact.cpp
@@ -694,8 +694,8 @@ void InsaneRebel1::checkDynamicLevelBranch(int32 curFrame) {
return;
if ((_currentLevel == 6 || _currentLevel == 7) && _pendingRouteIndex >= 0) {
- const uint32 routeFrame = (_currentLevel == 6 && curFrame >= 0) ?
- (uint32)curFrame : (uint32)_gameCounter;
+ const uint32 routeFrame = (curFrame >= 0) ?
+ (uint32)curFrame : (uint32)_currentSmushFrame;
if (!_vm->_smushVideoShouldFinish &&
_pendingRouteCutoverFrame >= 0 &&
routeFrame >= (uint32)_pendingRouteCutoverFrame) {
@@ -707,9 +707,8 @@ void InsaneRebel1::checkDynamicLevelBranch(int32 curFrame) {
_vm->_smushVideoShouldFinish = true;
const int32 resumeFrame = (_currentLevel == 6 && _pendingRouteStartFrame < 0) ?
0 : _pendingRouteStartFrame;
- debugC(DEBUG_INSANE, "L%d cutover: route=%d -> %d at %s=%u (resumeFrame=%d)",
+ debugC(DEBUG_INSANE, "L%d cutover: route=%d -> %d at localFrame=%u (resumeFrame=%d)",
_currentLevel + 1, _levelRouteIndex, _pendingRouteIndex,
- _currentLevel == 6 ? "localFrame" : "frame",
(unsigned)routeFrame, (int)resumeFrame);
}
return;
@@ -1512,7 +1511,7 @@ void InsaneRebel1::updateGameOp0BPhysics() {
bool level8WalkerPlayerHit = false;
if (_currentLevel == 7) {
- const uint16 walkerFrame = (uint16)_gameCounter;
+ const uint16 walkerFrame = (uint16)_currentSmushFrame;
level8WalkerPlayerHit = hasLevel8WalkerPlayerHit(_levelRouteIndex, walkerFrame,
_perspectiveX, _perspectiveY);
// Player collision and boss damage are tracked separately.
diff --git a/engines/scumm/insane/rebel1/render.cpp b/engines/scumm/insane/rebel1/render.cpp
index db1f6f364f8..957d149ec53 100644
--- a/engines/scumm/insane/rebel1/render.cpp
+++ b/engines/scumm/insane/rebel1/render.cpp
@@ -1773,7 +1773,7 @@ void InsaneRebel1::renderHUD(byte *dst, int pitch, int width, int height) {
_hudDirtyFlag = 0xFF;
}
-// Each route has up to 3 attack windows. -2 means disabled.
+// Each route has up to 3 attack windows, indexed by ANM-local frame. -2 means disabled.
const int16 InsaneRebel1::kWalkerAttackWindow1[3] = { 2588, 2323, 877 };
const int16 InsaneRebel1::kWalkerAttackWindow2[3] = { 1709, 1444, -2 };
const int16 InsaneRebel1::kWalkerAttackWindow3[3] = { 262, -2, -2 };
@@ -1781,7 +1781,7 @@ const int16 InsaneRebel1::kWalkerAttackWindow3[3] = { 262, -2, -2 };
void InsaneRebel1::updateLevel8WalkerState() {
if (_walkerHealth >= 11) {
_walkerHealth = (int16)(100 - (_killCount + (_killCount >> 2)));
- } else if (_walkerHealth > 0 && (_gameCounter & 3) == 0) {
+ } else if (_walkerHealth > 0 && (_currentSmushFrame & 3) == 0) {
_walkerHealth--;
}
@@ -1791,7 +1791,7 @@ void InsaneRebel1::updateLevel8WalkerState() {
}
int route = CLIP(_levelRouteIndex, 0, 2);
- uint16 fc = (uint16)_gameCounter;
+ uint16 fc = (uint16)_currentSmushFrame;
const int16 *windows[3] = {
&kWalkerAttackWindow1[route],
@@ -1831,7 +1831,7 @@ void InsaneRebel1::updateLevel8WalkerState() {
_walkerBranchChoice = (_shipPosX < 0xA0) ? 1 : 2;
}
} else {
- if ((_gameCounter & 7) == 0)
+ if ((fc & 7) == 0)
playSfx(kSfxLockOn, 127, 0);
}
}
@@ -1853,12 +1853,14 @@ void InsaneRebel1::updateLevel8WalkerState() {
newRoute = 2;
}
- if (newRoute != 0 && newRoute != route) {
+ if (newRoute != 0) {
_pendingRouteIndex = newRoute;
- _pendingRouteCutoverFrame = _gameCounter + 7;
- _pendingRouteStartFrame = _pendingRouteCutoverFrame;
- debugC(DEBUG_INSANE, "L8 branch: route=%d -> %d at frame=%u shipX=%d resumeTimelineFrame=%d cutoverFrame=%d",
- route, newRoute, (unsigned)_gameCounter, _shipPosX,
+ _pendingRouteCutoverFrame = _currentSmushFrame + 7;
+ // The destination starts at frame 1, advanced by the source tail
+ // already displayed. This also applies when repeating the same route.
+ _pendingRouteStartFrame = 1 + (_pendingRouteCutoverFrame - _currentSmushFrame);
+ debugC(DEBUG_INSANE, "L8 branch: route=%d -> %d at localFrame=%u shipX=%d resumeLocalFrame=%d cutoverFrame=%d",
+ route, newRoute, (unsigned)fc, _shipPosX,
(int)_pendingRouteStartFrame, (int)_pendingRouteCutoverFrame);
}
_walkerBranchChoice = 0;
@@ -1871,7 +1873,7 @@ void InsaneRebel1::renderLevel8Overlay(byte *dst, int pitch, int width, int heig
if (_currentLevel != 7)
return;
- if (_walkerHealth > 0 && (_walkerHealth >= 16 || (_gameCounter & 2) != 0)) {
+ if (_walkerHealth > 0 && (_walkerHealth >= 16 || (_currentSmushFrame & 2) != 0)) {
int16 projX = 0x61, projY = 0x8D;
projectGameplayPoint(projX, projY);
projX = (int16)(0x61 - ((projX - 0x61) >> 2));
@@ -1889,7 +1891,7 @@ void InsaneRebel1::renderLevel8Overlay(byte *dst, int pitch, int width, int heig
&kWalkerAttackWindow2[route],
&kWalkerAttackWindow3[route]
};
- int16 frameNum = (int16)(uint16)_gameCounter;
+ int16 frameNum = (int16)(uint16)_currentSmushFrame;
bool inWindow = false;
bool inDirectionalPhase = false;
@@ -1933,7 +1935,7 @@ void InsaneRebel1::renderLevel8Overlay(byte *dst, int pitch, int width, int heig
viewportX + 0xA8 - parallaxX, viewportY + 0x93 - parallaxY, "<<u");
}
} else {
- if ((_gameCounter & 4) == 0) {
+ if ((frameNum & 4) == 0) {
int16 projX = 0, projY = 0;
projectGameplayPoint(projX, projY);
int16 drawX = (int16)(0xA9 - (projX >> 2));
diff --git a/engines/scumm/insane/rebel1/runlevels.cpp b/engines/scumm/insane/rebel1/runlevels.cpp
index 86859ec13b2..14ad794e5ec 100644
--- a/engines/scumm/insane/rebel1/runlevels.cpp
+++ b/engines/scumm/insane/rebel1/runlevels.cpp
@@ -72,59 +72,6 @@ int32 findAnimFrameChunkOffset(ScummEngine_v7 *vm, const char *filename, int32 t
return result;
}
-int32 findAnimFrameChunkOffsetByGameCounter(ScummEngine_v7 *vm, const char *filename, int32 targetCounter, int32 &localFrame) {
- localFrame = 0;
- if (targetCounter <= 0)
- return 0;
-
- ScummFile *file = vm->instantiateScummFile();
- if (!vm->openFile(*file, Common::Path(filename))) {
- delete file;
- return -1;
- }
-
- int32 result = -1;
- if (file->size() >= 8) {
- file->readUint32BE();
- const uint32 animSize = file->readUint32BE();
- const int64 animEnd = MIN<int64>((int64)file->pos() + animSize, file->size());
-
- int32 frameIndex = 0;
- RA1AnimStreamChunkIterator chunks(*file, animEnd);
- RA1AnimChunk chunk;
- while (chunks.next(chunk)) {
- if (chunk.tag == MKTAG('F', 'R', 'M', 'E')) {
- RA1AnimStreamChunkIterator subChunks(*file, chunk.endOffset);
- RA1AnimChunk subChunk;
- while (subChunks.next(subChunk)) {
- if (subChunk.tag == MKTAG('G', 'A', 'M', 'E') && subChunk.size >= 8) {
- const uint32 opcode = file->readUint32BE();
- const int32 counter = (int32)file->readUint32BE();
- if (opcode == 0x0B && counter >= targetCounter) {
- localFrame = frameIndex;
- result = (int32)chunk.offset;
- break;
- }
- }
-
- subChunks.skip(subChunk);
- }
-
- if (result >= 0)
- break;
-
- frameIndex++;
- }
-
- chunks.skip(chunk);
- }
- }
-
- file->close();
- delete file;
- return result;
-}
-
void InsaneRebel1::formatTargetAccuracy(char *dst, size_t dstSize, int kills, int targetCount, bool perfectText) const {
if (perfectText && kills >= targetCount)
Common::sprintf_s(dst, dstSize, "%s", uiStr(kR1StrAccuracyPerfect));
@@ -816,7 +763,7 @@ bool InsaneRebel1::runLevel8() {
if (_walkerHealth <= 0)
break;
- if (_pendingRouteIndex >= 0 && _pendingRouteIndex != route) {
+ if (_pendingRouteIndex >= 0) {
// Branch to the next walker route while preserving active state.
routeStartFrame = _pendingRouteStartFrame;
route = _pendingRouteIndex;
@@ -1597,21 +1544,18 @@ void InsaneRebel1::resolveSeek(const char *filename, int32 startFrame, int32 &vi
(int)videoStartFrame, (unsigned)videoOffset);
}
} else if (_currentLevel == 7 && resumingRoute) {
- videoOffset = findAnimFrameChunkOffsetByGameCounter(_vm, filename, startFrame, videoStartFrame);
- if (videoOffset < 0) {
- debugC(DEBUG_INSANE, "L8 resume: route=%d timelineFrame=%d GAME counter lookup failed",
- _levelRouteIndex, (int)startFrame);
- videoStartFrame = startFrame;
- videoOffset = findAnimFrameChunkOffset(_vm, filename, videoStartFrame);
- }
+ // Walker routes restart at their own local frame, even when branching
+ // back to the same ANM. Their embedded GAME counters are not seek targets.
+ videoStartFrame = startFrame;
+ videoOffset = findAnimFrameChunkOffset(_vm, filename, videoStartFrame);
if (videoOffset < 0) {
- debugC(DEBUG_INSANE, "L8 resume: route=%d timelineFrame=%d localFrame=%d offset lookup failed",
- _levelRouteIndex, (int)startFrame, (int)videoStartFrame);
+ debugC(DEBUG_INSANE, "L8 resume: route=%d localFrame=%d offset lookup failed",
+ _levelRouteIndex, (int)videoStartFrame);
videoStartFrame = 0;
videoOffset = 0;
} else {
- debugC(DEBUG_INSANE, "L8 resume: route=%d timelineFrame=%d -> localFrame=%d offset=0x%x",
- _levelRouteIndex, (int)startFrame, (int)videoStartFrame, (unsigned)videoOffset);
+ debugC(DEBUG_INSANE, "L8 resume: route=%d localFrame=%d offset=0x%x",
+ _levelRouteIndex, (int)videoStartFrame, (unsigned)videoOffset);
}
} else if (_currentLevel == 13 && resumingRoute) {
// L14PLY2B is already the continuation clip. Preserve state, but do not seek.
@@ -1622,8 +1566,9 @@ void InsaneRebel1::resolveSeek(const char *filename, int32 startFrame, int32 &vi
void InsaneRebel1::captureInteractiveVideoInput() {
const bool level7RouteSplice = (_currentLevel == 6 && _levelRouteIndex > 0);
- const bool walkerRouteReplay = (_currentLevel == 7 && _walkerRoundReplay);
- const bool preserveInputState = _preserveInteractiveRuntimeState || level7RouteSplice || walkerRouteReplay;
+ const bool walkerRouteContinuation = (_currentLevel == 7 &&
+ (_walkerRoundReplay || _pendingRouteStartFrame > 0));
+ const bool preserveInputState = _preserveInteractiveRuntimeState || level7RouteSplice || walkerRouteContinuation;
enableIOSGamepadController();
Commit: 36bedd9b41f28bcde89ec009407d296ce6f5af69
https://github.com/scummvm/scummvm/commit/36bedd9b41f28bcde89ec009407d296ce6f5af69
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-09-05T13:00:59+02:00
Commit Message:
SCUMM: RA1: make sure cutscenes fill the screen
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 b2dae0b0a61..d5d7890ac6d 100644
--- a/engines/scumm/smush/rebel/smush_player_ra1.cpp
+++ b/engines/scumm/smush/rebel/smush_player_ra1.cpp
@@ -1113,8 +1113,7 @@ void SmushPlayerRebel1::handleGameUpdateScreen(const byte *src, int srcPitch, in
height = MIN(height, _ra1FadeFrameHeight);
}
- if (!_insane || !static_cast<InsaneRebel1 *>(_insane)->isInteractiveVideoActive() ||
- _vm->_screenWidth != kRA1PresentationScreenWidth ||
+ if (_vm->_screenWidth != kRA1PresentationScreenWidth ||
_vm->_screenHeight != kRA1PresentationScreenHeight) {
SmushPlayer::handleGameUpdateScreen(src, srcPitch, width, height);
ra1RememberDisplayedFrame(_ra1FadeFrame, _ra1FadeFrameSize,
@@ -1124,15 +1123,17 @@ void SmushPlayerRebel1::handleGameUpdateScreen(const byte *src, int srcPitch, in
return;
}
- int ra1ViewX = _ra1ViewportOffsetX;
- int ra1ViewY = _ra1ViewportOffsetY;
+ const bool interactive = _insane && static_cast<InsaneRebel1 *>(_insane)->isInteractiveVideoActive();
+ const int ra1ViewX = interactive ? _ra1ViewportOffsetX : 0;
+ const int ra1ViewY = interactive ? _ra1ViewportOffsetY : 0;
const byte *sourceBase = useFadeFrame ? src : _dst;
const int sourcePitch = useFadeFrame ? srcPitch : _width;
const int sourceWidth = useFadeFrame ? width : _width;
const int sourceHeight = useFadeFrame ? height : _height;
- const int srcX = useFadeFrame ? 0 : CLIP(_scrollX + ra1ViewX + kRA1PresentationBorder, 0, sourceWidth - 1);
- const int srcY = useFadeFrame ? 0 : CLIP(_scrollY + ra1ViewY + kRA1PresentationBorder, 0, sourceHeight - 1);
+ // Retained FADE frames already use screen coordinates, including the border.
+ const int srcX = CLIP((useFadeFrame ? 0 : _scrollX + ra1ViewX) + kRA1PresentationBorder, 0, sourceWidth - 1);
+ const int srcY = CLIP((useFadeFrame ? 0 : _scrollY + ra1ViewY) + kRA1PresentationBorder, 0, sourceHeight - 1);
int frameWidth = MIN<int>(sourceWidth - srcX, kRA1PresentationWidth);
int frameHeight = MIN<int>(sourceHeight - srcY, kRA1PresentationHeight);
@@ -1149,7 +1150,8 @@ void SmushPlayerRebel1::handleGameUpdateScreen(const byte *src, int srcPitch, in
}
memset(_ra1PresentationBuffer, 0, presentationSize);
- // Interactive gameplay draws a 312x192 viewport inside a black 320x200 frame.
+ // RA1 presents a 312x192 viewport inside a black 320x200 frame, including
+ // cinematics. The four-pixel inset keeps scenery outside cockpit overlays hidden.
const byte *dst = sourceBase + srcY * sourcePitch + srcX;
byte *presentationDst = _ra1PresentationBuffer +
kRA1PresentationBorder * kRA1PresentationScreenWidth + kRA1PresentationBorder;
diff --git a/engines/scumm/smush/rebel/smush_player_ra1.h b/engines/scumm/smush/rebel/smush_player_ra1.h
index fbcdfc05650..19c57ffb130 100644
--- a/engines/scumm/smush/rebel/smush_player_ra1.h
+++ b/engines/scumm/smush/rebel/smush_player_ra1.h
@@ -85,7 +85,7 @@ private:
int32 _ra1CleanFrameSize;
bool _ra1HasCleanFrame;
- // Interactive movies present a 312x192 viewport inside a black frame.
+ // Movies present a 312x192 viewport inside a black frame.
byte *_ra1PresentationBuffer;
int32 _ra1PresentationBufferSize;
More information about the Scummvm-git-logs
mailing list