Add nxdoom linum - #3681
Merged
Merged
Conversation
The blit assumed a 32-bit frame buffer: it wrote a uint32_t per pixel and converted the palette with ARGBTO32 as it went, so the image came out wrong anywhere else. It also drew at the origin, leaving the image in a corner of a display it does not fill, and indexed the source by the output column, which costs a division for every pixel of every frame. Convert the palette once per palette change into the format the frame buffer actually uses, map output columns to source columns through a table built at startup, and centre the result. Output rows that come from the same source row are copied rather than converted again. Four options are added, all off by default, so that a board can trade memory for speed where it pays: GAMES_NXDOOM_FB_CMAP blits palette indices and lets a frame buffer that has a colour map do the conversion in hardware. GAMES_NXDOOM_FILLSCREEN stretches the image over the whole display rather than scaling it by a whole number. GAMES_NXDOOM_ROWSTAGE builds each row in a staging buffer so that the frame buffer only sees burst-friendly copies. GAMES_NXDOOM_STATIC_SCRNBUF places the render target in .bss, which keeps it out of external memory on a board whose heap is mostly that. On an STM32H753 driving a 1024x600 panel from SDRAM, the last two are worth 2.7x together. Also open the frame buffer with O_CLOEXEC. Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
JorgeGzm
force-pushed
the
add_nxdoom_linum
branch
from
July 30, 2026 03:53
a68063e to
a5c6e88
Compare
jerpelea
approved these changes
Jul 30, 2026
Contributor
Author
|
This PR is being tested with PR apache/nuttx#19579 |
xiaoxiang781216
approved these changes
Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The NXDoom blit assumed a 32-bit frame buffer. It wrote a
uint32_tper pixeland converted the palette with
ARGBTO32as it went, so the image came outwrong on anything else. It also drew at the origin, leaving the image in a
corner of a display it does not fill, and indexed the source by the output
column, which costs an integer division for every pixel of every frame.
The palette is now converted once per palette change into the format the frame
buffer actually reports, output columns are mapped to source columns through a
table built at startup, and the result is centred. Output rows that come from
the same source row are copied rather than converted again.
Four options are added, all disabled by default, so a board can trade memory
for speed where it pays:
GAMES_NXDOOM_FB_CMAP: blit palette indices and let a frame buffer that hasa colour map do the conversion in hardware while it scans out.
GAMES_NXDOOM_FILLSCREEN: stretch over the whole display rather thanscaling by a whole number.
GAMES_NXDOOM_ROWSTAGE: build each row in a staging buffer so the framebuffer only sees burst-friendly copies.
GAMES_NXDOOM_STATIC_SCRNBUF: place the render target in.bss, keeping itout of external memory on a board whose heap is mostly that.
The frame buffer is also now opened with
O_CLOEXEC.Impact
n, so a build that does notenable them takes the same path as before. One behaviour changes for
everyone: the image is now centred rather than drawn in the corner of a
display it does not fill (no change where it fills exactly, such as the
simulator).
handled; previously only 32 worked.
scale) the output is unchanged.
colmap[x] = x * 320 / outwwas verified toequal the old
x / scalefor every column at every scale from 1 to 8 (zerodifferences), and the palette table uses the same
ARGBTO32.Testing
Host: Linux x86_64.
Boards: LINUM-STM32H753BI (1024x600 LTDC panel, frame buffer in SDRAM), and
the simulator.
nxstylereports 0 warnings ongames/NXDoom/src/i_video.c. Builds arewarning-free.
This branch was also built against a nuttx tree with the companion change
reverted, to reproduce what CI does (each repository is built against the
other's master).
sim:nxdoombuilds clean, confirming this PR has nocross-repository dependency.
Regression, existing configurations:
sim:nxdoom, no new option enabledraspberrypi-4b:nxdoom, no new option enabledsimset to the Raspberry Pi 4B geometrylinum-stm32h753bi:nxdoom, all options onBoth existing configurations were built with none of the new options enabled,
which is the path they take by default.
The Raspberry Pi 4B is the case where the image does not fill the display: its
frame buffer is 1920x1080 at 32 bpp, so DOOM is scaled by 5 to 1600x1000 and is
now centred rather than drawn in the corner. I have the board's toolchain but
not the board, so in addition to building it I reproduced its geometry in the
simulator and ran the game there, which exercises the same non-filling, centred
path.
Simulator run, no new option enabled:
Effect of the options, measured on the LINUM board at 1024x600 with a frame
counter added temporarily to
i_finish_update(), playing the same attract-modedemo:
ROWSTAGESTATIC_SCRNBUF