Skip to content

packing/shader_split: read loose .nvn program files - #2669

Open
bensaadmucret wants to merge 1 commit into
seedds:mainfrom
bensaadmucret:pr-nvn-loose
Open

bensaadmucret wants to merge 1 commit into
seedds:mainfrom
bensaadmucret:pr-nvn-loose

Conversation

@bensaadmucret

@bensaadmucret bensaadmucret commented Nov 14, 2026 •

Copy link
Copy Markdown

What

A reader for loose .nvn program files: one compiled NVN program behind a 16-byte header {control length, control offset, code length, code offset}, then the control section and the code area it names.

Why

Vengeance Hunters (01008EF020C98000) ships its eight shaders as loose *_vs.nvn / *_fs.nvn files in the RomFS. The file has no magic, so the generic prefilter dropped it before scan_blob could look inside, and the split stopped with [RED] the shader split found no shaders in main or the RomFS.

scan_file_in now tries nvn_loose on every file it loads: the header's two {length, offset} pairs must stay in the file and name a control section and a code area of the right magic; the stage comes from the SPH as usual, and check still verifies the control's own code length. The programs are single-stage, so '#NVN@' keys pair through the pixel-input cover like the other single-stage sources.

Checked

  • build_ipa_from_nsp.py on Vengeance Hunters splits its 8 shaders (1 vertex, 7 pixel) and the packed Mac app reaches its frame loop at 60 fps with no red line
  • test_split_nvn.py: a synthetic .nvn per stage, non-minimal offsets, and the four rejection shapes (control or code magic absent, offset out of the file, short file)
  • test_split_* suite: 87 tests pass; test_docs: 6/6

Docs

  • docs/reference/shaders.md: new entry "Loose .nvn program files"; docs_symptoms.py run (index regenerated)

Found on Vengeance Hunters (01008EF020C98000), no profile yet; tracked at LNPANDY/NX2Apple#1309.

@github-actions github-actions Bot added packing Building an IPA or a Mac app: the NSP script, extraction, the shader split, the packers tools Tools and scripts (dm/tools, scripts) docs Documentation labels Nov 14, 2026
Vengeance Hunters keeps its eight shaders as loose *_vs.nvn / *_fs.nvn
files in the RomFS, each one NVN program behind a 16-byte header
{control length, control offset, code length, code offset}. The file
has no magic, so the generic prefilter dropped it before scan_blob
could look inside, and the split stopped with 'found no shaders in
main or the RomFS'.

scan_file_in now tries nvn_loose on every file it loads: the header's
two {length, offset} pairs must stay in the file and name a control
section and a code area of the right magic, the stage from the SPH as
usual. The programs are single-stage; '#NVN@' keys pair through the
pixel-input cover like the other single-stage sources.

Checked: build_ipa_from_nsp.py on Vengeance Hunters splits its 8
shaders (1 vertex, 7 pixel) and the packed Mac app reaches its frame
loop at 60 fps with no red line; test_split_nvn covers each stage,
non-minimal offsets and the four rejection shapes.

Found on Vengeance Hunters (01008EF020C98000), no profile yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation packing Building an IPA or a Mac app: the NSP script, extraction, the shader split, the packers tools Tools and scripts (dm/tools, scripts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants