WIP: feat(builder): accept .nx archives (NXFormat) as the game files #685

Draft
nussico wants to merge 1 commit from nussico/Longshot:builder/nx-format into main
First-time contributor

Type: feat · Risk: low · Tested on: Windows 11, RTX 2070 · Needs: Linux, any GPU

Why

Players who keep their game as a .nx file (NXFormat, github.com/fab918/nxformat, made with nxconvert pack-nup) have to convert it back to a .nup or to folders before Longshot can build. With this PR the builder takes the .nx directly.

What changed

make_game.py now reads a .nx archive wherever it reads a .nup: it tells the two apart by the file's first bytes and runs a new reader for the .nx. The reader reuses nup.py's extraction, so path checks, progress and the damaged-.zs list behave the same, and every file is checked against its SHA-256 in the archive.

  • nx2: nx2/nxar.py (class Nx and a CLI like nup.py's) reads NX 0.2 and 0.3 archives holding exefs/romfs trees. A .nx holding NCA files (nxconvert pack) is refused with a message saying how to convert it. nx2/test_nxar.py builds archives from the spec, game-free.
  • nx2: nx2/nup.py: the step after extraction (plain NSOs, ZBIC) moved into plain_modules(), which nxar.py calls too. The .nup path is unchanged.
  • make_game: package_script() in nx2/make_game.py picks nx2/nxar.py or nx2/nup.py by the NXAR magic, in check() and in main()'s extraction; --nup and --game help mention .nx. Test: tests/test_make_game_package_script.py.
  • game files: .gitignore ignores *.nx and scripts/release.py's NOT_A_RELEASE_FILE refuses .nx (a .nx is a whole dump); CONTRIBUTING lists it with the game files.
  • docs: README (game copy section and command line), website/src/content/docs/requirements.mdx (its copy) and docs/development.md.

The launcher's side (finding, browsing and dropping .nx files) is a separate PR on LongshotLauncher, and needs a Longshot release with this change.

Measurements

Nothing to measure in the game: this changes only how the builder reads the game file; the build it makes and the game are unchanged (see Testing for the extraction check and its speed).

Flags and settings

None

Testing

Tested: On Windows 11 build 26300 (llvm-mingw 20260616), with my own copy, the same code in Hookshot's tree (this PR is that change with Longshot's names). The game files never left my PC.

  • The .nx and the .nup of the same game hold the same 186,592 files by path, size and SHA-256, with byte-identical exefs and build id e0f3ccfa.
  • Every file of the .nx decoded and SHA-256-checked: 26.27 GB in 158 s from disk (166 MB/s).
  • make_game.py --check --nup <file.nx>: "This is the version ... supports (build e0f3ccfa)."
  • A build from the .nx extracted all 186,592 files, made main a plain NSO and translated 100% of the code. The game it built starts and plays (NVIDIA GeForce RTX 2070, driver 32.0.16.2101).
  • In this tree: nx2/test_nxar.py and tests/test_make_game_package_script.py pass. python -I -B tests/run_all.py: 504 passed, 19 failed, 72 skipped; the same 19 fail on main @ 53f96d7 on this PC: test_appimage_player_build, test_cpm_discovery, test_cpp_preflight, test_crash_dialog, test_cv_signal_race, test_env_on, test_fpx_sticky, test_lift_cleanup_error, test_linux_preflight, test_make_game_cache, test_make_game_prepare, test_missing_nup, test_oot_state_tap, test_readback_late, test_spawn_emit, test_tested_configurations, test_vk_pgo, test_vram_budget_row, test_walk_key.

