Skip to content

Dump folders without a base game, with program/<n> folders, and a Switch 2 Edition's program 1 - #1253

Open
capibawa wants to merge 2 commits into
seedds:mainfrom
capibawa:dump-program-folders
Open

capibawa wants to merge 2 commits into
seedds:mainfrom
capibawa:dump-program-folders

Conversation

@capibawa

@capibawa capibawa commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

What and why

A dumper can write a game's update and DLC with no base/ folder, each version split into program/<n>/{exefs,romfs}, and a DLC under <n>/base/ or <n>/updates/<version>/, each optionally under program/0/. pack_dump.py read none of these, and a dump of Xenoblade Chronicles 2 Nintendo Switch 2 Edition stopped with "program ID 0400E95004038001 is not a base title ID".

pack_dump.py now takes these layouts and gets the title ID from program 0's NPDM, the DLC or --title-id. A Switch 2 Edition's update packs its Switch 2 program by default (--program N picks another), each program with its own RomFS. build_ipa_from_nsp.py prefers a profile for the packed program's own ID.

Checked

  • Tests: dm/tools/tests/test_nsp_dump.py (new cases: updates only, a DLC update winning, the Switch 2 Edition program ID, program/ folders, packing program 0 of several, refusals), test_docs.py.
  • Games run: the Xenoblade Chronicles 2 Nintendo Switch 2 Edition dump (update 1114112, 7 DLC) packs program 1 and plays with its profile (a later PR).
  • Devices and OS: Apple M3 Pro, macOS 27.0.1.
  • Tool change, reach limited to dump folders: scripts/regress.py check --quick on Donkey Kong Bananza 040074A01BF12000, Fire Emblem Fortune's Weave 04007EF01F8AE000 and Hello Kitty Party Land 01001340271EC000, with all of this work together: PASS (0 newly failing, 0 changed MSL). These are the local builds; none has a route, so the harness ran no boot runs. Its report is from before the rebase on current main.

Docs

  • README.md and docs/development.md describe the layouts; no reference entry needed
  • No game files, keys or data extracted from a game in the change or the attachments

🤖 Generated with Claude Code

…a Switch 2 Edition's program 1 pack: the NSP script builds from the Switch 2 program by default

A dumper can write a game's update and DLC with no base/ folder (an update's files are whole), each version split into program/<n>/{exefs,romfs}, and a DLC under <n>/base/ or <n>/updates/<version>/, each optionally under program/0/. pack_dump.py read none of these, and for a dump of Xenoblade Chronicles 2 Nintendo Switch 2 Edition (update 1114112) the scan stopped with "program ID 0400E95004038001 is not a base title ID": the update's program 1 is the Switch 2 game, which names a program of its own.

pack_dump.py now finds the base game optional beside an update, the program folders, the DLC layouts (the newest DLC update wins), and takes the title ID from program 0's NPDM, else from the DLC, else from --title-id. A Switch 2 Edition's update packs program 1 by default (--program N picks another); each program is packed with its own RomFS, as Horizon mounts it. build_ipa_from_nsp.py passes --program for a dump folder and prefers a profile for the packed program's own ID.

Checked: test_nsp_dump.py (updates only, a DLC update winning, the Switch 2 Edition program ID, program/ folders, packing program 0 of several, refusals) and test_docs.py; the Xenoblade Chronicles 2 dump packs program 1 (13.1 GB) and its seven DLC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@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 4, 2026
… does: lint-python's new finding on this change

pyright: Operator "/" not supported for "None" at is_dump, since program_dir returns None when an index names a program the folder lacks. is_dump passes no index, so it never crashed; the guard is the walrus the updates scan already uses. Checked with CI's pinned tools (dm/tools/lint_python.py --against origin/main: this finding gone; dm/games/settings.py:115 remains, red on main since 4e0333a and not from this change) and test_nsp_dump.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ishtiaq156

Copy link
Copy Markdown
Contributor

Updated the author-preserving #1253 integration against upstream f20f6507. It retains capibawa's Program 1 implementation, fixes version-specific profile selection (--package v0 stays Program 0; Edition uses Program 1), and reconciles current icon/survey behavior. 318/318 focused dump, NUP, Mac, profile and documentation tests passed. No game assets or RESTBL workaround. This is a fork-only integration candidate; #1253's original branch is unchanged. #1586 remains separate.

ishtiaq156 added a commit to ishtiaq156/nxnative that referenced this pull request Nov 11, 2026
Retain the newer --icon guidance while passing the selected Program 1 launch ID to Mac app packaging. Keep the original application ID for update/DLC selection and preserve iOS, NSP, NUP, Program 0 and explicit bundle-ID behavior.

Checked: 147 focused headless tests on refreshed main; 107 combined seedds#1253/seedds#1586 integration tests in an isolated worktree. No gameplay or full app rebuild for this identity-only sync.
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