mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
Ship Switch releases as an SD-ready zip only.
Players extract one zip at the microSD root for install and update; saves under pokemon-love2d/ survive merge. Drop the bare .nro from GitHub Release assets. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
name: Release
|
||||
|
||||
# Builds the macOS, Windows, and Linux desktop apps, an Android APK, an iOS
|
||||
# IPA, a Nintendo Switch fused NRO (experimental), and the Anbernic RG34XXSP
|
||||
# IPA, a Nintendo Switch SD-ready zip (experimental), and the Anbernic RG34XXSP
|
||||
# (Stock OS 64-bit MOD / PortMaster) port on the self-hosted Mac runner, and
|
||||
# publishes them as a GitHub Release.
|
||||
#
|
||||
@@ -270,13 +270,11 @@ jobs:
|
||||
[ -f "$ipa" ] || { echo "::error::$ipa not found (expected from scripts/build_ios.sh --device)"; exit 1; }
|
||||
cp "$ipa" "$outdir/gen1recomp-${v}-ios.ipa"
|
||||
|
||||
nro="dist/switch/gen1recomp-${v}-switch.nro"
|
||||
[ -f "$nro" ] || { echo "::error::$nro not found (expected from scripts/build_switch.sh --fused)"; exit 1; }
|
||||
cp "$nro" "$outdir/gen1recomp-${v}-switch.nro"
|
||||
# Sidecar written by build_fused.sh when the fused NRO succeeds.
|
||||
if [ -f "${nro}.sha256" ]; then
|
||||
cp "${nro}.sha256" "$outdir/gen1recomp-${v}-switch.nro.sha256"
|
||||
fi
|
||||
swzip="dist/switch/gen1recomp-${v}-switch.zip"
|
||||
[ -f "$swzip" ] || { echo "::error::$swzip not found (expected from scripts/build_switch.sh --fused → pack_sd_zip.sh)"; exit 1; }
|
||||
cp "$swzip" "$outdir/gen1recomp-${v}-switch.zip"
|
||||
# Local fused .nro stays under dist/switch/ for PR CI / debug; release
|
||||
# publishes the SD-ready zip only.
|
||||
|
||||
# Anbernic handheld port (suffix names the CFW it targets, so a
|
||||
# future RG35XX/other-CFW pack can ship alongside it).
|
||||
@@ -395,14 +393,11 @@ jobs:
|
||||
"dist/release/gen1recomp-${v}-linux.zip"
|
||||
"dist/release/gen1recomp-${v}-android.apk"
|
||||
"dist/release/gen1recomp-${v}-ios.ipa"
|
||||
"dist/release/gen1recomp-${v}-switch.nro"
|
||||
"dist/release/gen1recomp-${v}-switch.zip"
|
||||
"dist/release/gen1recomp-${v}-rg34xxsp-stockos64-mod.zip"
|
||||
"dist/release/gen1recomp-${v}.love"
|
||||
"dist/release/sha256sums.txt"
|
||||
)
|
||||
if [ -f "dist/release/gen1recomp-${v}-switch.nro.sha256" ]; then
|
||||
release_files+=("dist/release/gen1recomp-${v}-switch.nro.sha256")
|
||||
fi
|
||||
|
||||
gh release create "$tag" \
|
||||
--target "$GITHUB_SHA" \
|
||||
|
||||
@@ -231,15 +231,15 @@ Install steps, controls, and troubleshooting live in
|
||||
|
||||
## Nintendo Switch
|
||||
|
||||
Releases ship a fused `gen1recomp-*-switch.nro` (issue
|
||||
Releases ship an SD-ready `gen1recomp-*-switch.zip` (issue
|
||||
[#531](https://github.com/bryanthaboi/gen1recomp/issues/531)). Runtime target
|
||||
is pinned [love-nx](https://github.com/retronx-team/love-nx) `11.5-nx1`.
|
||||
Requires a console that can run Switch homebrew. Hardware evidence: **OLED**
|
||||
(author) and **V1 / Erista** boot (community).
|
||||
|
||||
- Players: [docs/switch-install.md](docs/switch-install.md) — download the
|
||||
NRO, copy to the SD, title-override launch, import your own legal ROM,
|
||||
Joy-Con controls and shortcuts.
|
||||
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).
|
||||
|
||||
+11
-8
@@ -1,14 +1,14 @@
|
||||
# Build the Nintendo Switch NRO — contributor guide
|
||||
|
||||
Want to play a release build instead? Download the fused NRO and copy it to
|
||||
your console — see [switch-install.md](switch-install.md).
|
||||
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).
|
||||
|
||||
This guide is for contributors who build Gen1Recomp for Switch from source.
|
||||
Hardware evidence, MTP operator loops, and deeper notes live in
|
||||
[switch-development.md](switch-development.md).
|
||||
|
||||
> Releases ship a fused `gen1recomp-*-switch.nro` (issue
|
||||
> [#531](https://github.com/bryanthaboi/gen1recomp/issues/531)). Hardware
|
||||
> Releases ship `gen1recomp-*-switch.zip` (SD tree under `switch/gen1recomp/`;
|
||||
> issue [#531](https://github.com/bryanthaboi/gen1recomp/issues/531)). Hardware
|
||||
> evidence: **OLED** (author) and **V1 boot** (community). See
|
||||
> [switch-development.md](switch-development.md) for known limitations.
|
||||
|
||||
@@ -64,7 +64,7 @@ builds can fall back to the pinned image when native tools are missing.
|
||||
| ---- | ------------ |
|
||||
| `--fetch` | Downloads pinned **love.nro** + **love.elf** into `.bazinga/love-nx/11.5-nx1/` and verifies SHA-256 against `scripts/switch/love-nx-11.5-nx1.sha256`. |
|
||||
| `--loose` | Packs `game.love`, copies pinned `love.nro` → `dist/switch/loose/` as `gen1recomp.nro` + `game.love` side by side. Needs the pin. |
|
||||
| `--fused` | Builds a single `dist/switch/gen1recomp-<ver>-switch.nro` (game in romfs) via `nacptool` + `elf2nro`. Needs the pin + toolchain (native or Docker). |
|
||||
| `--fused` | Builds `dist/switch/gen1recomp-<ver>-switch.nro` (game in romfs) via `nacptool` + `elf2nro`, then packs `dist/switch/gen1recomp-<ver>-switch.zip` (SD-ready tree). Needs the pin + toolchain (native or Docker). GitHub Releases publish the **zip only**. |
|
||||
|
||||
Rules:
|
||||
|
||||
@@ -109,12 +109,13 @@ scripts/build_switch.sh --fetch
|
||||
# Loose pair for iteration (fetch + assemble)
|
||||
scripts/build_switch.sh --fetch --loose
|
||||
|
||||
# Single fused NRO for a release-like artifact
|
||||
# Single fused NRO + SD-ready zip for a release-like artifact
|
||||
scripts/build_switch.sh --fetch --fused --version 0.2.0
|
||||
```
|
||||
|
||||
Outputs land under `dist/switch/` (and `dist/switch/loose/` for loose mode).
|
||||
The fused path also writes `gen1recomp-<ver>-switch.nro.sha256`.
|
||||
The fused path also writes `gen1recomp-<ver>-switch.nro.sha256` and
|
||||
`gen1recomp-<ver>-switch.zip` (+ `.sha256` sidecar for the zip).
|
||||
|
||||
Offline packaging smoke (no network, no nacptool required):
|
||||
|
||||
@@ -164,7 +165,9 @@ other platforms — this is a **hard gate** (no `continue-on-error`):
|
||||
scripts/build_switch.sh --fetch --fused --version "<release version>"
|
||||
```
|
||||
|
||||
A Switch packaging failure fails the entire release job.
|
||||
A Switch packaging failure fails the entire release job. The release asset is
|
||||
`gen1recomp-<ver>-switch.zip` (SD-ready); the versioned `.nro` stays under
|
||||
`dist/switch/` for the packer and for PR CI artifacts.
|
||||
|
||||
### Runner provisioning
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Nintendo Switch development (love-nx)
|
||||
|
||||
> Fused NRO support for issue [#531](https://github.com/bryanthaboi/gen1recomp/issues/531).
|
||||
> Releases ship `gen1recomp-*-switch.nro`. Console copy is manual; title override
|
||||
> required. See [Known limitations](#known-limitations-read-before-reviewing).
|
||||
> Releases ship `gen1recomp-*-switch.zip` (SD-ready tree). Console copy is
|
||||
> extract/merge at microSD root; title override required. See
|
||||
> [Known limitations](#known-limitations-read-before-reviewing).
|
||||
|
||||
**Canonical install / build / transfer docs** (start here unless you need hardware depth):
|
||||
|
||||
@@ -27,9 +28,9 @@ the transfer runbook).
|
||||
| ---- | ----- |
|
||||
| Feature | **Available** — playable fused NRO path (issue #531) |
|
||||
| Runtime | Pinned love-nx **`11.5-nx1`** |
|
||||
| Product artifact | Single fused `gen1recomp.nro` (game in romfs); loose `nro`+`game.love` for iteration |
|
||||
| Product artifact | Releases: SD-ready `gen1recomp-*-switch.zip`; local/PR: fused `.nro`; loose `nro`+`game.love` for iteration |
|
||||
| Hardware | **OLED** validated (author, title override); **V1 / Erista** boot confirmed (community). Lite, docked soak, and Pro Controller matrices welcome |
|
||||
| Deploy / install | Releases publish fused NRO; **console copy is manual** (MTP / SD / FTP — [switch-transfer.md](switch-transfer.md)); no `nxlink` path yet |
|
||||
| Deploy / install | Releases publish SD-ready zip; **extract/merge at microSD root** (MTP / SD / FTP — [switch-transfer.md](switch-transfer.md)); no `nxlink` path yet |
|
||||
| Contributor transfer | Documented for **macOS, Linux, and Windows**; OpenMTP on Mac is one example, not the only contract |
|
||||
| Network features on NX | Self-update / remote mod download **disabled** (`networkValidated == false`) |
|
||||
| Community help | Welcome — especially HOS / love-nx packaging and broader hardware coverage |
|
||||
@@ -165,7 +166,7 @@ Detail for **macOS / Linux / Windows** and **MTP / SD / FTP** lives in
|
||||
|
||||
| Layer | Intent |
|
||||
| ----- | ------ |
|
||||
| **Runtime / players** | Put the NRO under `sdmc:/switch/gen1recomp/` and land ROMs/mods under the save-dir inboxes. The game does not hard-depend on OpenMTP or macOS. |
|
||||
| **Runtime / players** | Extract the release zip at microSD root (`switch/gen1recomp/`) and land ROMs/mods under the save-dir inboxes. The game does not hard-depend on OpenMTP or macOS. |
|
||||
| **Contributor loop** | Manual copy via MTP (DBI responder), direct SD (Hekate UMS / reader), or FTP. Fully manual — no CI deploy, no `nxlink` yet. |
|
||||
|
||||
The Mac + OpenMTP steps that remain below are the **OLED evidence reproduction** path; prefer the transfer runbook for day-to-day contrib on other hosts.
|
||||
|
||||
@@ -127,7 +127,7 @@ Operator smoke for the switch-build-pipeline packaging CLI (closes matrix-deferr
|
||||
| love-nx | `11.5-nx1` (manifest checksums match) |
|
||||
| Artifact | `dist/switch/gen1recomp-0.0.0-test-switch.nro` |
|
||||
| NRO SHA-256 | `210efb884a8d27443dc1c64ed8f071b0f862d8d0c9b140ad8185093c4e4027db` |
|
||||
| Install doc | `docs/switch-install.md` — copy NRO under `sdmc:/switch/gen1recomp/` |
|
||||
| Install doc | `docs/switch-install.md` — at the time of this row: copy NRO under `sdmc:/switch/gen1recomp/` (releases now ship an SD-ready zip; same folder) |
|
||||
| Console | Switch OLED |
|
||||
| Operator | Andrew |
|
||||
| Date | 2026-08-01 |
|
||||
|
||||
+26
-20
@@ -1,8 +1,9 @@
|
||||
# Install Gen1Recomp on Nintendo Switch
|
||||
|
||||
Every GitHub Release that includes Switch support ships a fused homebrew
|
||||
binary: `gen1recomp-*-switch.nro`. Copy it to your microSD, launch with
|
||||
**title override**, then import your own legal `.gb` ROM.
|
||||
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
|
||||
own legal `.gb` ROM.
|
||||
|
||||
> You need a console that can run Switch homebrew (custom firmware / hbmenu).
|
||||
> This project does not help you set that up. Tracks issue
|
||||
@@ -16,30 +17,36 @@ Prefer building from source? See [switch-build.md](switch-build.md).
|
||||
Port by [andrewqsantos](https://github.com/andrewqsantos). Community testing
|
||||
help from [booshankles](https://github.com/booshankles).
|
||||
|
||||
## 1. Download the NRO
|
||||
## 1. Download the zip
|
||||
|
||||
1. Open
|
||||
[Releases](https://github.com/bryanthaboi/gen1recomp/releases).
|
||||
2. Download `gen1recomp-*-switch.nro` for the version you want.
|
||||
(Optional: the matching `*.nro.sha256` sidecar if you want to verify the
|
||||
download.)
|
||||
2. Download `gen1recomp-*-switch.zip` for the version you want.
|
||||
(Optional: verify against `sha256sums.txt` in the same release.)
|
||||
|
||||
## 2. Copy it to the microSD
|
||||
## 2. Extract onto the microSD
|
||||
|
||||
Put the file here on the SD card:
|
||||
Extract the zip at the **root** of the microSD so you get:
|
||||
|
||||
```text
|
||||
sdmc:/switch/gen1recomp/gen1recomp.nro
|
||||
sdmc:/switch/gen1recomp/pokemon-love2d/imports/
|
||||
sdmc:/switch/gen1recomp/pokemon-love2d/imports/mods/
|
||||
sdmc:/switch/gen1recomp/pokemon-love2d/imports/saves/...
|
||||
```
|
||||
|
||||
(or keep the versioned name under `sdmc:/switch/gen1recomp/` — hbmenu will
|
||||
list it either way).
|
||||
|
||||
Any method that lands the file on the SD is fine: **MTP** (DBI → Run MTP
|
||||
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**.
|
||||
Exit MTP / unmount / stop FTP cleanly before launching. Step-by-step for
|
||||
macOS, Linux, and Windows: [switch-transfer.md](switch-transfer.md).
|
||||
|
||||
### Updating
|
||||
|
||||
Use the **same** extract/merge. It replaces `gen1recomp.nro` (and the small
|
||||
help `README.txt` / `INSTALL.txt` files). Saves, 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
|
||||
|
||||
**Applet Mode is not supported** for this game (not enough memory).
|
||||
@@ -55,15 +62,12 @@ Do **not** launch from the Album applet path for normal play.
|
||||
|
||||
This project ships **no** game data. On first launch:
|
||||
|
||||
1. Put your own legally obtained Pokémon Red or Blue `.gb` into the ROM
|
||||
inbox under the game’s save directory (`imports/` — the launcher shows
|
||||
the live path).
|
||||
1. Put your own legally obtained Pokémon Red or Blue `.gb` into
|
||||
`switch/gen1recomp/pokemon-love2d/imports/` (the launcher also shows
|
||||
the live save-dir path).
|
||||
2. Use **Scan again** on the Red/Blue tab if you add the
|
||||
file after the first open.
|
||||
|
||||
Saves live in the LÖVE save directory and **persist across NRO updates** —
|
||||
you can replace only the `.nro` and keep your progress.
|
||||
|
||||
## 5. Import / Export a raw `.sav`
|
||||
|
||||
Continue a cart or PC battery save (or pull a slot off-console) via MTP /
|
||||
@@ -75,6 +79,8 @@ 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.)
|
||||
|
||||
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** →
|
||||
@@ -164,7 +170,7 @@ and
|
||||
|
||||
## Prefer building it yourself?
|
||||
|
||||
Building the fused (or loose) NRO from source is covered in
|
||||
Building the fused NRO (and SD-ready zip) from source is covered in
|
||||
[switch-build.md](switch-build.md). Copying artifacts and inbox files
|
||||
(MTP / SD / FTP on macOS, Linux, Windows): [switch-transfer.md](switch-transfer.md).
|
||||
Status, limitations, and how we tested: [switch-development.md](switch-development.md).
|
||||
|
||||
@@ -19,7 +19,7 @@ Player install (what to download, title override) stays in
|
||||
|
||||
| What | Where on the console |
|
||||
| ---- | -------------------- |
|
||||
| Fused release NRO | `sdmc:/switch/gen1recomp/gen1recomp.nro` (or versioned name under that folder) |
|
||||
| SD-ready release zip | Extract at microSD **root** → `sdmc:/switch/gen1recomp/gen1recomp.nro` plus `pokemon-love2d/` inbox folders. Install and update use the same merge; do **not** delete `pokemon-love2d/` |
|
||||
| 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/<save identity>/imports/`) |
|
||||
| Mod zip inbox | Same save dir → `imports/mods/` then MODS → **Scan again** |
|
||||
@@ -28,7 +28,8 @@ Player install (what to download, title override) stays in
|
||||
| Opt-in diagnostics | Empty `switch-debug.txt` in the save dir → `switch.log` |
|
||||
| Lua error log | `lua-error.log` in the save dir |
|
||||
|
||||
Saves persist across **NRO-only** replacements. Never commit ROM dumps, `.sav`
|
||||
Saves persist across zip re-extract / NRO replacements as long as
|
||||
`pokemon-love2d/` is left in place. Never commit ROM dumps, `.sav`
|
||||
files, or third-party mod zips to git.
|
||||
|
||||
---
|
||||
@@ -51,7 +52,8 @@ hardware evidence — **one contributor example**, not a Mac-only product rule.
|
||||
|
||||
1. Quit other MTP clients.
|
||||
2. Open OpenMTP → select the DBI device → **`1: SD Card`**.
|
||||
3. Create `switch/gen1recomp/` if needed; copy NRO (and `game.love` for loose).
|
||||
3. Create `switch/gen1recomp/` if needed; extract the release zip at SD root
|
||||
(or copy NRO / `game.love` for loose).
|
||||
4. For ROMs/mods/saves, open the save-dir `imports/`, `imports/mods/`,
|
||||
`imports/saves/<red|blue|yellow>/`, or `exports/<red|blue|yellow>/` path the
|
||||
launcher prints.
|
||||
@@ -68,7 +70,8 @@ fails to open.
|
||||
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. Copy into `switch/gen1recomp/` and the save-dir inboxes as above.
|
||||
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)
|
||||
and retry with a single client.
|
||||
@@ -81,7 +84,7 @@ card reader) or **FTP** instead — same destinations in the table above.
|
||||
|
||||
1. With DBI MTP active, open **This PC** / **File Explorer** and look under
|
||||
**Portable Devices** for the Switch / DBI MTP volume → **`1: SD Card`**.
|
||||
2. Copy files into `switch\gen1recomp\` and the save-dir inboxes.
|
||||
2. Copy / extract into `switch\gen1recomp\` and the save-dir inboxes.
|
||||
3. Optional: [OpenMTP](https://github.com/ganeshrvel/openmtp) on Windows if
|
||||
Explorer is flaky.
|
||||
4. If Windows does not show an MTP device: Device Manager → find DBI / Switch
|
||||
|
||||
+10
-5
@@ -19,10 +19,13 @@
|
||||
# (gen1recomp.nro + game.love side by side). Requires the pin
|
||||
# (run --fetch first, or combine --fetch --loose).
|
||||
#
|
||||
# --fused Build a single gen1recomp-<ver>-switch.nro via nacptool+elf2nro.
|
||||
# Uses native tools (PATH or $DEVKITPRO/tools/bin) first; else
|
||||
# Docker from scripts/switch/dkp-docker.image (override
|
||||
# GEN1_DKP_IMAGE). Requires the pin (run --fetch or combine).
|
||||
# --fused Build a single gen1recomp-<ver>-switch.nro via nacptool+elf2nro,
|
||||
# then pack dist/switch/gen1recomp-<ver>-switch.zip (SD-ready
|
||||
# tree under switch/gen1recomp/). Uses native tools (PATH or
|
||||
# $DEVKITPRO/tools/bin) first; else Docker from
|
||||
# scripts/switch/dkp-docker.image (override GEN1_DKP_IMAGE).
|
||||
# Requires the pin (run --fetch or combine). GitHub Releases
|
||||
# publish the zip only; the versioned .nro stays local / PR CI.
|
||||
#
|
||||
# Combinable: --fetch alone, or --fetch with --loose / --fused.
|
||||
# XOR: --loose and --fused cannot be used together.
|
||||
@@ -46,7 +49,7 @@ say() { printf '\033[1;32m==>\033[0m %s\n' "$*" >&2; }
|
||||
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
usage() {
|
||||
sed -n '2,32p' "$0" | sed 's/^# \{0,1\}//'
|
||||
sed -n '2,34p' "$0" | sed 's/^# \{0,1\}//'
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
@@ -128,7 +131,9 @@ fi
|
||||
if [ "$FUSED" -eq 1 ]; then
|
||||
GAME_LOVE="$(pack_game_love)"
|
||||
OUT_NRO="$DIST/gen1recomp-${VERSION}-switch.nro"
|
||||
OUT_ZIP="$DIST/gen1recomp-${VERSION}-switch.zip"
|
||||
"$ROOT/scripts/switch/build_fused.sh" "$GAME_LOVE" "$VERSION" "$OUT_NRO"
|
||||
"$ROOT/scripts/switch/pack_sd_zip.sh" "$OUT_NRO" "$VERSION" "$OUT_ZIP"
|
||||
cp "$WORK/build-info.json" "$DIST/gen1recomp-${VERSION}-build-info.json"
|
||||
say "done. See $DIST/"
|
||||
exit 0
|
||||
|
||||
Executable
+128
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pack a Switch SD-ready zip: extract at microSD root (merge-safe update).
|
||||
#
|
||||
# Usage:
|
||||
# scripts/switch/pack_sd_zip.sh NRO_PATH VERSION OUT_ZIP
|
||||
#
|
||||
# Layout inside the zip (SD root):
|
||||
# switch/gen1recomp/gen1recomp.nro
|
||||
# switch/gen1recomp/INSTALL.txt
|
||||
# switch/gen1recomp/pokemon-love2d/imports/.../README.txt
|
||||
# switch/gen1recomp/pokemon-love2d/exports/.../README.txt
|
||||
#
|
||||
# Does not ship ROMs, saves, or mods. Re-extracting merges over an existing
|
||||
# install and only overwrites the NRO + these text placeholders — keep
|
||||
# pokemon-love2d/ to preserve progress.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=common.sh
|
||||
. "$SCRIPT_DIR/common.sh"
|
||||
|
||||
NRO_PATH="${1:-}"
|
||||
VERSION="${2:-}"
|
||||
OUT_ZIP="${3:-}"
|
||||
|
||||
[ -n "$NRO_PATH" ] && [ -n "$VERSION" ] && [ -n "$OUT_ZIP" ] \
|
||||
|| fail "usage: scripts/switch/pack_sd_zip.sh NRO_PATH VERSION OUT_ZIP"
|
||||
|
||||
[ -f "$NRO_PATH" ] || fail "missing NRO at $NRO_PATH"
|
||||
|
||||
command -v zip >/dev/null 2>&1 || fail "need zip on PATH"
|
||||
|
||||
# Absolutize before any cd — relative OUT_ZIP would otherwise land inside the
|
||||
# staging dir and vanish when the EXIT trap cleans up.
|
||||
NRO_PATH="$(cd "$(dirname "$NRO_PATH")" && pwd)/$(basename "$NRO_PATH")"
|
||||
OUT_DIR="$(dirname "$OUT_ZIP")"
|
||||
mkdir -p "$OUT_DIR"
|
||||
OUT_ZIP="$(cd "$OUT_DIR" && pwd)/$(basename "$OUT_ZIP")"
|
||||
|
||||
STAGE="$(mktemp -d "${TMPDIR:-/tmp}/gen1recomp-sd-zip.XXXXXX")"
|
||||
cleanup() { rm -rf "$STAGE"; }
|
||||
trap cleanup EXIT
|
||||
|
||||
APP_DIR="$STAGE/switch/gen1recomp"
|
||||
SAVE_ROOT="$APP_DIR/pokemon-love2d"
|
||||
mkdir -p "$APP_DIR"
|
||||
cp "$NRO_PATH" "$APP_DIR/gen1recomp.nro"
|
||||
|
||||
cat > "$APP_DIR/INSTALL.txt" <<EOF
|
||||
gen1recomp Switch (v${VERSION})
|
||||
===============================
|
||||
|
||||
First install or update (same steps):
|
||||
1. Extract this zip at the root of your microSD (merge folders if asked).
|
||||
2. Do NOT delete switch/gen1recomp/pokemon-love2d/ — that folder holds
|
||||
your saves, imported ROMs, mods, and options. Re-extracting only
|
||||
replaces gen1recomp.nro and these help files.
|
||||
3. Launch with title override (hold R on HOME, open any title → hbmenu).
|
||||
4. Copy a legal Pokemon Red/Blue .gb into:
|
||||
switch/gen1recomp/pokemon-love2d/imports/
|
||||
then use Scan again in the launcher if needed.
|
||||
|
||||
Inboxes (drop files here via MTP / SD / FTP):
|
||||
imports/ — ROM .gb / .gbc
|
||||
imports/mods/ — community mod .zip
|
||||
imports/saves/red|blue|yellow/ — raw .sav import
|
||||
exports/red|blue|yellow/ — pull after Export save
|
||||
|
||||
Full guide: https://github.com/bryanthaboi/gen1recomp/blob/main/docs/switch-install.md
|
||||
EOF
|
||||
|
||||
write_readme() {
|
||||
local path="$1"
|
||||
local body="$2"
|
||||
mkdir -p "$(dirname "$path")"
|
||||
printf '%s\n' "$body" > "$path"
|
||||
}
|
||||
|
||||
write_readme "$SAVE_ROOT/imports/README.txt" \
|
||||
"Put a legal Pokemon Red or Blue .gb / .gbc here, then Scan again in the launcher."
|
||||
write_readme "$SAVE_ROOT/imports/mods/README.txt" \
|
||||
"Put community mod .zip files here, then MODS → Scan again."
|
||||
write_readme "$SAVE_ROOT/imports/saves/red/README.txt" \
|
||||
"Put a Red .sav (32 KB) here, then Red tab → SAVE FILES → Import save."
|
||||
write_readme "$SAVE_ROOT/imports/saves/blue/README.txt" \
|
||||
"Put a Blue .sav (32 KB) here, then Blue tab → SAVE FILES → Import save."
|
||||
write_readme "$SAVE_ROOT/imports/saves/yellow/README.txt" \
|
||||
"Put a Yellow .sav (32 KB) here, then Yellow tab → SAVE FILES → Import save."
|
||||
write_readme "$SAVE_ROOT/exports/red/README.txt" \
|
||||
"After Export save (Red), copy the .sav out of this folder via MTP / SD / FTP."
|
||||
write_readme "$SAVE_ROOT/exports/blue/README.txt" \
|
||||
"After Export save (Blue), copy the .sav out of this folder via MTP / SD / FTP."
|
||||
write_readme "$SAVE_ROOT/exports/yellow/README.txt" \
|
||||
"After Export save (Yellow), copy the .sav out of this folder via MTP / SD / FTP."
|
||||
|
||||
rm -f "$OUT_ZIP"
|
||||
(
|
||||
cd "$STAGE"
|
||||
zip -q -r "$OUT_ZIP" switch
|
||||
)
|
||||
|
||||
[ -f "$OUT_ZIP" ] || fail "zip was not created at $OUT_ZIP"
|
||||
[ -s "$OUT_ZIP" ] || fail "zip is empty: $OUT_ZIP"
|
||||
|
||||
LISTING="$(unzip -Z1 "$OUT_ZIP" 2>/dev/null || unzip -l "$OUT_ZIP")"
|
||||
printf '%s\n' "$LISTING" | grep -q 'switch/gen1recomp/gen1recomp.nro' \
|
||||
|| fail "zip missing switch/gen1recomp/gen1recomp.nro"
|
||||
|
||||
REQUIRED=(
|
||||
"switch/gen1recomp/INSTALL.txt"
|
||||
"switch/gen1recomp/pokemon-love2d/imports/README.txt"
|
||||
"switch/gen1recomp/pokemon-love2d/imports/mods/README.txt"
|
||||
"switch/gen1recomp/pokemon-love2d/imports/saves/red/README.txt"
|
||||
"switch/gen1recomp/pokemon-love2d/imports/saves/blue/README.txt"
|
||||
"switch/gen1recomp/pokemon-love2d/imports/saves/yellow/README.txt"
|
||||
"switch/gen1recomp/pokemon-love2d/exports/red/README.txt"
|
||||
"switch/gen1recomp/pokemon-love2d/exports/blue/README.txt"
|
||||
"switch/gen1recomp/pokemon-love2d/exports/yellow/README.txt"
|
||||
)
|
||||
for rel in "${REQUIRED[@]}"; do
|
||||
printf '%s\n' "$LISTING" | grep -Fq "$rel" || fail "zip missing $rel"
|
||||
done
|
||||
|
||||
ZIP_SHA="$(sha256_file "$OUT_ZIP")"
|
||||
printf '%s %s\n' "$ZIP_SHA" "$OUT_ZIP" > "${OUT_ZIP}.sha256"
|
||||
say "SD-ready zip: $OUT_ZIP"
|
||||
printf '%s %s\n' "$ZIP_SHA" "$OUT_ZIP"
|
||||
@@ -4,8 +4,8 @@
|
||||
# Usage: scripts/switch/selftest_build_switch.sh
|
||||
#
|
||||
# Covers: sha256_file, --help glossary, XOR loose/fused, fail_need_fetch,
|
||||
# verify_love_nx mismatch, fail_fused_toolchain message. Does not download
|
||||
# love-nx or invoke nacptool/elf2nro/Docker.
|
||||
# verify_love_nx mismatch, fail_fused_toolchain message, pack_sd_zip layout.
|
||||
# Does not download love-nx or invoke nacptool/elf2nro/Docker.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -209,6 +209,108 @@ else
|
||||
bad "fail_fused_toolchain missing OS hints:$OS_MISSING"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 6. pack_sd_zip.sh builds SD-ready tree (offline; fake NRO)
|
||||
# ---------------------------------------------------------------------------
|
||||
FAKE_NRO="$STAGING/fake.nro"
|
||||
printf 'fake-nro-bytes\n' > "$FAKE_NRO"
|
||||
FAKE_ZIP="$STAGING/gen1recomp-0.0.0-test-switch.zip"
|
||||
PACK_RC=0
|
||||
"$ROOT/scripts/switch/pack_sd_zip.sh" "$FAKE_NRO" "0.0.0-test" "$FAKE_ZIP" \
|
||||
>"$STAGING/pack.out" 2>"$STAGING/pack.err" || PACK_RC=$?
|
||||
if [ "$PACK_RC" -eq 0 ] && [ -f "$FAKE_ZIP" ] && [ -s "$FAKE_ZIP" ]; then
|
||||
ok "pack_sd_zip.sh writes a non-empty zip"
|
||||
else
|
||||
bad "pack_sd_zip.sh failed (rc=$PACK_RC err=$(cat "$STAGING/pack.err"))"
|
||||
fi
|
||||
|
||||
ZIP_LIST="$(unzip -Z1 "$FAKE_ZIP" 2>/dev/null || unzip -l "$FAKE_ZIP")"
|
||||
PACK_MISSING=""
|
||||
for rel in \
|
||||
"switch/gen1recomp/gen1recomp.nro" \
|
||||
"switch/gen1recomp/INSTALL.txt" \
|
||||
"switch/gen1recomp/pokemon-love2d/imports/README.txt" \
|
||||
"switch/gen1recomp/pokemon-love2d/imports/mods/README.txt" \
|
||||
"switch/gen1recomp/pokemon-love2d/imports/saves/red/README.txt" \
|
||||
"switch/gen1recomp/pokemon-love2d/imports/saves/blue/README.txt" \
|
||||
"switch/gen1recomp/pokemon-love2d/imports/saves/yellow/README.txt" \
|
||||
"switch/gen1recomp/pokemon-love2d/exports/red/README.txt" \
|
||||
"switch/gen1recomp/pokemon-love2d/exports/blue/README.txt" \
|
||||
"switch/gen1recomp/pokemon-love2d/exports/yellow/README.txt"
|
||||
do
|
||||
printf '%s\n' "$ZIP_LIST" | grep -Fq "$rel" || PACK_MISSING="${PACK_MISSING} ${rel}"
|
||||
done
|
||||
if [ -z "$PACK_MISSING" ]; then
|
||||
ok "pack_sd_zip.sh zip contains SD tree + inbox READMEs"
|
||||
else
|
||||
bad "pack_sd_zip.sh zip missing:$PACK_MISSING"
|
||||
fi
|
||||
|
||||
EXTRACT_DIR="$STAGING/extract-v1"
|
||||
rm -rf "$EXTRACT_DIR"
|
||||
mkdir -p "$EXTRACT_DIR"
|
||||
unzip -q "$FAKE_ZIP" -d "$EXTRACT_DIR"
|
||||
if cmp -s "$FAKE_NRO" "$EXTRACT_DIR/switch/gen1recomp/gen1recomp.nro"; then
|
||||
ok "pack_sd_zip.sh NRO bytes match source"
|
||||
else
|
||||
bad "pack_sd_zip.sh NRO inside zip differs from source"
|
||||
fi
|
||||
|
||||
if [ -f "${FAKE_ZIP}.sha256" ]; then
|
||||
ok "pack_sd_zip.sh writes .sha256 sidecar"
|
||||
else
|
||||
bad "pack_sd_zip.sh should write ${FAKE_ZIP}.sha256"
|
||||
fi
|
||||
|
||||
MISSING_NRO_RC=0
|
||||
"$ROOT/scripts/switch/pack_sd_zip.sh" "$STAGING/does-not-exist.nro" "0.0.0" \
|
||||
"$STAGING/should-fail.zip" >/dev/null 2>&1 || MISSING_NRO_RC=$?
|
||||
if [ "$MISSING_NRO_RC" -ne 0 ]; then
|
||||
ok "pack_sd_zip.sh fails when NRO is missing"
|
||||
else
|
||||
bad "pack_sd_zip.sh should fail on missing NRO"
|
||||
fi
|
||||
|
||||
# Relative OUT_ZIP must survive (absolutized before cd into staging)
|
||||
REL_DIR="$STAGING/rel-out"
|
||||
mkdir -p "$REL_DIR"
|
||||
REL_RC=0
|
||||
(
|
||||
cd "$REL_DIR"
|
||||
"$ROOT/scripts/switch/pack_sd_zip.sh" "$FAKE_NRO" "0.0.1" "relative.zip" \
|
||||
>"$STAGING/rel.out" 2>"$STAGING/rel.err"
|
||||
) || REL_RC=$?
|
||||
if [ "$REL_RC" -eq 0 ] && [ -f "$REL_DIR/relative.zip" ] && [ -s "$REL_DIR/relative.zip" ]; then
|
||||
ok "pack_sd_zip.sh accepts relative OUT_ZIP"
|
||||
else
|
||||
bad "pack_sd_zip.sh relative OUT_ZIP failed (rc=$REL_RC err=$(cat "$STAGING/rel.err"))"
|
||||
fi
|
||||
|
||||
# Merge-safe update: second extract replaces NRO, keeps user data
|
||||
printf 'KEEP-SAVE' > "$EXTRACT_DIR/switch/gen1recomp/pokemon-love2d/slot.sav"
|
||||
printf 'KEEP-ROM' > "$EXTRACT_DIR/switch/gen1recomp/pokemon-love2d/imports/red.gb"
|
||||
printf 'KEEP-MOD' > "$EXTRACT_DIR/switch/gen1recomp/pokemon-love2d/imports/mods/mod.zip"
|
||||
printf 'KEEP-OPTS' > "$EXTRACT_DIR/switch/gen1recomp/pokemon-love2d/options.lua"
|
||||
|
||||
FAKE_NRO2="$STAGING/fake-v2.nro"
|
||||
printf 'fake-nro-bytes-v2\n' > "$FAKE_NRO2"
|
||||
FAKE_ZIP2="$STAGING/gen1recomp-0.0.1-test-switch.zip"
|
||||
"$ROOT/scripts/switch/pack_sd_zip.sh" "$FAKE_NRO2" "0.0.1-test" "$FAKE_ZIP2" \
|
||||
>"$STAGING/pack2.out" 2>"$STAGING/pack2.err"
|
||||
unzip -qo "$FAKE_ZIP2" -d "$EXTRACT_DIR"
|
||||
|
||||
MERGE_OK=1
|
||||
cmp -s "$FAKE_NRO2" "$EXTRACT_DIR/switch/gen1recomp/gen1recomp.nro" || MERGE_OK=0
|
||||
[ "$(cat "$EXTRACT_DIR/switch/gen1recomp/pokemon-love2d/slot.sav")" = "KEEP-SAVE" ] || MERGE_OK=0
|
||||
[ "$(cat "$EXTRACT_DIR/switch/gen1recomp/pokemon-love2d/imports/red.gb")" = "KEEP-ROM" ] || MERGE_OK=0
|
||||
[ "$(cat "$EXTRACT_DIR/switch/gen1recomp/pokemon-love2d/imports/mods/mod.zip")" = "KEEP-MOD" ] || MERGE_OK=0
|
||||
[ "$(cat "$EXTRACT_DIR/switch/gen1recomp/pokemon-love2d/options.lua")" = "KEEP-OPTS" ] || MERGE_OK=0
|
||||
if [ "$MERGE_OK" -eq 1 ]; then
|
||||
ok "pack_sd_zip.sh merge update preserves user data"
|
||||
else
|
||||
bad "pack_sd_zip.sh merge update lost user data or failed to replace NRO"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Summary
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -172,4 +172,28 @@ do
|
||||
mustContain(block, "Hard-fail", "release Build Switch comment")
|
||||
end
|
||||
|
||||
-- Release publishes SD-ready zip only (no bare .nro / .nro.sha256 assets)
|
||||
do
|
||||
local start = release:find("- name: Stage release assets", 1, true)
|
||||
check(start ~= nil, "release Stage release assets present")
|
||||
local rest = release:sub(start)
|
||||
local nextStep = rest:find("\n - name:", 2)
|
||||
local block = nextStep and rest:sub(1, nextStep - 1) or rest
|
||||
mustContain(block, "gen1recomp-${v}-switch.zip", "release Stage Switch zip")
|
||||
mustContain(block, "pack_sd_zip.sh", "release Stage cites pack_sd_zip")
|
||||
mustNotContain(block, "gen1recomp-${v}-switch.nro", "release Stage no bare NRO")
|
||||
mustNotContain(block, "switch.nro.sha256", "release Stage no NRO sha256 sidecar")
|
||||
end
|
||||
|
||||
do
|
||||
local start = release:find("- name: Publish GitHub Release", 1, true)
|
||||
check(start ~= nil, "release Publish GitHub Release present")
|
||||
local rest = release:sub(start)
|
||||
local nextStep = rest:find("\n - name:", 2)
|
||||
local block = nextStep and rest:sub(1, nextStep - 1) or rest
|
||||
mustContain(block, "gen1recomp-${v}-switch.zip", "release Publish Switch zip")
|
||||
mustNotContain(block, "gen1recomp-${v}-switch.nro", "release Publish no bare NRO")
|
||||
mustNotContain(block, "switch.nro.sha256", "release Publish no NRO sha256 sidecar")
|
||||
end
|
||||
|
||||
T.finish("switch_ci_workflows_test")
|
||||
|
||||
Reference in New Issue
Block a user