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:
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
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user