Skip to content

1.4.0.6013 alpha: movies in full colour again - #42

Merged
ForkedInTime merged 3 commits into
alphafrom
fix/truecolor-movies
Oct 23, 2026
Merged

ForkedInTime merged 3 commits into
alphafrom
fix/truecolor-movies

Conversation

@ForkedInTime

Copy link
Copy Markdown
Owner

Movies play in full colour again, and this is the 1.4.0.6013 alpha: the fix, its changelog entry and the README correction. Rebase-merge, so the build number at the tag equals the changelog heading (6013) and the README's count (411).

What was wrong

Every movie the game ships (ldata/*.smk) is H.264: intromix, outromix, drag and ea at 1280x800, bullfrog at 2560x960. Up to stable 1.4.0.5660 the fork decoded them to RGBA and drew them through its own GL present layer, scaled linearly. The 2026-09-16 sync (486c8ea) replaced that layer with the team's renderer, whose RendererPresentImage() takes indexed images only. What was left was the old emergency fallback: each frame squeezed into a fixed 6x6x6 colour cube with an 8x8 ordered dither, then enlarged nearest-neighbour in the 8-bit draw surface. Every alpha from 1.4.0.5698 played its movies that way; nothing in QA looked at one, and the workstation ran stable until today.

The fix (376477b)

  • RendererManager.h: PRESENT_FORMAT_RGB24. The format field existed for this; its comment called true-colour formats future work.
  • RendererSoftware: an RGB24 present uploads to a streaming texture of its own (linear scaling), and PresentFrame() draws it in place of the draw surface through the same mapping into the window. An opaque indexed present clears a pending movie frame; destroy_present_target() frees the texture with the renderer.
  • RendererOpenGL::PresentImage: refuses anything but INDEXED8 (its image pass samples through the palette).
  • bflib_fmvids.cpp: each frame is offered as RGB24 first; on refusal the movie keeps the 8-bit path and says so once in the log. Both conversions run before their frame is opened, so a conversion failure cannot leave the draw surface locked.

Checks

On a build of this branch, against the installed 1.4.0.6010 package and stable 5660's engine:

  • Intro at 3440x1440 (qa-harness/intro_shot_1023.py), distinct colours in the centre 800x500 of the same frames: 5660 31,183–82,069; 6010 30–43; this branch 26,841–60,773. Side-by-side crops match 5660; the framing is identical.
  • 2560x960 movie played in the intro's place: full colour, letterboxed, and the menu draws normally when it ends. Escape during the intro: the menu draws normally.
  • RENDERER=OPENGL: the movie plays in 256 colours as before and the log says so once; gl_smoke.py 4/4, with the same 10 warning kinds as 6010.
  • tests/run.sh (14,571 + 36 checks, 0 failed); handpick_1022.py (the hand picks up imps, no Castability warnings); qa_common.py all steps.
  • An independent review of the diff (lifetime, frame open/close balance on every path including exceptions, coordinate mapping, other RendererPresentImage callers, SDL3 return conventions) found no defects. One visible difference: the mouse cursor is not drawn over a movie, as in 5660.

Not changed: the OpenGL renderer's movie path (still 256 colours; a full-colour texture there is a follow-up).

Every movie the game ships (ldata/*.smk) is H.264, not Smacker: intromix,
outromix, drag and ea at 1280x800, bullfrog at 2560x960. Up to 1.4.0.5660
they were decoded to RGBA and drawn by the fork's GL present layer with
linear scaling. The 2026-09-16 sync replaced that layer with the team's
renderer, whose RendererPresentImage() takes indexed images only, so what
was left was the old emergency fallback: each frame squeezed into a fixed
6x6x6 colour cube with an ordered dither, then enlarged nearest-neighbour in
the 8-bit draw surface. Every alpha since 5698 played its movies that way.

The present API gains PRESENT_FORMAT_RGB24 (its format field was there for
it; the comment called true-colour formats future work). The software
renderer uploads such a frame to a texture of its own, scaled linearly, and
PresentFrame() draws it in place of the draw surface through the same
mapping into the window. The OpenGL backend's image pass samples through
the palette, so it refuses RGB24; the movie player then keeps the 8-bit
path for the rest of that movie and says so once in the log.

Measured at 3440x1440 on the same intro frames, distinct colours in the
centre 800x500: stable 5660 31,183-82,069; alpha 6010 30-43; this commit
26,841-60,773, frames matching 5660 side by side. The 2560x960 movie plays
letterboxed, and the main menu draws normally after a skipped intro.
@ForkedInTime
ForkedInTime merged commit 13b5a41 into alpha Oct 23, 2026
1 check passed
@ForkedInTime
ForkedInTime deleted the fix/truecolor-movies branch October 23, 2026 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant