Skip to content

Library: find packages whose name has no title ID by their NCA headers (#1012) - #1013

Closed
Haseenesss wants to merge 2 commits into
LNPANDY:mainfrom
Haseenesss:feat/1012-title-id-from-nca
Closed

Haseenesss wants to merge 2 commits into
LNPANDY:mainfrom
Haseenesss:feat/1012-title-id-from-nca

Conversation

@Haseenesss

Copy link
Copy Markdown
Contributor

Fix or feature

  • Fix
  • Feature

Feature from outside: #1012 has no milestone yet. It needs a maintainer's yes before this can merge.

Stacked on #1009. This branch starts from #1009, which keeps the keys in Settings, so the first commit here is #1009's. Merge #1009 first. This PR then shows only its own commit, Library: find packages whose name has no title ID by their NCA headers (#1012).

What and why

Closes #1012. @Absenti suggested it in #996.

The library scan read a package's title ID only from its file name (Game [0100000000010000][v0].nsp). A renamed NSP, such as Mario.nsp, was not a game of the library, and a renamed update or DLC was not found beside its game. The title ID is also in the package itself. The meta NCA's header holds the content meta's ID at 0x210, and the header is encrypted with header_key, which the keys saved in Settings (#996) have.

  • PackageTitleID (new, app target, next to KeyCheck) reads that ID for an NSP or NSZ whose name has none. It reads the headers as the key check does (KeyCheck.readContainer and KeyCheck.xts, a few kilobytes per file). It takes the meta NCA (content type 1), because an update's program NCA can name the base game. Key values are never logged or shown.
  • GameLibrary.sourceGames(in:repo:headerKey:) uses a resolver for every title ID it needs: the base, its family when it climbs folders, the update and the DLC. A name that holds a title ID still wins, and each file is read at most once per scan. Without saved keys, with a header_key that opens nothing, or for an XCI (its NCAs sit behind a card header), the scan reads names only, as before.
  • GameLibrary.keysFile hands the scan the saved keys (set in LauncherView). Choosing or removing the saved keys scans the library again. The guided setup's games scan gets the setup's keys.
  • A build of such a game stays the scan's entry for it. rememberInputs matches the entry by its base file when the name has no title ID, so it no longer adds a second entry keyed by the file's path. The build itself is unchanged: the script reads the title ID from the package as before (Shell install: take the framework the build wrote, not one named after the build key (#515) #548).

Checked

  • Tests: swift build, then swift test --filter on PackageTitleIDTests, LibraryTests, KeyCheckTests, LiveOnboardingDriverTests and SourceSizeTests, 108 tests, all pass. The pre-push hook ran the full swift test.
  • New PackageTitleIDTests, on synthetic NSPs whose NCAs are only an encrypted header, with a made-up key:
    • The meta NCA names the package, not the program NCA.
    • A renamed base, update and DLC in one folder are one game with all three inputs.
    • Without keys, or with a key that opens nothing, only names count.
    • A name with a title ID wins over the header, and an XCI is not read.
    • header_key is read from the keys file.
    • A real library scan with keysFile finds the renamed game, and a build of it keeps the library's entry.
  • Run on a device or Mac: not run on real game files. There are no dumps on this Mac. The 0x210 and 0x205 offsets are those of the NCA header format (switchbrew, LibHac).

Screenshots

None, no view changed. A renamed game now shows in the library the same way any other game does.

Scope

  • No engine file (dm/, scripts/, docs/, ref/) is added to the repository
  • A fix to the engine or a game profile also goes to seedds/nxnative: not applicable, launcher only
  • A change to a launcher view has before and after screenshots above: no view changed
  • No keys, game files or data extracted from a game in the change or the attachments. The test packages are synthetic and the test key is made up.

🤖 Generated with Claude Code

Haseenesss and others added 2 commits November 9, 2026 10:06
Every Switch build needs prod.keys, and the keys row of the Builds page was
filled per game. A player with one keys file picked it again for each new
game, and a game whose library entry names a keys file that was moved could
not build until it was picked again.

Settings gets a Keys card with the saved prod.keys, Choose and Remove. The
build store keeps the file in the defaults (savedKeysPath). A build whose
keys row is empty, or names a file that is gone, takes the saved keys, and
the row shows them as "Saved in Settings". A Switch 2 game folder needs no
keys and never takes them.

Keys are saved only on an explicit choice: Choose in Settings, a file picked
for the keys row, a keys file dropped itself, or the keys confirmed in the
guided setup. A folder scan or a dropped folder never saves them. Skipping
the keys in the guided setup forgets the saved ones, and an ephemeral setup
run holds the change back until it ends, as its other writes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LNPANDY#1012)

The library scan read a package's title ID only from its file name, so a
renamed NSP (Mario.nsp) was not a game of the library, and a renamed update
or DLC was not found beside its game. The package names it too: the meta
NCA's header holds the content meta's ID at 0x210, encrypted with
header_key, and the keys saved in Settings (LNPANDY#996) have that key.

PackageTitleID reads it the way the key check reads NCA headers
(KeyCheck.readContainer and xts, a few kilobytes per file), for an NSP or
NSZ whose name has no title ID. A name with one still wins. Without saved
keys, with a header_key that opens nothing, or for an XCI, the scan reads
names only, as before. Each file is read at most once per scan.

GameLibrary.keysFile hands the scan the saved keys, the guided setup's scan
gets the setup's keys, and choosing or removing the saved keys scans the
library again. A build of such a game stays the scan's entry for it instead
of adding a second one keyed by the file's path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added launcher The NX2Apple launcher app windows Windows (the Qt front end) labels Nov 9, 2026
@v0lumehi

v0lumehi commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Thank you @Haseenesss. Your change is part of #1097, the launcher UI overhaul, with you as co-author. Closing this one in favor of it. Please have a look there if something of yours is missing or changed.

@v0lumehi v0lumehi closed this Nov 10, 2026
@Haseenesss
Haseenesss deleted the feat/1012-title-id-from-nca branch November 13, 2026 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

launcher The NX2Apple launcher app windows Windows (the Qt front end)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Library: recognize game files whose name has no title ID, from their NCA headers

2 participants