Repository navigation
Description
What happened
Advance Wars 1+2: Re-Boot Camp aborts about a minute into play, when a CO power was triggered by the enemy, on the Mac (shortly after play starts, every time), with a fatal NVN command-list check in nvn_queue_submit:
[dm] FATAL NVN command list 0x7cd96c2740: record {op 8, size 504} at 0x10ce43000, 0 bytes into its piece of 16 at 0x10ce43000
[dm] CRASH sig=6 addr=__pthread_kill+0x8 pc=__pthread_kill+0x8 lr=pthread_kill+0x128 sp=0x11e766e70
[dm] bt: abort+0x94 nvn_queue_submit+0x468 dm_bigstack_ret+0 main+0x92bb58 main+0x8c1bac main+0x8c24e8 main+0x8ba5d8 main+0x976a4c sdk+0x33e7a8 sdk+0x342f74 dm_thread_enter+0x18
The same record (op 8, size 504, 0 bytes into a 16-byte piece) is reported in every crashing run. The check is the one at dm/gfx/nvn/nvn_queue.inc:229.
Bisected to f02d047 (PR #1609)
The game works in a build from before 10 November, so I built only the Mac host at three revisions and ran each with the same rewritten modules, the same RomFS, the same shader library (b-94ec9a118fb3) and a fresh copy of the same save, playing to the same point:
| host | revision | result |
|---|---|---|
| C | main (637f3fa) | FATAL at 67.6 s |
| B | f02d047 | FATAL at 68.5 s, same record {op 8, size 504} |
| A | f02d047^ (629dd75) | no error, played past it to 94 s |
f02d047 ("NVN recordings take no more command memory than the driver's commands", PR #1609) moved recordings' ends, links and calls into control memory and introduced this check. It touches only host files (hle_nvn.c, nvn_queue.inc, nvn_obj.h).
Note on the test: A and B were built with DMSH_CHAIN set to 94ec9a118fb3 so they load the current shader library (the game draws nothing without it). That changes only which library is loaded, not the command-list code; the A/B difference is f02d047 alone. A revert of f02d047 on main does not apply cleanly (conflicts in hle_nvn.c and nvn_queue.inc), so I did not test that.
Register dump at the abort, in case it helps: x24 = 0x10ce43000 (the piece, memory pool +0x200000) holds 0x1f800000008, i.e. the 8-byte header of a 504-byte op-8 record, and x26 points into the command list (0x7cd96c2748). So the queue reads a record header where it expects a 16-byte piece.
[dm] *x5: 0x7cd96c2740 0x8 0x1f8 main+0x502b000 0 0x10
[dm] *x24: 0x1f800000008 0x1 main+0x502b0f8 0 0 0
[dm] *x26: 0x40002000219c8600 0x400d100021a08600 0x4009400f9973584d 0x4000200021988600 0x4017f000219c8600 0x602be00f997358e1
[dm] *x27: main+0x502b0f8 0 0 0 0 0
[dm] x24 0x10ce43000: memory pool 0x10cc43000..0x10d243000 (+0x200000)
[dm] x27 0x10ce43010: memory pool 0x10cc43000..0x10d243000 (+0x200010)
What you expected
The game keeps running, as it does with f02d047^.
Game, title ID and version
Advance Wars 1+2: Re-Boot Camp, 0100300012F2A000, 1.0.0 (v0), no update, no DLC
nxnative commit
637f3fa (main); bisected to f02d047
Shader chain version
94ec9a118fb3
How it was built and run
Mac app (--platform mac-app); the bisect runs used the host from a terminal (--platform mac style run command)
Device and OS
Apple M5 Pro, 48 GB, macOS 27.2.1
Settings and environment overrides
Mac app defaults (DM_OPMODE=1, DM_PSO_MTL4=1, DM_PSO_PREBUILD=1, DM_PRESENT_UPSCALE=off); bisect runs: none besides the run command's own (DM_WINDOW=1, DM_AUDIO=0, DM_LANG=en-US).
Logs
Excerpts above; the full logs can be attached on request.
- Nothing attached here contains game files, keys or data extracted from a game.
Activity
seedds commentedon Nov 13, 2026
Thanks for the bisect and the register dump: the control entries in
x26were enough to find the writer.The game's Unity rendering plugin (
main+0x1545800) rotates three command buffers, one 1 MB block each (pool +0, +0x200000, +0x400000). For each render event it waits on the fence it recorded in that buffer last time, re-adds the block from its start, records, and hands the handle to Unity, which calls it into the frame's list. A frame normally has two events. Your list has four: B's fence-only recording, C, A, then B again. So the plugin re-recorded B's block while the frame's list, not yet submitted, still called the 16-byte fence piece. On the console the GPU just runs whatever bytes are there. Before f02d047 the host's CALL record ran the newer recording twice, unnoticed; since then the submit-time check aborted.a780d2c makes a piece run what its command memory holds at submit: the whole records that fit, as the GPU does. A record that doesn't fit ends the piece with a
[RED] NVN command list … was recorded over after it was calledline instead of aborting. Reference: docs/reference/nvn-objects.md, "A called recording recorded over before its caller is submitted".I couldn't reach a CO power here (no save that far), so the fixed path is covered by
t_nvn, not by the game. Could you retest at the same point with your save? If it misbehaves, please attach the log with its[RED]lines and reopen.nvn/queue: run what a called piece holds at submit, not abort on it