Not tested: A build from this Longshot branch in the game (only Hookshot's tree with the same change); Linux (I have no Linux PC).

Must be tested:

  • Linux, any GPU: run python -I nx2/make_game.py --check --nup <your .nx> and then a build with --nup <your .nx> (a .nx made from your .nup with nxconvert pack-nup), expecting the check to report build e0f3ccfa and the game to start (by hand: a tester with a .nx, since the farm's copies are .nup).

Risks

What could break: Only a file starting with NXAR goes to the new reader; every .nup still goes to nup.py, whose extraction is unchanged except that its last step moved into a function.

Turning it off: revert the commit.

Compatibility: Nothing changes for a player who builds from a .nup or folders: no saves, options, caches or vk ABI touched.

Issues

Fixes #411

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named).
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Docs updated.
**Type:** feat · **Risk:** low · **Tested on:** Windows 11, RTX 2070 · **Needs:** Linux, any GPU ## Why Players who keep their game as a `.nx` file (NXFormat, github.com/fab918/nxformat, made with `nxconvert pack-nup`) have to convert it back to a `.nup` or to folders before Longshot can build. With this PR the builder takes the `.nx` directly. ## What changed `make_game.py` now reads a `.nx` archive wherever it reads a `.nup`: it tells the two apart by the file's first bytes and runs a new reader for the `.nx`. The reader reuses `nup.py`'s extraction, so path checks, progress and the damaged-`.zs` list behave the same, and every file is checked against its SHA-256 in the archive. - nx2: `nx2/nxar.py` (class `Nx` and a CLI like `nup.py`'s) reads NX 0.2 and 0.3 archives holding exefs/romfs trees. A `.nx` holding NCA files (`nxconvert pack`) is refused with a message saying how to convert it. `nx2/test_nxar.py` builds archives from the spec, game-free. - nx2: `nx2/nup.py`: the step after extraction (plain NSOs, ZBIC) moved into `plain_modules()`, which `nxar.py` calls too. The `.nup` path is unchanged. - make_game: `package_script()` in `nx2/make_game.py` picks `nx2/nxar.py` or `nx2/nup.py` by the NXAR magic, in `check()` and in `main()`'s extraction; `--nup` and `--game` help mention `.nx`. Test: `tests/test_make_game_package_script.py`. - game files: `.gitignore` ignores `*.nx` and `scripts/release.py`'s `NOT_A_RELEASE_FILE` refuses `.nx` (a `.nx` is a whole dump); CONTRIBUTING lists it with the game files. - docs: README (game copy section and command line), `website/src/content/docs/requirements.mdx` (its copy) and `docs/development.md`. The launcher's side (finding, browsing and dropping `.nx` files) is a separate PR on LongshotLauncher, and needs a Longshot release with this change. ## Measurements Nothing to measure in the game: this changes only how the builder reads the game file; the build it makes and the game are unchanged (see Testing for the extraction check and its speed). ### Flags and settings None ## Testing **Tested:** On Windows 11 build 26300 (llvm-mingw 20260616), with my own copy, the same code in Hookshot's tree (this PR is that change with Longshot's names). The game files never left my PC. - The `.nx` and the `.nup` of the same game hold the same 186,592 files by path, size and SHA-256, with byte-identical exefs and build id `e0f3ccfa`. - Every file of the `.nx` decoded and SHA-256-checked: 26.27 GB in 158 s from disk (166 MB/s). - `make_game.py --check --nup <file.nx>`: "This is the version ... supports (build e0f3ccfa)." - A build from the `.nx` extracted all 186,592 files, made `main` a plain NSO and translated 100% of the code. The game it built starts and plays (NVIDIA GeForce RTX 2070, driver 32.0.16.2101). - In this tree: `nx2/test_nxar.py` and `tests/test_make_game_package_script.py` pass. `python -I -B tests/run_all.py`: 504 passed, 19 failed, 72 skipped; the same 19 fail on `main` @ 53f96d7 on this PC: test_appimage_player_build, test_cpm_discovery, test_cpp_preflight, test_crash_dialog, test_cv_signal_race, test_env_on, test_fpx_sticky, test_lift_cleanup_error, test_linux_preflight, test_make_game_cache, test_make_game_prepare, test_missing_nup, test_oot_state_tap, test_readback_late, test_spawn_emit, test_tested_configurations, test_vk_pgo, test_vram_budget_row, test_walk_key. **Not tested:** A build from this Longshot branch in the game (only Hookshot's tree with the same change); Linux (I have no Linux PC). **Must be tested:** - Linux, any GPU: run `python -I nx2/make_game.py --check --nup <your .nx>` and then a build with `--nup <your .nx>` (a `.nx` made from your `.nup` with `nxconvert pack-nup`), expecting the check to report build e0f3ccfa and the game to start (by hand: a tester with a `.nx`, since the farm's copies are `.nup`). ## Risks **What could break:** Only a file starting with `NXAR` goes to the new reader; every `.nup` still goes to `nup.py`, whose extraction is unchanged except that its last step moved into a function. **Turning it off:** revert the commit. **Compatibility:** Nothing changes for a player who builds from a `.nup` or folders: no saves, options, caches or vk ABI touched. ## Issues Fixes #411 ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [x] Docs updated.
feat(builder): accept .nx archives (NXFormat) as the game files
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 17s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Guide screenshots / Guide images and local UI source review (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
012546faae
HumanBean force-pushed builder/nx-format from 012546faae
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 17s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Guide screenshots / Guide images and local UI source review (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
to c9d3ac620f
Some checks failed
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 6s
CI / Conventional Commit title (pull_request) Successful in 5s
CI / Workflow lint (actionlint) (pull_request) Successful in 8s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 9s
Third-party parts / As their notes say (pull_request) Successful in 15s
Website / Website on Cloudflare (pull_request_target) Has been skipped
2026-11-15 18:46:26 +00:00
Compare
Owner

Rebased onto main @ 7bacf846: no conflicts. No tests were run here; the test boxes stay yours.

Rebased onto `main` @ 7bacf846: no conflicts. No tests were run here; the test boxes stay yours.
Some checks failed
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 6s
CI / Conventional Commit title (pull_request) Successful in 5s
CI / Workflow lint (actionlint) (pull_request) Successful in 8s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 9s
Third-party parts / As their notes say (pull_request) Successful in 15s
Website / Website on Cloudflare (pull_request_target) Has been skipped
This pull request is marked as a work in progress.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'builder/nx-format:nussico-builder/nx-format'
git switch 'nussico-builder/nx-format'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!685
No description provided.