mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
75cd28435c
Point launcher, fused build, docs, and gitignore at the relocated Switch port tree.
447 lines
18 KiB
Bash
Executable File
447 lines
18 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Offline self-test for Switch packaging entry points (no network, no nacptool).
|
|
#
|
|
# 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, pack_sd_zip layout.
|
|
# Does not download love-nx or invoke nacptool/elf2nro/Docker.
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
# shellcheck source=common.sh
|
|
. "$SCRIPT_DIR/common.sh"
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
ok() {
|
|
PASS=$((PASS + 1))
|
|
printf ' PASS: %s\n' "$*"
|
|
}
|
|
|
|
bad() {
|
|
FAIL=$((FAIL + 1))
|
|
printf ' FAIL: %s\n' "$*" >&2
|
|
}
|
|
|
|
say "selftest_build_switch (offline)"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 1. sha256_file on a known temp file
|
|
# ---------------------------------------------------------------------------
|
|
TMP="$(mktemp "${TMPDIR:-/tmp}/selftest-sha.XXXXXX")"
|
|
printf 'gen1recomp-selftest\n' > "$TMP"
|
|
EXPECTED_SHA="$(shasum -a 256 "$TMP" | awk '{print $1}')"
|
|
ACTUAL_SHA="$(sha256_file "$TMP")"
|
|
rm -f "$TMP"
|
|
if [ "$ACTUAL_SHA" = "$EXPECTED_SHA" ]; then
|
|
ok "sha256_file matches shasum ($ACTUAL_SHA)"
|
|
else
|
|
bad "sha256_file mismatch (expected $EXPECTED_SHA, got $ACTUAL_SHA)"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 2. --help contains fetch / loose / fused
|
|
# ---------------------------------------------------------------------------
|
|
HELP_OUT="$("$ROOT/scripts/build_switch.sh" --help 2>&1 || true)"
|
|
HELP_LC="$(printf '%s' "$HELP_OUT" | tr '[:upper:]' '[:lower:]')"
|
|
MISSING=""
|
|
printf '%s' "$HELP_LC" | grep -q 'fetch' || MISSING="${MISSING} fetch"
|
|
printf '%s' "$HELP_LC" | grep -q 'loose' || MISSING="${MISSING} loose"
|
|
printf '%s' "$HELP_LC" | grep -q 'fused' || MISSING="${MISSING} fused"
|
|
printf '%s' "$HELP_LC" | grep -Eq 'devkitpro' || MISSING="${MISSING} DEVKITPRO"
|
|
printf '%s' "$HELP_LC" | grep -Eq 'auto-download|downloads' || MISSING="${MISSING} auto-download"
|
|
printf '%s' "$HELP_LC" | grep -Eq 'non-goal|does not|never' || MISSING="${MISSING} non-goals"
|
|
if [ -z "$MISSING" ]; then
|
|
ok "build_switch.sh --help mentions fetch, loose, fused, DEVKITPRO (+ auto-download/non-goals)"
|
|
else
|
|
bad "build_switch.sh --help missing:$MISSING"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 3. XOR --loose --fused exits non-zero
|
|
# ---------------------------------------------------------------------------
|
|
XOR_RC=0
|
|
"$ROOT/scripts/build_switch.sh" --loose --fused >/dev/null 2>&1 || XOR_RC=$?
|
|
if [ "$XOR_RC" -ne 0 ]; then
|
|
ok "build_switch.sh --loose --fused exits non-zero ($XOR_RC)"
|
|
else
|
|
bad "build_switch.sh --loose --fused should exit non-zero"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 4. assemble_loose without pin → stderr contains --fetch
|
|
# ---------------------------------------------------------------------------
|
|
STAGING="$(mktemp -d "${TMPDIR:-/tmp}/selftest-loose.XXXXXX")"
|
|
# shellcheck disable=SC2064
|
|
trap "rm -rf '$STAGING'" EXIT
|
|
|
|
FAKE_LOVE="$STAGING/game.love"
|
|
printf 'PK\x03\x04' > "$FAKE_LOVE" # minimal placeholder; assemble only checks -f
|
|
|
|
# Temporarily hide the pin dir if present by pointing ROOT's pin via a subshell
|
|
# that moves the pin aside — or run assemble against a missing path by
|
|
# ensuring .bazinga/love-nx/11.5-nx1/love.nro is absent for this check.
|
|
PIN_DIR="$ROOT/.bazinga/love-nx/11.5-nx1"
|
|
PIN_BACKUP=""
|
|
if [ -f "$PIN_DIR/love.nro" ]; then
|
|
PIN_BACKUP="$STAGING/love.nro.bak"
|
|
mv "$PIN_DIR/love.nro" "$PIN_BACKUP"
|
|
fi
|
|
|
|
ASS_ERR="$STAGING/assemble.err"
|
|
ASS_RC=0
|
|
"$ROOT/scripts/switch/assemble_loose.sh" "$FAKE_LOVE" >"$STAGING/assemble.out" 2>"$ASS_ERR" || ASS_RC=$?
|
|
|
|
if [ -n "$PIN_BACKUP" ]; then
|
|
mv "$PIN_BACKUP" "$PIN_DIR/love.nro"
|
|
fi
|
|
|
|
if [ "$ASS_RC" -ne 0 ] && grep -q -- '--fetch' "$ASS_ERR"; then
|
|
ok "assemble_loose without pin cites --fetch"
|
|
else
|
|
bad "assemble_loose without pin should fail citing --fetch (rc=$ASS_RC err=$(cat "$ASS_ERR"))"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 5a. verify_love_nx fails on checksum mismatch (corrupt copy)
|
|
# ---------------------------------------------------------------------------
|
|
VERIFY_WORK="$STAGING/verify-mismatch"
|
|
mkdir -p "$VERIFY_WORK"
|
|
# Create a private ROOT-like tree is hard; instead corrupt a temp copy and
|
|
# invoke verify by temporarily swapping the pin file.
|
|
CORRUPT_BACKUP=""
|
|
if [ -f "$PIN_DIR/love.nro" ]; then
|
|
CORRUPT_BACKUP="$STAGING/love.nro.real"
|
|
cp "$PIN_DIR/love.nro" "$CORRUPT_BACKUP"
|
|
printf 'not-the-real-love-nro\n' > "$PIN_DIR/love.nro"
|
|
VM_RC=0
|
|
VM_ERR="$STAGING/verify.err"
|
|
"$ROOT/scripts/switch/verify_love_nx.sh" >"$STAGING/verify.out" 2>"$VM_ERR" || VM_RC=$?
|
|
mv "$CORRUPT_BACKUP" "$PIN_DIR/love.nro"
|
|
if [ "$VM_RC" -ne 0 ] && grep -Eqi 'mismatch|expected' "$VM_ERR"; then
|
|
ok "verify_love_nx fails on checksum mismatch"
|
|
else
|
|
bad "verify_love_nx should fail on mismatch (rc=$VM_RC err=$(cat "$VM_ERR"))"
|
|
fi
|
|
else
|
|
# No real pin available — still assert sha256_file + manifest read path
|
|
ok "verify_love_nx mismatch skipped (no local pin binaries)"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 5b. Idempotent fetch skip when pin already valid (no network if present)
|
|
# ---------------------------------------------------------------------------
|
|
if [ -f "$PIN_DIR/love.nro" ] && [ -f "$PIN_DIR/love.elf" ]; then
|
|
if "$ROOT/scripts/switch/verify_love_nx.sh" >/dev/null 2>&1; then
|
|
FETCH_OUT="$STAGING/fetch.out"
|
|
FETCH_RC=0
|
|
"$ROOT/scripts/switch/fetch_love_nx.sh" >"$FETCH_OUT" 2>&1 || FETCH_RC=$?
|
|
if [ "$FETCH_RC" -eq 0 ] && grep -Eqi 'skip|already|verified' "$FETCH_OUT"; then
|
|
ok "fetch_love_nx idempotent skip when pin present"
|
|
elif [ "$FETCH_RC" -eq 0 ]; then
|
|
ok "fetch_love_nx exits 0 with existing valid pin"
|
|
else
|
|
bad "fetch_love_nx with valid pin failed (rc=$FETCH_RC out=$(cat "$FETCH_OUT"))"
|
|
fi
|
|
else
|
|
ok "fetch idempotent skipped (pin present but verify failed — left alone)"
|
|
fi
|
|
else
|
|
ok "fetch idempotent skipped (no local pin binaries; offline)"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 5b2. Mid-fetch / network failure: URL + tool status + retry --fetch (SWBLD-05)
|
|
# ---------------------------------------------------------------------------
|
|
FETCH_FAIL_ERR="$STAGING/fetch-fail.err"
|
|
FETCH_FAIL_OUT="$STAGING/fetch-fail.out"
|
|
FETCH_FAIL_RC=0
|
|
PIN_MOVED=""
|
|
if [ -d "$PIN_DIR" ]; then
|
|
PIN_MOVED="$STAGING/pin-backup"
|
|
mv "$PIN_DIR" "$PIN_MOVED"
|
|
fi
|
|
# Closed port / unreachable host — no real network asset required.
|
|
GEN1_LOVE_NX_BASE_URL="http://127.0.0.1:1" \
|
|
"$ROOT/scripts/switch/fetch_love_nx.sh" >"$FETCH_FAIL_OUT" 2>"$FETCH_FAIL_ERR" || FETCH_FAIL_RC=$?
|
|
if [ -n "$PIN_MOVED" ]; then
|
|
rm -rf "$PIN_DIR"
|
|
mv "$PIN_MOVED" "$PIN_DIR"
|
|
fi
|
|
if [ "$FETCH_FAIL_RC" -ne 0 ] \
|
|
&& grep -q 'download failed:' "$FETCH_FAIL_ERR" \
|
|
&& grep -Eq 'curl exit|wget exit|HTTP status' "$FETCH_FAIL_ERR" \
|
|
&& grep -q 'retry: scripts/build_switch.sh --fetch' "$FETCH_FAIL_ERR"; then
|
|
ok "fetch network failure cites URL status and retry --fetch"
|
|
else
|
|
bad "fetch failure should cite status + retry --fetch (rc=$FETCH_FAIL_RC err=$(cat "$FETCH_FAIL_ERR"))"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 5c2. fail_missing_devkitpro cites install_devkitpro_deps.sh
|
|
# ---------------------------------------------------------------------------
|
|
MDK_ERR="$STAGING/missing-dkp.err"
|
|
MDK_RC=0
|
|
(
|
|
. "$SCRIPT_DIR/common.sh"
|
|
fail_missing_devkitpro
|
|
) >"$STAGING/missing-dkp.out" 2>"$MDK_ERR" || MDK_RC=$?
|
|
|
|
if [ "$MDK_RC" -ne 0 ] \
|
|
&& grep -q 'install_devkitpro_deps.sh' "$MDK_ERR" \
|
|
&& grep -q 'DEVKITPRO' "$MDK_ERR" \
|
|
&& grep -q 'switch-dev' "$MDK_ERR"; then
|
|
ok "fail_missing_devkitpro cites DEVKITPRO + switch-dev + install_devkitpro_deps.sh"
|
|
else
|
|
bad "fail_missing_devkitpro should cite setup steps (rc=$MDK_RC err=$(cat "$MDK_ERR"))"
|
|
fi
|
|
|
|
OTA_ERR="$STAGING/missing-ota.err"
|
|
OTA_RC=0
|
|
(
|
|
. "$SCRIPT_DIR/common.sh"
|
|
fail_missing_ota_deps
|
|
) >"$STAGING/missing-ota.out" 2>"$OTA_ERR" || OTA_RC=$?
|
|
|
|
if [ "$OTA_RC" -ne 0 ] \
|
|
&& grep -q 'install_devkitpro_deps.sh' "$OTA_ERR" \
|
|
&& grep -qi 'docker' "$OTA_ERR"; then
|
|
ok "fail_missing_ota_deps cites native or Docker options"
|
|
else
|
|
bad "fail_missing_ota_deps should cite native + Docker (rc=$OTA_RC err=$(cat "$OTA_ERR"))"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 5d. fail_fused_toolchain mentions docs/switch-build.md
|
|
# ---------------------------------------------------------------------------
|
|
FT_ERR="$STAGING/fused-toolchain.err"
|
|
FT_RC=0
|
|
(
|
|
# Invoke as a function in a subshell that sources common
|
|
. "$SCRIPT_DIR/common.sh"
|
|
fail_fused_toolchain
|
|
) >"$STAGING/fused-toolchain.out" 2>"$FT_ERR" || FT_RC=$?
|
|
|
|
if [ "$FT_RC" -ne 0 ] && grep -q 'docs/switch-build.md' "$FT_ERR"; then
|
|
ok "fail_fused_toolchain cites docs/switch-build.md"
|
|
else
|
|
bad "fail_fused_toolchain should mention docs/switch-build.md (rc=$FT_RC err=$(cat "$FT_ERR"))"
|
|
fi
|
|
|
|
# Also check multi-OS hints
|
|
FT_LC="$(tr '[:upper:]' '[:lower:]' < "$FT_ERR")"
|
|
OS_MISSING=""
|
|
printf '%s' "$FT_LC" | grep -q 'macos' || OS_MISSING="${OS_MISSING} macOS"
|
|
printf '%s' "$FT_LC" | grep -q 'linux' || OS_MISSING="${OS_MISSING} Linux"
|
|
printf '%s' "$FT_LC" | grep -Eq 'windows|msys' || OS_MISSING="${OS_MISSING} Windows"
|
|
printf '%s' "$FT_LC" | grep -q 'docker' || OS_MISSING="${OS_MISSING} Docker"
|
|
if [ -z "$OS_MISSING" ]; then
|
|
ok "fail_fused_toolchain mentions macOS/Linux/Windows/Docker"
|
|
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/version.txt" \
|
|
"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
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 7. Dual-NRO OTA layout (launcher + game) when 4th arg set
|
|
# ---------------------------------------------------------------------------
|
|
FAKE_LAUNCHER="$STAGING/fake-launcher.nro"
|
|
FAKE_GAME="$STAGING/fake-game.nro"
|
|
printf 'fake-launcher\n' > "$FAKE_LAUNCHER"
|
|
printf 'fake-game\n' > "$FAKE_GAME"
|
|
OTA_ZIP="$STAGING/gen1recomp-0.0.2-ota-layout-switch.zip"
|
|
OTA_RC=0
|
|
"$ROOT/scripts/switch/pack_sd_zip.sh" "$FAKE_GAME" "0.0.2" "$OTA_ZIP" "$FAKE_LAUNCHER" \
|
|
>"$STAGING/ota-pack.out" 2>"$STAGING/ota-pack.err" || OTA_RC=$?
|
|
OTA_LIST="$(unzip -Z1 "$OTA_ZIP" 2>/dev/null || true)"
|
|
if [ "$OTA_RC" -eq 0 ] \
|
|
&& printf '%s\n' "$OTA_LIST" | grep -Fq 'switch/gen1recomp/gen1recomp.nro' \
|
|
&& printf '%s\n' "$OTA_LIST" | grep -Fq 'switch/gen1recomp/gen1recomp-game.nro' \
|
|
&& printf '%s\n' "$OTA_LIST" | grep -Fq 'switch/gen1recomp/version.txt'
|
|
then
|
|
EXTRACT_OTA="$STAGING/extract-ota"
|
|
rm -rf "$EXTRACT_OTA"
|
|
mkdir -p "$EXTRACT_OTA"
|
|
unzip -q "$OTA_ZIP" -d "$EXTRACT_OTA"
|
|
DUAL_OK=1
|
|
cmp -s "$FAKE_LAUNCHER" "$EXTRACT_OTA/switch/gen1recomp/gen1recomp.nro" || DUAL_OK=0
|
|
cmp -s "$FAKE_GAME" "$EXTRACT_OTA/switch/gen1recomp/gen1recomp-game.nro" || DUAL_OK=0
|
|
[ "$(cat "$EXTRACT_OTA/switch/gen1recomp/version.txt")" = "0.0.2" ] || DUAL_OK=0
|
|
if [ "$DUAL_OK" -eq 1 ]; then
|
|
ok "pack_sd_zip.sh dual-NRO OTA layout (launcher + game + version.txt)"
|
|
else
|
|
bad "pack_sd_zip.sh dual-NRO bytes/version mismatch"
|
|
fi
|
|
else
|
|
bad "pack_sd_zip.sh dual-NRO layout failed (rc=$OTA_RC err=$(cat "$STAGING/ota-pack.err"))"
|
|
fi
|
|
|
|
MANIFEST="$ROOT/scripts/switch/ota_launcher.manifest"
|
|
if [ -f "$MANIFEST" ] && grep -q '^OTA_ENABLED=1$' "$MANIFEST" \
|
|
&& grep -q 'ENTRY_NRO=switch/gen1recomp/gen1recomp.nro' "$MANIFEST" \
|
|
&& grep -q 'GAME_NRO=switch/gen1recomp/gen1recomp-game.nro' "$MANIFEST"
|
|
then
|
|
ok "ota_launcher.manifest requires dual-NRO when OTA_ENABLED=1"
|
|
else
|
|
bad "ota_launcher.manifest missing OTA dual-NRO requirements"
|
|
fi
|
|
|
|
if [ -f "$ROOT/scripts/switch/build_ota_launcher.sh" ] \
|
|
&& grep -q 'ota_launcher_deps_ready' "$ROOT/scripts/switch/build_ota_launcher.sh" \
|
|
&& grep -q 'fail_missing_devkitpro' "$ROOT/scripts/switch/build_ota_launcher.sh" \
|
|
&& grep -q 'preflight_fused_build' "$ROOT/scripts/build_switch.sh" \
|
|
&& [ -f "$ROOT/ports/switch/ota-launcher/Makefile" ]
|
|
then
|
|
ok "native OTA launcher sources + build_ota_launcher.sh present"
|
|
else
|
|
bad "missing native OTA launcher tree or build script"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 8. Unified OTA asset = dual-NRO SD zip (no separate OTA-only archive)
|
|
# ---------------------------------------------------------------------------
|
|
LEGACY_OTA_PACKER="$ROOT/scripts/switch/pack_ota_zip.sh"
|
|
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 "OTA uses the same SD zip as install (legacy OTA-only packer gone)"
|
|
else
|
|
bad "legacy separate OTA-only packer / asset still present"
|
|
fi
|
|
|
|
if grep -q 'ota_ui_prompt_update' "$ROOT/ports/switch/ota-launcher/src/main.c" \
|
|
&& grep -q 'ota_net_init' "$ROOT/ports/switch/ota-launcher/src/main.c" \
|
|
&& grep -q 'framebufferCreate\|COL_RAIL' "$ROOT/ports/switch/ota-launcher/src/ota_ui.c" \
|
|
&& grep -q '^ROMFS' "$ROOT/ports/switch/ota-launcher/Makefile" \
|
|
&& grep -q 'cacert.pem' "$ROOT/ports/switch/ota-launcher/Makefile"
|
|
then
|
|
ok "launcher UI uses framebuffer (no prompt when up to date)"
|
|
else
|
|
bad "launcher missing branded ota_ui / ROMFS"
|
|
fi
|
|
|
|
if [ -f "$ROOT/ports/switch/ota-launcher/src/ota_unzip.c" ] \
|
|
&& grep -q 'zzip/zzip.h' "$ROOT/ports/switch/ota-launcher/src/ota_unzip.c" \
|
|
&& grep -q 'ota_unzip_extract_file' "$ROOT/ports/switch/ota-launcher/src/main.c"
|
|
then
|
|
ok "launcher wires zziplib ota_unzip_extract_file"
|
|
else
|
|
bad "launcher missing zziplib unzip wiring"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Summary
|
|
# ---------------------------------------------------------------------------
|
|
echo ""
|
|
say "selftest: $PASS passed, $FAIL failed"
|
|
if [ "$FAIL" -ne 0 ]; then
|
|
exit 1
|
|
fi
|
|
exit 0
|