A // on a metas[] line hides the rows after it on that line, and the game then ends at start with "FATAL: cfg:
NX2NAVI_<X> has no row in the settings table"; that shipped in two test builds and nothing caught it before a
start. And 15 names the runtime reads were not in known[], so setting any of them in nx2navi.ini logged "unknown
key" and put it in the menu's list of unknown keys although it took effect: AUDIO_DUMP, DEFER_STAMP, DEPTH_TWIN,
DLAA_ZFIT, DUMP_SKIP_RUNS, DUMP_TEX, DUMP_UBO, EVENT_ORDER, GATHER_BIAS, PIN_SWEEP, REC_CHECK, REC_DELAY_US,
REG_ORDER, SHADOW and ZERO_LOCALS (GATHER_BIAS and ZERO_LOCALS through vk_caps.c env_u32).
tests/cfg_rows_check.py (standard library only) parses known[], metas[], sections[], DECK[] and LOWEND[] by
brace matching that skips string and character literals and comments (an apostrophe in a comment inside a table
would otherwise open a character literal and run the table on past its end), line by line with the first // outside
a string split off, and the first #if branch standing for the table. It fails on a row or name after //, a /* in a table, a name twice in known[], two metas[] rows for a
key, a metas[] row not in known[], a cfg_value/cfg_int/cfg_bool/cfg_double read (directly or through one level of
wrapper) with no row and no cfg_get, cfg_is_set or cfg_meta guard earlier in the same function (kernel.c SPIN and
SVC_WAITS, vk_headroom.c VRAM_HEADROOM pass that way), and a name read through cfg_get, cfg_is_set, cfg_meta,
rt_knob, a cfg_get or "NX2NAVI_%s" wrapper, or a patches-v111.txt set line that is not in known[] or a cheat.
--self-test puts each kind of fault into a copy and checks it is caught. The content guard workflow runs the
check after tools/check_content.py. The 15 names go into known[] on a line of their own with no //.
Reproduced before the change: the check reported the 15 names on stability-pass, as the audit's prototype did.
Now it reports 0 problems and its self-test catches all 15 injected faults; the scratchpad cfg rows check
("missing []"), cfg_parse_check and the compile checks pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The release is assembled on Windows, and the AppImage needs Linux (the translator's native build and
appimagetool), so releases carried no Linux download. .github/workflows/linux-appimage.yml runs when a
release is published, or by hand for a tag: it builds the translator, takes the button art from the
release's own app zip, runs tools/make_appimage.py, checks that the AppImage starts and uploads it with
its SHA-256 to that release. tools/make_appimage.py takes --prompt-art as make_kit.py does and bundles
pillow, so an AppImage build can draw the Xbox, PlayStation and keyboard prompts.
Pull request #273 by loteran, taken as it is. Added: the workflow installs glslc and spirv-tools, which
make_appimage.py needs since the runtime's shaders are compiled at build time.
The workflow does nothing until this file is on the repository's default branch on GitHub; from then on
every published release starts it, with write access to that release. It was not run here, and
make_appimage.py only passes a syntax check on Windows.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>