Skip to content

NDSR pack read entry by entry: a program after a 4-byte data entry is no longer stepped over (Ocarina of Time's SMAA weights) - #1353

Closed
lunks wants to merge 1 commit into
seedds:mainfrom
lunks:pr/ndsr-odd-entries
Closed

lunks wants to merge 1 commit into
seedds:mainfrom
lunks:pr/ndsr-odd-entries

Conversation

@lunks

@lunks lunks commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Ocarina of Time (Switch 2, 0400486024DEC000, update v131072; profile in #1299) logs [RED] shader d17eefaff4f0bc23 is not in the shader map and skips that dispatch every frame. It is the SMAA blending-weights program of agl's upscaler, so foliage and prop edges are hard and stair-stepped. #1299's Open list has it: "one shader the scene asks for (d17eefaff4f0bc23) is in none of the shader archives".

It is in the archive. An NDSR pack is a list of 8-byte entries and ndsr_shaders walked two at a time. In the variable-ratio packs (agl_ndsr_vr.pck, agl_ndsr_vr_light.pck) a 4-byte data entry sits between two programs, so the next program falls on an odd entry and was stepped over. The walk now takes single entries and takes only control entries (types 0, 3, 6) as programs. The split of Ocarina's files finds 3 more shaders: d17eefaff4f0bc23, 1fdc85178b60f6ce and 92918e9b7e2f89a4.

Reference entry: Programs on odd entries of an NDSR pack.

Relation to open PRs: #1298 changes records_from in the same function (short packs) and will conflict on that line; #1255 hands another game's NDSR entry to ndsr_shaders and does not touch the walk. Neither changes what this does.

Checked

  • Tests: dm/tools/tests/test_split_ndsr_entries.py (synthetic bytes; 4 subtests fail on main's reader, pass here), test_docs.py, test_nsp_chain.py, test_split_nesting.py, test_split_unreadable.py, test_split_gzip.py, test_split_viper.py, test_split_narc.py. lint_python.py (ruff 0.17.2, pyright 1.1.414): no finding in the changed files; it reports 3 new ones in test_nso_match.py, which this change does not touch.
  • Games run: Ocarina of Time v131072, on our stack (this change plus [WIP] The Legend of Zelda: Ocarina of Time (Switch 2, 0400486024DEC000, v0, SDK 22.2.8) runs on the Mac through the title movie into Kokiri Forest #1299's profile and others). With the shader built, edges were anti-aliased from the outdoor save, by eye; no frame comparison. Donkey Kong Bananza's agl_ndsr.pck gives the same 30 keys as before. Star Fox and Mario Kart World were not re-split.
  • Devices and OS: Apple M5 Pro, macOS 27.
  • shader_split.py is not a chain tool (DMSH_CHAIN unchanged); regress.py was not run.

Docs

  • The finding is in docs/reference/shaders.md and python3 dm/tools/docs_symptoms.py was run (the symptom index)
  • A chain tool changed: not applicable
  • No game files, keys or data extracted from a game in the change or the attachments

…try is no longer stepped over

An NDSR pack is a list of 8-byte entries, and ndsr_shaders walked two at a time. In the variable-ratio packs of agl (Ocarina of Time, Switch 2) a 4-byte data entry sits between two programs, so the next program fell on an odd entry and was stepped over. The log had `[RED] shader d17eefaff4f0bc23 is not in the shader map` with the dispatch skipped every frame, and foliage and prop edges were hard and stair-stepped: d17eefaff4f0bc23 is the upscaler's SMAA blending weights (in a pass dump it reads the edges and the edge list that f8965bffbdf51d78 writes and a 192x128 lookup texture, and sets the 1920x1080 image a335c1db6270c355 reads with the scene).

The walk now takes single entries and takes only control entries (types 0, 3, 6) as programs. The split of Ocarina of Time finds 3 more shaders: d17eefaff4f0bc23, 1fdc85178b60f6ce and 92918e9b7e2f89a4. With d17eefaff4f0bc23, edges were anti-aliased in the game on the stack this was found on. Donkey Kong Bananza's agl_ndsr.pck gave the same 30 keys before and after.

Checked: test_split_ndsr_entries.py (fails 4 subtests on main's reader), test_docs.py, test_nsp_chain.py, the split's other tests. shader_split.py is not part of the chain. Star Fox and Mario Kart World were not re-split.
@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 5, 2026
stan69b pushed a commit to stan69b/nxnative that referenced this pull request Nov 5, 2026
lunks' seedds#1353 (5ec8a62): ndsr_shaders walked an NDSR pack two entries at a
time, so a program after a 4-byte data entry was stepped over. In Ocarina
of Time's variable-ratio packs that left d17eefaff4f0bc23 (the shader the
scene asked for that no archive held, "is not in the shader map"),
1fdc85178b60f6ce and one more out of the split; seedds#1353 ties them to the
SMAA weights. shader_split.py only, not a chain tool.

The reference conflict was two new entries side by side (seedds#1299's NDVE pack
entry and seedds#1353's); both kept, symptom index regenerated. test_docs and
test_split_ndsr_entries pass. Whether d17eefaff4f0bc23 is now in the map is
checked after the next split.
gnosticgeek pushed a commit to gnosticgeek/nxforge that referenced this pull request Nov 5, 2026
gnosticgeek pushed a commit to gnosticgeek/nxforge that referenced this pull request Nov 6, 2026
AnkMister added a commit to AnkMister/nxnative that referenced this pull request Nov 6, 2026
…ee NDSR keys and facts from the corrected split. The splitter algorithm remains behind DM
@seedds

seedds commented Nov 6, 2026

Copy link
Copy Markdown
Owner

Thank you for tracking this down. The missing upscaler shader is handled on main now, so I'm closing this. Final checks on the rebased tree (full shader build, walks, regression) are still running, so please report anything you see.

@seedds seedds closed this Nov 6, 2026
gnosticgeek pushed a commit to gnosticgeek/nxforge that referenced this pull request Nov 6, 2026
) replaces the pull request heads

Upstream landed Ocarina of Time in main (chain adec7d81d970: "holds 60 fps in
Kokiri Forest, 4 GB less") and closed the pull requests it folded in, with
reworded and partly different code. Mixing a pull request head with its landed
version hunk by hunk silently broke things (two GlobalToStorage tables, a
duplicate AF2ip, two mtk_pso definitions), so the rule here is one version per
feature:

- Pull requests upstream closed (seedds#1299, seedds#1300, seedds#1312, seedds#1343, seedds#1345, seedds#1353,
  seedds#1354, seedds#1359, seedds#1360, seedds#1373, seedds#1428, seedds#1430, seedds#1434): their hunks are taken out
  of our side before the three-way merge, so upstream's landed version stands
  alone. Gone with them: bindless pool table patching (reg_bump), the ghost
  table's per-submission hold, the growing raw pool table and its write-log
  sizing, seedds#1428's pool_buf spares (upstream's pool_table_take is the same
  idea), the ixc-based indirect mesh draw (upstream uses mdx), and their tests
  (t_pool_table, t_mesh_indirect, t_gmem_raw, finalized_bindless_pool,
  test_bnsh_nvn2, test_ndve).
- Open pull requests that upstream's landing supersedes: seedds#1394 (upstream's
  mtl_pool_addressed) and seedds#1393 pool_skip_retired (upstream's budgeted pool
  walk; the profile does not use it) are dropped with their tests and docs.
  seedds#1368's mesh pipeline prewarm is dropped too: upstream kept the background
  build in nvn_geometry.inc, and the prewarm's mtk_build / mtk_claim /
  g_warm_mps went with it.
- Kept, as upstream does not have them: NXForge's own features (GPU watchdog,
  present filters and anti-aliasing, aniso floor, quick settings, pipeline
  archive compaction, upload breakdown, memory report lines) and the still
  open pull requests seedds#1304, seedds#1305, seedds#1308, seedds#1320, seedds#1331, seedds#1332, seedds#1355, seedds#1356,
  seedds#1369, seedds#1376, seedds#1377, seedds#1379, seedds#1382, seedds#1390, seedds#1391, seedds#1392, seedds#1414, seedds#1420,
  seedds#1436, seedds#1439, seedds#1446, seedds#1453.
- Combined where both sides changed the same lines: GW_N 1 << 16 with seedds#1320's
  wide-write intervals (GW_PAGES = SBW_WPAGES, 128 slots), the CPU upload log
  with upstream's linear upload route, arch_open_end before the compaction
  limit, cbn_prog in geo_gs_one (seedds#1382).
- Translator: upstream's sources and binaries, plus seedds#1414's
  InstEmitAmpereMem diff and the LDSM SubgroupBarrier in
  InstEmitAmpereTensor.cs. The binaries and dmsh_chain.lock are upstream's
  until the Mac rebuilds them (dotnet publish, tool_lock --update-lock,
  dmsh_chain --header); dmsh_chain.h is regenerated for now.
- RED_ONCE keys: upstream took 153 and 154, so the present anti-aliasing lines
  move to 156 and 157 and seedds#1420's packaged-entry line to 158 (array 159).
- Host: hle_net.c and t_net_eventfd.c are upstream's (its eventfd poll waits
  out the whole timeout, which our 5d7920c fixed another way).
- Kept ours: dm/tools/romfs_image.py and its test, so the 26 GB RomFS image is
  not packed again.

dm/tools tests on Linux: same failures as on 875449e (Linux-only quirks),
plus test_nlg4 and test_dmsh_pool_arrays, which fail on upstream main too.
Not yet built on the Mac.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016qteK29T18U8p1c9LsVY8g
gnosticgeek pushed a commit to gnosticgeek/nxforge that referenced this pull request Nov 6, 2026
seedds#1299's and seedds#1353's heads

Both pull requests are closed upstream and landed in main in their own form
(nvn2_stage, the NDSR entry walk); the merge had kept the heads' versions of
the same code beside them, as those hunks did not conflict. NXForge's own
readers (HAL .cmp, YCD) stay. dm/tools tests: no change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016qteK29T18U8p1c9LsVY8g
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