From c7e72149f12e18ad955cb2cb391fd3d5832a8fda Mon Sep 17 00:00:00 2001 From: Andrew Quenehen Date: Thu, 6 Aug 2026 08:43:32 -0300 Subject: [PATCH] Tighten Switch docs prose and drop filler patterns. --- README.md | 9 +-- docs/switch-build.md | 34 +++++------ docs/switch-install.md | 77 +++++++++++++------------ docs/switch-transfer.md | 34 +++++------ docs/updater.md | 6 +- native/switch-ota-launcher/README.md | 18 +++--- scripts/switch/ota_launcher.manifest | 2 +- scripts/switch/selftest_build_switch.sh | 4 +- src/update/SwitchOta.lua | 2 +- test/switch-nro-ota.spec.test.js | 4 +- tests/switch_ci_workflows_test.lua | 4 +- tests/switch_transfer_docs_test.lua | 6 +- tools/switch-probe/README.md | 6 +- 13 files changed, 102 insertions(+), 104 deletions(-) diff --git a/README.md b/README.md index 878d612e..7bf9e554 100644 --- a/README.md +++ b/README.md @@ -235,12 +235,13 @@ Releases ship an SD-ready `gen1recomp-*-switch.zip`. Runtime target is pinned [love-nx](https://github.com/retronx-team/love-nx) `11.5-nx1`. Requires a console that can run Switch homebrew. -- Players: [docs/switch-install.md](docs/switch-install.md) — download the +- Players: [docs/switch-install.md](docs/switch-install.md). Download the zip, extract at the microSD root (install or update), title-override launch, import your own legal ROM, Joy-Con controls and shortcuts. -- Builders: [docs/switch-build.md](docs/switch-build.md) — `--fetch` / - `--loose` / `--fused`, toolchain, Docker fallback, and **CI vs release** - (path-gated ubuntu selftest, canonical fused PR artifact, release hard-fail). +- Builders: [docs/switch-build.md](docs/switch-build.md). `--fetch` / + `--loose` / `--fused`, toolchain, Docker fallback, and CI vs release + (path-gated ubuntu selftest, fused PR artifact on the main repo, release + hard-fail). - File transfer (MTP / SD / FTP): [docs/switch-transfer.md](docs/switch-transfer.md). ## Modding diff --git a/docs/switch-build.md b/docs/switch-build.md index 5367513c..9593524c 100644 --- a/docs/switch-build.md +++ b/docs/switch-build.md @@ -1,7 +1,7 @@ -# Build the Nintendo Switch NRO — contributor guide +# Build Gen1Recomp for Nintendo Switch Want to play a release build instead? Download the SD-ready zip and extract it -at your microSD root — see [switch-install.md](switch-install.md). +at your microSD root. See [switch-install.md](switch-install.md). This guide is for contributors who build Gen1Recomp for Switch from source. @@ -14,7 +14,7 @@ This guide is for contributors who build Gen1Recomp for Switch from source. ## Prerequisites by OS All packaging entrypoints are **bash**. On Windows, use Git Bash, MSYS2, or -WSL — not cmd.exe or PowerShell (AD-008). +WSL, not cmd.exe or PowerShell (AD-008). ### macOS / Linux @@ -25,7 +25,7 @@ WSL — not cmd.exe or PowerShell (AD-008). sudo dkp-pacman -S switch-dev ``` -3. OTA launcher toolchain — **native or Docker** (either is fine): +3. OTA launcher toolchain, **native or Docker** (either is fine): ```sh bash scripts/switch/install_devkitpro_deps.sh # native @@ -51,7 +51,7 @@ scripts/switch/build_ota_launcher.sh # host-test first; NRO needs DEVKITPRO/Do `--fused` always builds the fused game, native OTA launcher, and dual-NRO SD zip. The same `*-switch.zip` is the OTA download asset. **DEVKITPRO is -required.** OTA launcher: native packages **or** Docker — both are supported. +required.** OTA launcher: native packages **or** Docker. Both are supported. Release-like build from repo root: @@ -70,14 +70,14 @@ See `native/switch-ota-launcher/README.md` and - **WSL** (Ubuntu/etc.) with the Linux pacman flow above, or - **Git Bash** for `--fetch` / `--loose`; for `--fused` prefer MSYS2 or WSL if Docker bind-mounts from Git Bash paths misbehave. -2. Install `switch-dev` (or rely on Docker fallback — see below). +2. Install `switch-dev` (or rely on Docker fallback; see below). 3. Do **not** expect `scripts/build_switch.sh` to run under cmd/PowerShell. ### What you must install yourself | You install | Script does **not** install | | ----------- | --------------------------- | -| bash, git, zip tooling the repo already expects | — | +| bash, git, zip tooling the repo already expects | (none) | | `dkp-pacman` + `switch-dev` + OTA packages **or** Docker | `dkp-pacman -S …` | | A legal `.gb` ROM (to play) | Any ROM or game data | @@ -96,7 +96,7 @@ See `native/switch-ota-launcher/README.md` and Rules: - `--fetch` alone is fine; combine as `--fetch --loose` or `--fetch --fused`. -- `--loose` and `--fused` are **XOR** — pick one packaging path per run. +- `--loose` and `--fused` are **XOR**. Pick one packaging path per run. - `--version X.Y.Z` sets the NACP / filename version (defaults to short git SHA). ### What `--fetch` downloads @@ -172,7 +172,7 @@ the NX runtime modules `src/core/NxAssetOverlay.lua`, `src/core/Platform.lua`, `tests/engine/switch_diagnostics_test.lua`, `tests/engine/platform_nx_*`, or the Switch-related workflow YAML), CI runs: -1. **Offline selftest** on `ubuntu-latest` (forks **and** the canonical repo): +1. **Offline selftest** on `ubuntu-latest` (forks **and** the main repo): `scripts/switch/selftest_build_switch.sh`, `scripts/switch/verify_payload.sh --self-test`, `luajit tests/switch_ci_workflows_test.lua`, @@ -180,14 +180,10 @@ or the Switch-related workflow YAML), CI runs: headlessly (`luajit tests/engine/assets_version_fallback_test.lua`, `luajit tests/engine/nx_generated_guard_test.lua`, `luajit tests/engine/nx_yellow_boot_test.lua`). -2. **Fused NRO build** only on the **canonical** repository +2. **Fused NRO build** only on the **main** repository (`bryanthaboi/gen1recomp`), on the self-hosted Mac runner (`scripts/build_switch.sh --fetch --fused`), and only when the workflow - head is that repo (same-repo push/PR). **Fork repository** CI never runs - fused. **Fork → canonical PRs** also skip Switch fused (offline selftest - still runs) so untrusted head code is not executed on the self-hosted Mac; - iOS device build eligibility is unchanged. Fused also waits for a successful - offline selftest before starting on the Mac runner. + head is that repo (same-repo push/PR). Fork CI never runs fused. Fork PRs into the main repo also skip Switch fused (offline selftest still runs) so untrusted head code is not executed on the self-hosted Mac; iOS device build eligibility is unchanged. Fused also waits for a successful offline selftest before starting on the Mac runner. 3. On successful PR fused builds, a follow-up workflow posts a PR comment linking the Actions artifact named `gen1recomp-switch-nro` (comment tag `switch-build-result`; see @@ -198,7 +194,7 @@ Unrelated PRs do not burn the self-hosted Mac on Switch packaging. ### Release hard-fail (`.github/workflows/release.yml`) GitHub Releases always build Switch on the same self-hosted Mac runner as the -other platforms — this is a **hard gate** (no `continue-on-error`): +other platforms. This is a **hard gate** (no `continue-on-error`): ```sh scripts/build_switch.sh --fetch --fused --version "" @@ -221,7 +217,7 @@ sudo dkp-pacman -S switch-dev export DEVKITPRO=/opt/devkitpro export PATH="$DEVKITPRO/tools/bin:$PATH" -# OTA launcher — pick one: +# OTA launcher: pick one bash scripts/switch/install_devkitpro_deps.sh # native # or ensure Docker is installed (same pin as fused builds) ``` @@ -240,8 +236,8 @@ These scripts and this guide do **not**: - Push files to the console (no automated MTP / FTP / SD scripting) - Bundle or download any Pokémon ROM - Install `dkp-pacman` / `switch-dev` for you -- Provide `nxlink` / netloader deploy (deferred — see [switch-transfer.md](switch-transfer.md)) -- Validate **Applet Mode** — use title override (hold **R**) for full memory +- Provide `nxlink` / netloader deploy (deferred; see [switch-transfer.md](switch-transfer.md)) +- Validate **Applet Mode**. Use title override (hold **R**) for full memory Player install steps: [switch-install.md](switch-install.md). Manual transfer (MTP / SD / FTP, macOS / Linux / Windows): diff --git a/docs/switch-install.md b/docs/switch-install.md index 4f4c69e4..2a54aa06 100644 --- a/docs/switch-install.md +++ b/docs/switch-install.md @@ -2,7 +2,7 @@ Every GitHub Release that includes Switch support ships an SD-ready zip: `gen1recomp-*-switch.zip`. Extract it at the root of your microSD (install -**or** update — same steps), launch with **title override**, then import your +or update, same steps), launch with **title override**, then import your own legal `.gb` ROM. > You need a console that can run Switch homebrew (custom firmware / hbmenu). @@ -34,7 +34,8 @@ sdmc:/switch/gen1recomp/pokemon-love2d/imports/saves/... ``` Older single-NRO zips only had `gen1recomp.nro` (the fused game). Current -releases use the dual-NRO layout above — open `gen1recomp` in hbmenu (the launcher). +releases use the dual-NRO layout above. Open `gen1recomp` in hbmenu (the +launcher). Merge folders if your OS asks. Any method works: **MTP** (DBI → Run MTP responder + a client), **direct SD** (Hekate UMS or a card reader), or **FTP**. @@ -45,25 +46,25 @@ macOS, Linux, and Windows: [switch-transfer.md](switch-transfer.md). #### Native OTA launcher (in-console) -On Switch, over-the-air updates are handled by the **native OTA launcher** -(DEVKITPRO / libnx + curl), **not** by the LÖVE self-updater -(`src/update/Check.lua`). The hbmenu entry is the launcher NRO -(`gen1recomp.nro`). If a newer release exists it may download the same -`gen1recomp-*-switch.zip` used for install, verify SHA-256 from -`sha256sums.txt`, replace **both** `gen1recomp-game.nro` and -`gen1recomp.nro` (so the NACP version matches the release for hbmenu / -Sphaira), then hand off via `envSetNextLoad`. When you are already up to -date (or offline), the launcher stays quiet and opens the game with no -UI. When an update is available it shows a short screen in the same visual -language as the in-game launcher (black field, RGB rail, logo, A/B buttons). -Saves under `pokemon-love2d/` are never touched. Protocol -contract: `src/update/SwitchOta.lua`. +Switch OTA runs in a separate **native launcher NRO** (libnx + curl), not the +LÖVE self-updater (`src/update/Check.lua`). hbmenu opens `gen1recomp.nro`. + +When a newer release exists, the launcher downloads the same install zip +(`gen1recomp-*-switch.zip`), checks SHA-256 against `sha256sums.txt`, replaces +both `gen1recomp-game.nro` and `gen1recomp.nro` (keeps NACP version in sync +for hbmenu and Sphaira), then loads the game with `envSetNextLoad`. + +If you are up to date or offline, it skips straight to the game with no +prompt. If an update is available, you get a short prompt styled like the +in-game launcher: black background, RGB rail, logo, A/B buttons. Saves under +`pokemon-love2d/` are not touched. See `src/update/SwitchOta.lua` for the +wire format. The LÖVE self-updater stays **disabled** on NX (`networkValidated == false`). **Sphaira forwarder (HOME shortcut):** Sphaira copies name/version/icon into the installed forwarder at creation time. After an OTA (or zip) update, the -`.nro` on the microSD already has the new version — but the HOME shortcut +`.nro` on the microSD already has the new version, but the HOME shortcut keeps the old badge until you **reinstall the forwarder once** in Sphaira (Install Forwarder again on `gen1recomp.nro`). Browsing the NRO in Sphaira / hbmenu always shows the live file version. @@ -72,7 +73,7 @@ hbmenu always shows the live file version. Use the **same** extract/merge of `gen1recomp-*-switch.zip`. It replaces the NROs (and the small help `README.txt` / `INSTALL.txt` files). Saves, -imported ROMs, mods, and options live under `pokemon-love2d/` — **do not +imported ROMs, mods, and options live under `pokemon-love2d/`. **Do not delete that folder** when updating, or you will lose progress. ## 3. Launch with title override @@ -80,7 +81,7 @@ delete that folder** when updating, or you will lose progress. **Applet Mode is not supported** for this game (not enough memory). 1. On the Switch HOME menu, highlight any installed title. -2. Hold **R** and launch that title — this opens hbmenu with full memory +2. Hold **R** and launch that title. This opens hbmenu with full memory (title override). 3. From hbmenu, open `gen1recomp`. @@ -94,14 +95,14 @@ This project ships **no** game data. On first launch: (`.gbc`) dump into `switch/gen1recomp/pokemon-love2d/imports/` (the launcher also shows the live save-dir path). All three can sit in the same folder. -2. Use **Scan again** on that game’s tab (Red / Blue / Yellow). Rescan - matches by ROM SHA-1 for the open tab only — a Red dump never imports +2. Use **Scan again** on that game's tab (Red / Blue / Yellow). Rescan + matches by ROM SHA-1 for the open tab only. A Red dump never imports from the Yellow tab (and vice versa). ## 5. Import / Export a raw `.sav` Continue a cart or PC battery save (or pull a slot off-console) via MTP / -SD / FTP — same transfer methods as ROMs. Paths are **per game**: +SD / FTP, same transfer methods as ROMs. Paths are **per game**: | Game | Import inbox | Export folder | | ---- | ------------ | ------------- | @@ -109,19 +110,19 @@ SD / FTP — same transfer methods as ROMs. Paths are **per game**: | Blue | `imports/saves/blue/` | `exports/blue/` | | Yellow | `imports/saves/yellow/` | `exports/yellow/` | -(Under the save dir `pokemon-love2d/` — the zip already creates these folders.) +(Under the save dir `pokemon-love2d/`. The zip already creates these folders.) -1. Copy a Gen1 `.sav` (32 KB) into that game’s inbox under the save dir +1. Copy a Gen1 `.sav` (32 KB) into that game's inbox under the save dir ([switch-transfer.md](switch-transfer.md)). -2. With the game’s ROM already imported, open **that game’s tab** → +2. With the game's ROM already imported, open **that game's tab** → **SAVE FILES** → **Import save**. Only that folder is scanned. 3. A successful import retires the file to `*.sav.imported` and records its content hash so pressing **Import save** again does not clone slots. Failed imports leave the original `.sav` in place. 4. To pull a slot off the console, use **Export save**, then copy the file - from that game’s **`exports//`** folder via MTP / SD / FTP. + from that game's **`exports//`** folder via MTP / SD / FTP. -Do not put `.sav` files into git. Prefer clean copies — some MTP clients +Do not put `.sav` files into git. Prefer clean copies. Some MTP clients create `._*.sav` AppleDouble sidecars that are not real saves. ## Controls @@ -158,12 +159,12 @@ create `._*.sav` AppleDouble sidecars that are not real saves. Mods install from a zip inbox (same transfer methods as ROMs): 1. Copy a release `.zip` into the save-dir **`imports/mods/`** path the - launcher shows (MTP / SD / FTP — [switch-transfer.md](switch-transfer.md)). + launcher shows (MTP / SD / FTP. See [switch-transfer.md](switch-transfer.md)). 2. In the launcher, open **MODS** → **Scan again** → enable the mod → **Play**. Remote **FIND MODS** / GitHub download stays **off** on Switch. Do not put -mod zips into git. Community mods ship their own OPTIONS / rebinds — this port +mod zips into git. Community mods ship their own OPTIONS / rebinds. This port does not document third-party control tables. ### Joy-Con shortcuts (Select + face) @@ -185,16 +186,16 @@ If the handheld stutters with extras on, try **OPTIONS → PERFORMANCE** → ## Limitations -- **Homebrew required** — custom firmware and hbmenu; this project does not help - set that up. -- **Title override required** — hold **R** when launching a title for full - memory. Applet Mode (Album) is not supported. -- **Manual file transfer** — ROMs, mods, and saves are copied via MTP, direct - SD, or FTP; there is no automated deploy. -- **No LÖVE self-updater** — in-console updates use the native OTA launcher - only. Remote **FIND MODS** / GitHub download stays off on Switch. -- **Hardware** — tested on Switch OLED; Switch V1 / Erista boot confirmed by the - community. Other models may work but are less tested. +- You need homebrew (custom firmware, hbmenu). This project does not set that + up. +- Launch with title override (hold **R** on a title). Applet Mode (Album) is + not supported. The game needs full memory. +- ROMs, mods, and saves are copied manually via MTP, direct SD, or FTP. There + is no automated deploy. +- Updates use the native OTA launcher only. The LÖVE self-updater and remote + **FIND MODS** stay off on Switch. +- Tested on Switch OLED. Switch V1 / Erista boot confirmed by the community. + Other models may work but are less tested. ## Prefer building it yourself? diff --git a/docs/switch-transfer.md b/docs/switch-transfer.md index 3c1477af..1e53de2f 100644 --- a/docs/switch-transfer.md +++ b/docs/switch-transfer.md @@ -1,16 +1,16 @@ # Switch file transfer (MTP / SD / FTP) -Canonical ways to put Gen1Recomp artifacts and inbox files onto a Nintendo -Switch. **Any method is valid** if the bytes land in the destinations below. +Ways to put Gen1Recomp artifacts and inbox files onto a Nintendo Switch. +**Any method is valid** if the bytes land in the destinations below. -This is the home runbook for contributors on **macOS, Linux, and Windows**. +This is the runbook for contributors on **macOS, Linux, and Windows**. Player install (what to download, title override) stays in [switch-install.md](switch-install.md). Packaging stays in [switch-build.md](switch-build.md). > **Not supported yet:** `nxlink` / hbmenu netloader automation. Useful later -> for a fast contrib rebuild loop; deferred on purpose (AD-009). Do not treat -> netloader as the release or ROM/mod install path. +> for a fast contrib rebuild loop; deferred (AD-009). Do not treat netloader as +> the release or ROM/mod install path. --- @@ -22,7 +22,7 @@ Player install (what to download, title override) stays in | Loose iteration pair | `sdmc:/switch/gen1recomp/gen1recomp.nro` **and** `game.love` beside it | | ROM inbox | LÖVE save dir → `imports/` (launcher shows the live `getSaveDirectory()` path; under MTP often `1: SD Card//imports/`) | | Mod zip inbox | Same save dir → `imports/mods/` then MODS → **Scan again** | -| Save `.sav` inbox | Same save dir → `imports/saves/red\|blue\|yellow/` then that game’s SAVE FILES → **Import save** | +| Save `.sav` inbox | Same save dir → `imports/saves/red\|blue\|yellow/` then that game's SAVE FILES → **Import save** | | Save exports | Same save dir → `exports/red\|blue\|yellow/` (pull after **Export save**; MTP / SD / FTP) | | Opt-in diagnostics | Empty `switch-debug.txt` in the save dir → `switch.log` | | Lua error log | `lua-error.log` in the save dir | @@ -33,7 +33,7 @@ files, or third-party mod zips to git. --- -## Canonical methods +## Transfer methods ### 1. MTP (DBI responder + host client) @@ -47,7 +47,7 @@ before launching. #### macOS (example: OpenMTP) [OpenMTP](https://github.com/ganeshrvel/openmtp) is a documented example for -macOS — **one contributor workflow**, not a Mac-only product rule. +macOS, not a Mac-only requirement. 1. Quit other MTP clients. 2. Open OpenMTP → select the DBI device → **`1: SD Card`**. @@ -59,25 +59,25 @@ macOS — **one contributor workflow**, not a Mac-only product rule. 5. Wait for the queue; refresh; exit MTP responder; title-override launch. macOS clients often create AppleDouble sidecars (`._Something.zip`, -`._cart.gb`, `._foo.sav`). Those are not real archives or saves — the +`._cart.gb`, `._foo.sav`). Those are not real archives or saves. The launcher skips hidden `.*` names. Delete `._*` junk if a zip/ROM/`.sav` fails to open. #### Linux 1. Install desktop MTP support if needed (e.g. `gvfs-mtp` on GNOME/GTK - desktops, or your distro’s KDE MTP stack). + desktops, or your distro's KDE MTP stack). 2. With DBI MTP active, open **Files** / **Dolphin** / **Thunar** and select the Switch / DBI device → **`1: SD Card`**. 3. Extract the release zip at SD root (merge), or copy into `switch/gen1recomp/` and the save-dir inboxes as above. 4. Use **only one** MTP accessor at a time. If `mtp-tools` / `mtpfs` reports - “device is busy”, close the file manager’s MTP mount (or the CLI mount) + "device is busy", close the file manager's MTP mount (or the CLI mount) and retry with a single client. 5. Eject/unmount cleanly; exit MTP on the Switch; title-override launch. If MTP is unavailable or flaky on Linux, use **direct SD** (Hekate UMS or a -card reader) or **FTP** instead — same destinations in the table above. +card reader) or **FTP** instead. Same destinations in the table above. #### Windows @@ -92,7 +92,7 @@ card reader) or **FTP** instead — same destinations in the table above. 5. Safely disconnect; exit MTP on the Switch; title-override launch. If MTP is unavailable or flaky on Windows, use **direct SD** (Hekate UMS or a -card reader) or **FTP** instead — same destinations in the table above. +card reader) or **FTP** instead. Same destinations in the table above. ### 2. Direct SD (Hekate UMS or card reader) @@ -108,9 +108,9 @@ Do not yank the card or unplug UMS mid-write. ### 3. FTP (any SD-exposing Switch FTP) -Any homebrew FTP server that can write the microSD is fine — for example -**DBI’s own FTP**, **sys-ftpd-light**, or **Sphaira** (names are illustrations -only; pick what your CFW setup already uses). +Any homebrew FTP server that can write the microSD is fine. For example +**DBI's own FTP**, **sys-ftpd-light**, or **Sphaira**. Names are illustrations +only; pick what your CFW setup already uses. 1. Start the FTP server on the Switch; note IP/port/credentials from that app. 2. From the host, connect with any FTP client and upload to the same @@ -153,7 +153,7 @@ Copy the file back from the SD and compare hashes. Round-trip must match. | Symptom | What to try | | ------- | ----------- | | Device busy / no MTP volume | One client only; different cable/port; Windows MTP USB Device driver; alternate method (SD or FTP) | -| Zip/ROM/`.sav` “could not be opened” | Delete `._*` sidecars (including `._*.sav`); confirm real zip starts with `PK` | +| Zip/ROM/`.sav` "could not be opened" | Delete `._*` sidecars (including `._*.sav`); confirm real zip starts with `PK` | | Half-copied NRO / crash on boot | Re-copy; verify SHA-256; exit transfer mode before launch | | App opens in Applet Mode | Use title override (hold **R**), not Album | diff --git a/docs/updater.md b/docs/updater.md index 047ffbd1..c27615a3 100644 --- a/docs/updater.md +++ b/docs/updater.md @@ -126,6 +126,6 @@ bundled game, in that case. checkout is always "the game" itself; updating it means pulling the repo. - **Nintendo Switch does not use this LÖVE self-updater.** On NX, `Platform.networkValidated()` is `false`, so `Boot.run` / `Check` never - download `.love` payloads. In-console OTA is the **native OTA launcher** - (DEVKITPRO) documented in [switch-install.md](switch-install.md); protocol contract - `src/update/SwitchOta.lua`. Manual zip install remains the fallback. + download `.love` payloads. In-console OTA uses the **native OTA launcher** + (DEVKITPRO), documented in [switch-install.md](switch-install.md). Wire + format: `src/update/SwitchOta.lua`. Manual zip install remains the fallback. diff --git a/native/switch-ota-launcher/README.md b/native/switch-ota-launcher/README.md index 6d777508..ffa02cbc 100644 --- a/native/switch-ota-launcher/README.md +++ b/native/switch-ota-launcher/README.md @@ -6,20 +6,20 @@ are already up to date or offline). Only if a newer release exists does it show a **launcher-style screen** (black + RGB rail + project logo + flat A/B buttons), download the same `gen1recomp-*-switch.zip` used for install, verify SHA-256 from `sha256sums.txt`, replace **both** `gen1recomp-game.nro` and -`gen1recomp.nro` (matching NACP version for hbmenu/Sphaira), then hand off +`gen1recomp.nro` (matching NACP version for hbmenu/Sphaira), then load the game with `envSetNextLoad`. The LÖVE self-updater (`src/update/Check.lua`) stays **disabled** on NX. -Protocol contract (also in Lua): `src/update/SwitchOta.lua`. +Wire format (also in Lua): `src/update/SwitchOta.lua`. NACP icon: `assets/switch/icon.jpg`. ## Layout on microSD ```text -sdmc:/switch/gen1recomp/gen1recomp.nro ← this launcher -sdmc:/switch/gen1recomp/gen1recomp-game.nro ← fused LÖVE game -sdmc:/switch/gen1recomp/version.txt ← installed X.Y.Z -sdmc:/switch/gen1recomp/pokemon-love2d/ ← saves (never touched by OTA) +sdmc:/switch/gen1recomp/gen1recomp.nro <- this launcher +sdmc:/switch/gen1recomp/gen1recomp-game.nro <- fused LÖVE game +sdmc:/switch/gen1recomp/version.txt <- installed X.Y.Z +sdmc:/switch/gen1recomp/pokemon-love2d/ <- saves (never touched by OTA) ``` ## Host tests (no DEVKITPRO) @@ -42,7 +42,7 @@ Needs `DEVKITPRO` with packages roughly: export DEVKITPRO=/opt/devkitpro # typical cd native/switch-ota-launcher make -# → gen1recomp.nro +# -> gen1recomp.nro ``` Or from repo root (as part of `--fused`): @@ -62,12 +62,12 @@ Docker fallback uses the same pin as fused builds (`scripts/switch/dkp-docker.im ## Packaging `scripts/switch/pack_sd_zip.sh GAME_NRO VERSION OUT_ZIP LAUNCHER_NRO` writes both -NROs into the SD zip. That zip is also the OTA download asset (unified). +NROs into the SD zip. That zip is also what OTA downloads. Manifest: `scripts/switch/ota_launcher.manifest`. ## Status / known gaps - Zip extraction uses `switch-zziplib` (`ota_unzip.c`) on device. -- OTA replaces launcher + game from the unified zip (NACP versions stay aligned). +- OTA replaces launcher + game from the install zip (NACP versions stay aligned). - Sphaira HOME forwarders cache metadata until reinstalled (see docs/switch-install.md). - Release runner: `switch-dev` + (`install_devkitpro_deps.sh` **or** Docker) diff --git a/scripts/switch/ota_launcher.manifest b/scripts/switch/ota_launcher.manifest index cf84a6d4..79409299 100644 --- a/scripts/switch/ota_launcher.manifest +++ b/scripts/switch/ota_launcher.manifest @@ -4,7 +4,7 @@ # entrypoint. The LÖVE fused game NRO is loaded via envSetNextLoad after the # update check. Self-update of the launcher itself is out of scope for v1. # -# OTA download uses the same SD zip as install (unified asset). +# OTA downloads the install zip. # # Paths relative to microSD root: diff --git a/scripts/switch/selftest_build_switch.sh b/scripts/switch/selftest_build_switch.sh index b1634c0b..7a796d09 100755 --- a/scripts/switch/selftest_build_switch.sh +++ b/scripts/switch/selftest_build_switch.sh @@ -410,7 +410,7 @@ if [ ! -f "$LEGACY_OTA_PACKER" ] \ && ! grep -Eq 'pack_ota_zip\.sh|switch-ota\.zip' "$ROOT/scripts/build_switch.sh" \ && grep -q 'OTA_ASSET_GLOB=gen1recomp-\*-switch.zip' "$MANIFEST" then - ok "unified OTA download is the same SD zip (legacy OTA-only packer gone)" + ok "OTA uses the same SD zip as install (legacy OTA-only packer gone)" else bad "legacy separate OTA-only packer / asset still present" fi @@ -419,7 +419,7 @@ if grep -q 'ota_ui_prompt_update' "$ROOT/native/switch-ota-launcher/src/main.c" && grep -q 'framebufferCreate\|COL_RAIL' "$ROOT/native/switch-ota-launcher/src/ota_ui.c" \ && grep -q '^ROMFS' "$ROOT/native/switch-ota-launcher/Makefile" then - ok "launcher UI is branded framebuffer (quiet by default)" + ok "launcher UI uses framebuffer (no prompt when up to date)" else bad "launcher missing branded ota_ui / ROMFS" fi diff --git a/src/update/SwitchOta.lua b/src/update/SwitchOta.lua index db03b22a..ca914bb2 100644 --- a/src/update/SwitchOta.lua +++ b/src/update/SwitchOta.lua @@ -1,4 +1,4 @@ --- Switch OTA protocol contract (host-testable, no love.*). +-- Switch OTA wire format (host-testable, no love.*). -- The native DEVKITPRO launcher (libnx + switch-curl) must implement the -- same decisions. LÖVE on NX never runs this path — Platform.networkValidated -- stays false and src/update/Check.lua remains gated off on NX. diff --git a/test/switch-nro-ota.spec.test.js b/test/switch-nro-ota.spec.test.js index 4f216cb2..1f66305e 100644 --- a/test/switch-nro-ota.spec.test.js +++ b/test/switch-nro-ota.spec.test.js @@ -571,8 +571,8 @@ test('AC-011: Empacotamento dual-NRO e selftest @spec:AC-011', () => { const selftest = read('scripts/switch/selftest_build_switch.sh'); assert.match(selftest, /dual-NRO|gen1recomp-game\.nro/); assert.match(selftest, /ota_launcher\.manifest/); - assert.match(selftest, /unified OTA|same SD zip|legacy OTA-only/i); - assert.match(selftest, /ota_ui|branded framebuffer|Quiet by default|quiet by default/i); + assert.match(selftest, /OTA uses the same SD zip|same SD zip|legacy OTA-only/i); + assert.match(selftest, /ota_ui|framebuffer|no prompt when up to date/i); const manifest = read('scripts/switch/ota_launcher.manifest'); assert.match(manifest, /^OTA_ENABLED=1$/m); diff --git a/tests/switch_ci_workflows_test.lua b/tests/switch_ci_workflows_test.lua index d43e6ccf..5ae2d693 100644 --- a/tests/switch_ci_workflows_test.lua +++ b/tests/switch_ci_workflows_test.lua @@ -157,14 +157,14 @@ local readme = read("README.md") mustContain(build_doc, "Path-gated", "switch-build.md") mustContain(build_doc, "ubuntu-latest", "switch-build.md") mustContain(build_doc, "selftest_build_switch.sh", "switch-build.md") -mustContain(build_doc, "canonical", "switch-build.md") +mustContain(build_doc, "main repo", "switch-build.md") mustContain(build_doc, "gen1recomp-switch-nro", "switch-build.md") mustContain(build_doc, "switch-build-result", "switch-build.md") mustContain(build_doc, "hard gate", "switch-build.md") mustContain(build_doc, "continue-on-error", "switch-build.md") mustContain(build_doc, "nacptool", "switch-build.md") mustContain(build_doc, "Docker", "switch-build.md") -mustContain(build_doc, "Fork → canonical", "switch-build.md") +mustContain(build_doc, "Fork PRs into the main repo", "switch-build.md") mustContain(build_doc, "skip Switch fused", "switch-build.md") mustContain(build_doc, "CI and release", "switch-build.md") mustNotContain(build_doc, "switch-development", "switch-build.md") diff --git a/tests/switch_transfer_docs_test.lua b/tests/switch_transfer_docs_test.lua index 68cd600b..808f76a3 100644 --- a/tests/switch_transfer_docs_test.lua +++ b/tests/switch_transfer_docs_test.lua @@ -32,7 +32,7 @@ mustContain(transfer, "imports/", "transfer") mustContain(transfer, "imports/mods/", "transfer") mustContain(transfer, "1: SD Card", "transfer") mustContain(transfer, "Scan again", "transfer") -mustContain(transfer, "one contributor workflow", "transfer") +mustContain(transfer, "documented example", "transfer") mustContain(transfer, "Linux", "transfer") mustContain(transfer, "Windows", "transfer") mustContain(transfer, "macOS", "transfer") @@ -46,7 +46,7 @@ mustContain(transfer, "Portable Devices", "transfer") mustContain(transfer, "MTP USB Device", "transfer") mustContain(transfer, "AppleDouble", "transfer") mustContain(transfer, "card reader", "transfer") -mustContain(transfer, "Canonical methods", "transfer") +mustContain(transfer, "Transfer methods", "transfer") mustContain(transfer, "OpenMTP", "transfer") mustContain(transfer, "only one", "transfer") mustContain(transfer, "USB-C", "transfer") @@ -69,7 +69,7 @@ mustContain(install, "GBC FX", "install") mustContain(install, "PERFORMANCE", "install") mustContain(install, "Stock engine effect", "install") mustContain(install, "## Limitations", "install") -mustContain(install, "Title override required", "install") +mustContain(install, "Launch with title override", "install") mustNotContain(install, "VoxelMod", "install") mustNotContain(install, "switch-development", "install") mustContain(build, "switch-transfer.md", "build") diff --git a/tools/switch-probe/README.md b/tools/switch-probe/README.md index f0940c85..c645324c 100644 --- a/tools/switch-probe/README.md +++ b/tools/switch-probe/README.md @@ -1,4 +1,4 @@ -# switch-probe — love-nx hardware probe +# switch-probe: love-nx hardware probe **NOT FOR RELEASE.** This package is a developer-only diagnostic for Nintendo Switch (love-nx). Do not ship it inside `game.love` or release NRO payloads. @@ -12,7 +12,7 @@ Validate Phase 0 runtime facts on real Switch hardware before running the full G - Gamepad / joystick / touch event logging To date this probe has only been run on **Switch OLED**; other models are -untested. Deploy beside `gen1recomp.nro` remains **manual** (MTP); see +untested. Deploy beside `gen1recomp.nro` remains **manual** (MTP). See `docs/switch-transfer.md`. ## Fields shown on screen @@ -39,7 +39,7 @@ zip -9 -j .bazinga/work/switch-probe.love tools/switch-probe/main.lua tools/swit ``` Deploy beside `gen1recomp.nro` (loose mode) per `docs/switch-build.md` and -`docs/switch-transfer.md`, renaming to `game.love` only for a probe run — use a +`docs/switch-transfer.md`. Rename to `game.love` only for a probe run. Use a separate SD folder so probe and game builds do not mix. ## Desktop smoke (optional)