diff --git a/.gitignore b/.gitignore index 862484ca..d68dbada 100644 --- a/.gitignore +++ b/.gitignore @@ -37,22 +37,22 @@ mobile/ios/build/ # Final packaged build artifacts (mac/win/web/android/ios/switch) — see scripts/build.sh /dist/ -# Native Switch OTA launcher build outputs -native/switch-ota-launcher/build/ -native/switch-ota-launcher/build-host/ -native/switch-ota-launcher/*.nro -native/switch-ota-launcher/*.nacp -native/switch-ota-launcher/*.elf -native/switch-ota-launcher/*.map -native/switch-ota-launcher/romfs/logo.rgba -native/switch-ota-launcher/romfs/logo.png -native/switch-ota-launcher/romfs/cacert.pem -native/switch-ota-launcher/romfs/ota-bootstrap.nro -native/switch-ota-bootstrap/build/ -native/switch-ota-bootstrap/*.nro -native/switch-ota-bootstrap/*.nacp -native/switch-ota-bootstrap/*.elf -native/switch-ota-bootstrap/*.map +# Switch OTA launcher build outputs +ports/switch/ota-launcher/build/ +ports/switch/ota-launcher/build-host/ +ports/switch/ota-launcher/*.nro +ports/switch/ota-launcher/*.nacp +ports/switch/ota-launcher/*.elf +ports/switch/ota-launcher/*.map +ports/switch/ota-launcher/romfs/logo.rgba +ports/switch/ota-launcher/romfs/logo.png +ports/switch/ota-launcher/romfs/cacert.pem +ports/switch/ota-launcher/romfs/ota-bootstrap.nro +ports/switch/ota-bootstrap/build/ +ports/switch/ota-bootstrap/*.nro +ports/switch/ota-bootstrap/*.nacp +ports/switch/ota-bootstrap/*.elf +ports/switch/ota-bootstrap/*.map # Legacy manual convenience-copy location (superseded by /dist/android/) mobile/dist/ diff --git a/docs/switch-build.md b/docs/switch-build.md index 9593524c..61f8a574 100644 --- a/docs/switch-build.md +++ b/docs/switch-build.md @@ -41,10 +41,10 @@ Fused game builds can also use Docker when native `nacptool`/`elf2nro` are absen In-console OTA uses a **separate DEVKITPRO NRO** (not LÖVE). The LÖVE self-updater (`Check.lua`) is disabled on NX. Source: -`native/switch-ota-launcher/`. Host protocol tests (no toolchain): +`ports/switch/ota-launcher/`. Host protocol tests (no toolchain): ```sh -make -C native/switch-ota-launcher host-test +make -C ports/switch/ota-launcher host-test # or scripts/switch/build_ota_launcher.sh # host-test first; NRO needs DEVKITPRO/Docker ``` @@ -59,7 +59,7 @@ Release-like build from repo root: scripts/build_switch.sh --fetch --fused --version X.Y.Z ``` -See `native/switch-ota-launcher/README.md` and +See `ports/switch/ota-launcher/README.md` and `scripts/switch/ota_launcher.manifest`. ### Windows (Git Bash / MSYS2 / WSL) diff --git a/ports/switch/ota-launcher/Makefile b/ports/switch/ota-launcher/Makefile index d5545f00..d468c86a 100644 --- a/ports/switch/ota-launcher/Makefile +++ b/ports/switch/ota-launcher/Makefile @@ -45,8 +45,8 @@ APP_AUTHOR := bryanthaboi, port by andrewqsantos APP_VERSION ?= 0.0.0 # Prefer project Switch icon if present -ICON := $(TOPDIR)/../../assets/switch/icon.jpg -LOGO_RGBA_SRC := $(TOPDIR)/assets/logo.rgba +ICON := $(TOPDIR)/../assets/icon.jpg +LOGO_RGBA_SRC := $(TOPDIR)/../assets/logo.rgba LOGO_ROMFS := $(CURDIR)/$(ROMFS)/logo.rgba #--------------------------------------------------------------------------------- @@ -131,7 +131,7 @@ ifneq ($(ROMFS),) export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) endif -BOOTSTRAP_DIR := $(TOPDIR)/../switch-ota-bootstrap +BOOTSTRAP_DIR := $(TOPDIR)/../ota-bootstrap BOOTSTRAP_ROMFS := $(CURDIR)/$(ROMFS)/ota-bootstrap.nro .PHONY: $(BUILD) clean all host-test sync-romfs bootstrap-romfs diff --git a/ports/switch/ota-launcher/README.md b/ports/switch/ota-launcher/README.md index b61d5761..f6865955 100644 --- a/ports/switch/ota-launcher/README.md +++ b/ports/switch/ota-launcher/README.md @@ -11,7 +11,7 @@ with `envSetNextLoad`. The LÖVE self-updater (`src/update/Check.lua`) stays **disabled** on NX. Wire format (also in Lua): `src/update/SwitchOta.lua`. -NACP icon: `assets/switch/icon.jpg`. +NACP icon: `ports/switch/assets/icon.jpg`. ## Layout on microSD @@ -25,7 +25,7 @@ sdmc:/switch/gen1recomp/pokemon-love2d/ <- saves (never touched by OTA) ## Host tests (no DEVKITPRO) ```bash -cd native/switch-ota-launcher +cd ports/switch/ota-launcher make host-test ``` @@ -40,7 +40,7 @@ Needs `DEVKITPRO` with packages roughly: ```bash export DEVKITPRO=/opt/devkitpro # typical -cd native/switch-ota-launcher +cd ports/switch/ota-launcher make # -> gen1recomp.nro ``` @@ -62,7 +62,7 @@ Docker fallback uses the same pin as fused builds (`scripts/switch/dkp-docker.im ## OTA logo asset The launcher draws a pre-scaled logo from `romfs:/logo.rgba` (no PNG decoder in -the NRO). The baked blob lives at `assets/logo.rgba` and is copied into romfs at +the NRO). The baked blob lives at `../assets/logo.rgba` and is copied into romfs at build time. After changing `assets/logo/logo.png`, regenerate: ```bash diff --git a/scripts/switch/bake_ota_logo.py b/scripts/switch/bake_ota_logo.py index 1703730e..bbfc989f 100644 --- a/scripts/switch/bake_ota_logo.py +++ b/scripts/switch/bake_ota_logo.py @@ -23,7 +23,7 @@ from pathlib import Path ROOT = Path(__file__).resolve().parents[2] DEFAULT_SRC = ROOT / "assets/logo/logo.png" -DEFAULT_OUT = ROOT / "native/switch-ota-launcher/assets/logo.rgba" +DEFAULT_OUT = ROOT / "ports/switch/assets/logo.rgba" DEFAULT_MAX_W = 320 DEFAULT_MAX_H = 90 diff --git a/scripts/switch/build_fused.sh b/scripts/switch/build_fused.sh index 26024386..b6dbf5e3 100755 --- a/scripts/switch/build_fused.sh +++ b/scripts/switch/build_fused.sh @@ -15,7 +15,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" LOVE_NX_TAG="11.5-nx1" LOVE_NX_DIR="$ROOT/.bazinga/love-nx/$LOVE_NX_TAG" LOVE_ELF="$LOVE_NX_DIR/love.elf" -ICON="$ROOT/assets/switch/icon.jpg" +ICON="$ROOT/ports/switch/assets/icon.jpg" APP_NAME="gen1recomp" APP_AUTHOR="bryanthaboi, port by andrewqsantos" DKP_IMAGE_FILE="$ROOT/scripts/switch/dkp-docker.image" @@ -93,7 +93,7 @@ run_fused_docker() { set -euo pipefail nacptool --create '$APP_NAME' '$APP_AUTHOR' '$VERSION' /work/control.nacp elf2nro /src/.bazinga/love-nx/$LOVE_NX_TAG/love.elf /out/$out_base \ - --icon=/src/assets/switch/icon.jpg \ + --icon=/src/ports/switch/assets/icon.jpg \ --nacp=/work/control.nacp \ --romfsdir=/work/romfs " diff --git a/scripts/switch/build_ota_launcher.sh b/scripts/switch/build_ota_launcher.sh index c8a8facd..4de830fb 100755 --- a/scripts/switch/build_ota_launcher.sh +++ b/scripts/switch/build_ota_launcher.sh @@ -14,7 +14,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" # shellcheck source=common.sh . "$SCRIPT_DIR/common.sh" -LAUNCHER_DIR="$ROOT/native/switch-ota-launcher" +LAUNCHER_DIR="$ROOT/ports/switch/ota-launcher" OUT_NRO="${1:-$ROOT/dist/switch/gen1recomp-launcher.nro}" APP_VERSION="${2:-${GEN1_LAUNCHER_VERSION:-0.0.0}}" DKP_IMAGE_FILE="$ROOT/scripts/switch/dkp-docker.image" @@ -59,7 +59,7 @@ if command -v docker >/dev/null 2>&1; then say "building launcher NRO via Docker ($image, NACP $APP_VERSION)" if ! docker run --rm \ -v "$ROOT:/work" \ - -w /work/native/switch-ota-launcher \ + -w /work/ports/switch/ota-launcher \ -e "APP_VERSION=$APP_VERSION" \ "$image" \ bash -lc 'pacman -Sy --noconfirm switch-curl switch-mbedtls switch-zlib switch-zziplib >/dev/null 2>&1 || true; make clean; make all APP_VERSION="$APP_VERSION"'; then diff --git a/scripts/switch/common.sh b/scripts/switch/common.sh index b08494dc..eb4cfb15 100644 --- a/scripts/switch/common.sh +++ b/scripts/switch/common.sh @@ -102,7 +102,7 @@ Pick one: Then re-run: scripts/build_switch.sh --fetch --fused -See docs/switch-build.md and native/switch-ota-launcher/README.md. +See docs/switch-build.md and ports/switch/ota-launcher/README.md. EOF )" } @@ -121,7 +121,7 @@ Re-run with a clean tree: If packages look wrong, reinstall: bash scripts/switch/install_devkitpro_deps.sh -See native/switch-ota-launcher/README.md. +See ports/switch/ota-launcher/README.md. EOF )" fi diff --git a/scripts/switch/selftest_build_switch.sh b/scripts/switch/selftest_build_switch.sh index 1f8be38d..99928faf 100755 --- a/scripts/switch/selftest_build_switch.sh +++ b/scripts/switch/selftest_build_switch.sh @@ -395,7 +395,7 @@ 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/native/switch-ota-launcher/Makefile" ] + && [ -f "$ROOT/ports/switch/ota-launcher/Makefile" ] then ok "native OTA launcher sources + build_ota_launcher.sh present" else @@ -415,20 +415,20 @@ else bad "legacy separate OTA-only packer / asset still present" fi -if grep -q 'ota_ui_prompt_update' "$ROOT/native/switch-ota-launcher/src/main.c" \ - && grep -q 'ota_net_init' "$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" \ - && grep -q 'cacert.pem' "$ROOT/native/switch-ota-launcher/Makefile" +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/native/switch-ota-launcher/src/ota_unzip.c" ] \ - && grep -q 'zzip/zzip.h' "$ROOT/native/switch-ota-launcher/src/ota_unzip.c" \ - && grep -q 'ota_unzip_extract_file' "$ROOT/native/switch-ota-launcher/src/main.c" +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 diff --git a/test/switch-nro-ota.spec.test.js b/test/switch-nro-ota.spec.test.js index 6d25f97d..7d64934b 100644 --- a/test/switch-nro-ota.spec.test.js +++ b/test/switch-nro-ota.spec.test.js @@ -457,8 +457,8 @@ test('AC-008: Gates de regressão anti-“erro invisível” @spec:AC-008', () = }); test('AC-009: Protocolo C host-testável espelha SwitchOta.lua @spec:AC-009', () => { - const proto = read('native/switch-ota-launcher/src/ota_protocol.c'); - const header = read('native/switch-ota-launcher/include/ota_protocol.h'); + const proto = read('ports/switch/ota-launcher/src/ota_protocol.c'); + const header = read('ports/switch/ota-launcher/include/ota_protocol.h'); assert.match(header, /OTA_CHECK_TIMEOUT_SEC\s+6/); assert.match(header, /ota_compare_semver/); assert.match(header, /ota_parse_release/); @@ -476,7 +476,7 @@ test('AC-009: Protocolo C host-testável espelha SwitchOta.lua @spec:AC-009', () // Compile + run C host tests (gcc) const r = spawnSync( 'make', - ['-C', path.join(root, 'native/switch-ota-launcher'), 'host-test'], + ['-C', path.join(root, 'ports/switch/ota-launcher'), 'host-test'], { encoding: 'utf8' } ); assert.equal(r.status, 0, `host-test failed:\n${r.stdout}\n${r.stderr}`); @@ -485,17 +485,17 @@ test('AC-009: Protocolo C host-testável espelha SwitchOta.lua @spec:AC-009', () test('AC-010: Fonte do launcher e Makefile DEVKITPRO existem @spec:AC-010', () => { for (const rel of [ - 'native/switch-ota-launcher/Makefile', - 'native/switch-ota-launcher/README.md', - 'native/switch-ota-launcher/src/main.c', - 'native/switch-ota-launcher/src/ota_net.c', - 'native/switch-ota-launcher/src/ota_fs.c', + 'ports/switch/ota-launcher/Makefile', + 'ports/switch/ota-launcher/README.md', + 'ports/switch/ota-launcher/src/main.c', + 'ports/switch/ota-launcher/src/ota_net.c', + 'ports/switch/ota-launcher/src/ota_fs.c', 'scripts/switch/build_ota_launcher.sh', 'docs/switch-build.md', ]) { assert.ok(fs.existsSync(path.join(root, rel)), `missing ${rel}`); } - const main = read('native/switch-ota-launcher/src/main.c'); + const main = read('ports/switch/ota-launcher/src/main.c'); assert.match(main, /envSetNextLoad|ota_fs_handoff_to_game/); assert.match(main, /gen1recomp-game\.nro|OTA_GAME_NRO_NAME/); assert.match(main, /Quiet by default|stays quiet|LÖVE self-updater stays off|self-updater stays off/i); @@ -505,13 +505,13 @@ test('AC-010: Fonte do launcher e Makefile DEVKITPRO existem @spec:AC-010', () = assert.doesNotMatch(main, /\u2026/, 'OTA UI strings must be ASCII (no Unicode ellipsis)'); assert.doesNotMatch(main, /ota_ui_alert\([^)]*Install failed/, 'generic install alert removed'); assert.doesNotMatch(main, /consoleInit/, 'no terminal console UI'); - assert.ok(fs.existsSync(path.join(root, 'native/switch-ota-launcher/src/ota_ui.c'))); - const otaUi = read('native/switch-ota-launcher/src/ota_ui.c'); + assert.ok(fs.existsSync(path.join(root, 'ports/switch/ota-launcher/src/ota_ui.c'))); + const otaUi = read('ports/switch/ota-launcher/src/ota_ui.c'); assert.match(otaUi, /COL_RAIL_R|rail|FFD600|255,\s*214/); assert.match(otaUi, /logo\.rgba/); assert.doesNotMatch(otaUi, /stb_image/); assert.ok( - fs.existsSync(path.join(root, 'native/switch-ota-launcher/assets/logo.rgba')), + fs.existsSync(path.join(root, 'ports/switch/assets/logo.rgba')), 'pre-baked OTA logo asset' ); assert.ok( @@ -521,44 +521,44 @@ test('AC-010: Fonte do launcher e Makefile DEVKITPRO existem @spec:AC-010', () = assert.match(otaUi, /ota_ui_sanitize_ascii/); assert.match(otaUi, /draw_text_wrapped_centered/); assert.match(otaUi, /ota_ui_alert_error/); - assert.match(read('native/switch-ota-launcher/src/ota_net.c'), /ota_net_init/); - assert.match(read('native/switch-ota-launcher/src/main.c'), /ota_net_init/); - assert.match(read('native/switch-ota-launcher/src/ota_net.c'), /CURLOPT_SSL_VERIFYPEER,\s*1L/); - assert.match(read('native/switch-ota-launcher/src/ota_net.c'), /romfs:\/cacert\.pem/); - assert.doesNotMatch(read('native/switch-ota-launcher/src/ota_net.c'), /CURLOPT_SSL_VERIFYPEER,\s*0L/); - assert.match(read('native/switch-ota-launcher/Makefile'), /^ROMFS\s*:=/m); - assert.match(read('native/switch-ota-launcher/Makefile'), /cacert\.pem/); - assert.match(read('native/switch-ota-launcher/Makefile'), /logo\.rgba/); + assert.match(read('ports/switch/ota-launcher/src/ota_net.c'), /ota_net_init/); + assert.match(read('ports/switch/ota-launcher/src/main.c'), /ota_net_init/); + assert.match(read('ports/switch/ota-launcher/src/ota_net.c'), /CURLOPT_SSL_VERIFYPEER,\s*1L/); + assert.match(read('ports/switch/ota-launcher/src/ota_net.c'), /romfs:\/cacert\.pem/); + assert.doesNotMatch(read('ports/switch/ota-launcher/src/ota_net.c'), /CURLOPT_SSL_VERIFYPEER,\s*0L/); + assert.match(read('ports/switch/ota-launcher/Makefile'), /^ROMFS\s*:=/m); + assert.match(read('ports/switch/ota-launcher/Makefile'), /cacert\.pem/); + assert.match(read('ports/switch/ota-launcher/Makefile'), /logo\.rgba/); - const mk = read('native/switch-ota-launcher/Makefile'); + const mk = read('ports/switch/ota-launcher/Makefile'); assert.match(mk, /libnx\/switch_rules|DEVKITPRO/); assert.match(mk, /-lcurl/); assert.match(mk, /-lzzip/); - assert.match(mk, /assets\/switch\/icon\.jpg/, 'uses project Switch icon'); + assert.match(mk, /ports\/switch\/assets\/icon\.jpg|assets\/icon\.jpg/, 'uses project Switch icon'); - assert.ok(fs.existsSync(path.join(root, 'native/switch-ota-launcher/src/ota_unzip.c'))); - assert.match(read('native/switch-ota-launcher/src/ota_unzip.c'), /zzip\/zzip\.h/); - assert.match(read('native/switch-ota-launcher/src/main.c'), /ota_unzip_extract_file/); - assert.match(read('native/switch-ota-launcher/src/main.c'), /GAME_MEMBER_IN_ZIP|switch\/gen1recomp\//); - assert.match(read('native/switch-ota-launcher/src/main.c'), /LAUNCHER_MEMBER_IN_ZIP|ota_fs_stage_launcher_bootstrap/); - assert.match(read('native/switch-ota-launcher/src/main.c'), /ota_fs_stage_launcher_bootstrap\([\s\S]*\) != 0/); - assert.match(read('native/switch-ota-launcher/src/main.c'), /return 2.*bootstrap|bootstrap.*return 2/i); - assert.match(read('native/switch-ota-launcher/src/ota_fs.c'), /ota_fs_atomic_replace_nro/); - assert.match(read('native/switch-ota-launcher/src/ota_fs.c'), /remove\(dest\)/); - assert.doesNotMatch(read('native/switch-ota-launcher/src/ota_fs.c'), /#ifdef _WIN32[\s\S]*remove\(dest\)/); + assert.ok(fs.existsSync(path.join(root, 'ports/switch/ota-launcher/src/ota_unzip.c'))); + assert.match(read('ports/switch/ota-launcher/src/ota_unzip.c'), /zzip\/zzip\.h/); + assert.match(read('ports/switch/ota-launcher/src/main.c'), /ota_unzip_extract_file/); + assert.match(read('ports/switch/ota-launcher/src/main.c'), /GAME_MEMBER_IN_ZIP|switch\/gen1recomp\//); + assert.match(read('ports/switch/ota-launcher/src/main.c'), /LAUNCHER_MEMBER_IN_ZIP|ota_fs_stage_launcher_bootstrap/); + assert.match(read('ports/switch/ota-launcher/src/main.c'), /ota_fs_stage_launcher_bootstrap\([\s\S]*\) != 0/); + assert.match(read('ports/switch/ota-launcher/src/main.c'), /return 2.*bootstrap|bootstrap.*return 2/i); + assert.match(read('ports/switch/ota-launcher/src/ota_fs.c'), /ota_fs_atomic_replace_nro/); + assert.match(read('ports/switch/ota-launcher/src/ota_fs.c'), /remove\(dest\)/); + assert.doesNotMatch(read('ports/switch/ota-launcher/src/ota_fs.c'), /#ifdef _WIN32[\s\S]*remove\(dest\)/); assert.doesNotMatch(read('scripts/switch/install_devkitpro_deps.sh'), /switch-minizip/); assert.match(read('scripts/switch/install_devkitpro_deps.sh'), /switch-zziplib/); assert.match(read('scripts/switch/install_devkitpro_deps.sh'), /switch-dev/); const buildDoc = read('docs/switch-build.md'); - assert.match(buildDoc, /native\/switch-ota-launcher|build_ota_launcher/); + assert.match(buildDoc, /ports\/switch\/ota-launcher|build_ota_launcher/); assert.match(buildDoc, /native packages.*or.*Docker|native or Docker/i); assert.match(buildDoc, /--fused|install_devkitpro_deps/); assert.match(buildDoc, /Requires DEVKITPRO|DEVKITPRO is[\s\S]*required/i); assert.doesNotMatch(buildDoc, /switch-ota\.zip/); assert.doesNotMatch(buildDoc, /--ota\b/); - const readme = read('native/switch-ota-launcher/README.md'); + const readme = read('ports/switch/ota-launcher/README.md'); assert.match(readme, /DEVKITPRO|devkitPro/i); assert.match(readme, /Docker|devkita64/i); assert.match(readme, /Quiet|quiet|silen/i);