Co-authored-by: Cursor <cursoragent@cursor.com>
8.9 KiB
Nintendo Switch development (love-nx)
Gen1Recomp on Nintendo Switch runs on a pinned love-nx runtime. This document covers vendor layout, fetch instructions, and the Mac ↔ Switch transfer workflow.
love-nx 11.5-nx1 (pinned)
Tag: 11.5-nx1
Local layout (not committed):
.bazinga/love-nx/11.5-nx1/
├── love.nro # homebrew launcher binary (loose mode: copied to gen1recomp.nro)
└── love.elf # required for fused NRO builds (devkitPro nacptool/elf2nro)
Manifest: scripts/switch/love-nx-11.5-nx1.sha256 lists expected artifact names and SHA-256 checksums. Checksums are filled when binaries are fetched (TBD_* placeholders until then).
Fetch instructions
-
Open the 11.5-nx1 release and download
love.nroandlove.elf. -
Create the directory:
mkdir -p .bazinga/love-nx/11.5-nx1 -
Move both files into that directory.
-
Record checksums and update the manifest:
shasum -a 256 .bazinga/love-nx/11.5-nx1/love.nro \ .bazinga/love-nx/11.5-nx1/love.elf -
Replace the
TBD_*lines inscripts/switch/love-nx-11.5-nx1.sha256with the real hashes.
Never commit love-nx binaries, ROM dumps, or generated cache into git. The repo .gitignore excludes .bazinga/ (vendor cache) and /dist/ (build output).
Loose-mode dist layout
Development builds place gen1recomp.nro and game.love side by side:
dist/switch/loose/
├── gen1recomp.nro
└── game.love
Assemble with:
scripts/build_switch.sh --loose
(See scripts/switch/assemble_loose.sh for the underlying copy + checksum step.)
Transfer policy (mandatory)
Mac ↔ Switch file movement uses USB/MTP only:
- Switch: DBI →
Run MTP responder - Mac: OpenMTP (Apple Silicon build)
- Destination root:
1: SD Card/switch/gen1recomp/
Forbidden for this project (do not use as workarounds):
- Removing the microSD card to mount it on the Mac (
/Volumes/…, Finder copy) - FTP / Sphaira / any network file share to the Switch
nxlink/ netloader deploy- DBI
MicroSD install,NAND install, or other virtual install folders (NSP/NSZ/XCI paths)
If MTP fails, diagnose cable, USB port, DBI state, and OpenMTP exclusivity — do not silently fall back to forbidden methods.
OpenMTP + DBI transfer (loose build)
On the Switch
- Close Gen1Recomp if it is running.
- Open DBI from hbmenu.
- Select
Run MTP responder(DBI documentsXon the main screen). - Keep DBI on that screen for the entire transfer.
- Connect the Switch to the Mac with a USB-C data cable.
On the Mac
-
Close any other MTP clients.
-
Open OpenMTP and select the DBI device.
-
In the remote pane, open
1: SD Card. -
Navigate to
switch/and creategen1recomp/if needed. -
Enter
1: SD Card/switch/gen1recomp/. -
Drag from the local pane:
dist/switch/loose/gen1recomp.nro dist/switch/loose/game.love -
Wait for the OpenMTP queue to finish completely.
-
Refresh the remote listing and confirm file sizes match the local files.
-
On the Switch, exit MTP responder normally in DBI before launching the app.
Expected layout on SD:
1: SD Card/
└── switch/
└── gen1recomp/
├── gen1recomp.nro
└── game.love
Round-trip SHA-256 verification
For the first deploy of each artifact type (loose pair, later fused NRO), verify MTP integrity:
-
Before send — record local hashes:
shasum -a 256 dist/switch/loose/gen1recomp.nro \ dist/switch/loose/game.love -
After send — in OpenMTP, copy the same files from
1: SD Card/switch/gen1recomp/back to an empty local folder, e.g.dist/switch/mtp-roundtrip/. -
Compare round-trip hashes:
shasum -a 256 dist/switch/mtp-roundtrip/gen1recomp.nro \ dist/switch/mtp-roundtrip/game.love -
Local pre-send and round-trip hashes must match. Record results in the test report template below.
Repeat whenever a cable glitch or interrupted transfer is suspected.
Title override launch (full memory)
Applet Mode is not the primary validation path. Use title override so hbmenu runs with full memory:
- Confirm the OpenMTP transfer queue finished.
- Exit MTP responder in DBI; disconnect USB if desired.
- Hold
Rwhile launching any legitimately installed title. - Keep holding until hbmenu appears.
- Confirm hbmenu does not show Applet Mode.
- Launch
gen1recomp(or the probe NRO during Phase 0).
Album / applet launches are only useful to document applet-specific limitations; P0/P1 gates use title override.
Phase 0 hardware checklist
Complete in order on OLED hardware. Operator fills evidence fields — leave blank until tested.
| Step | Action | Pass | Evidence / notes |
|---|---|---|---|
| P0-0a | Fetch love-nx 11.5-nx1; record manifest SHA-256 | yes | See scripts/switch/love-nx-11.5-nx1.sha256 |
| P0-0b | Build switch-probe.love per tools/switch-probe/README.md |
yes | |
| P0-0c | Assemble loose probe (game.love = probe) to dist/switch/loose/ |
yes | |
| P0-0d | MTP deploy to 1: SD Card/switch/gen1recomp/; round-trip SHA-256 |
yes | nro 8290ac15…5918f5; love 9f198637…fa2e34f |
| P0-0e | Title override → probe boots; getOS() shows NX |
yes | getOS()=NX, love._os=NX |
| P0-0f | Probe lists 1280×720 (or documented dims), save path, gamepad/touch log | yes | save sdmc:/switch/gen1recomp/switch-probe; Joy-Con Y→#3 X→#4 |
| P0-1a | Replace game.love with unpatched Gen1Recomp build |
yes | feat/switch-nx inbox build |
| P0-1b | MTP replace game.love only; round-trip SHA-256 |
yes | |
| P0-1c | Title override → launcher reaches import screen | yes | |
| P0-1d | Joy-Con: can navigate launcher (no touch-only) | yes | Full report: docs/switch-hardware-evidence.md |
Operator: Andrew Date: 2026-08-01 Console: Switch OLED
love-nx tag: 11.5-nx1 gen1recomp commit: df7cea4
Phase 0 test report template
Copy this block into your hardware notes or PR evidence. Do not commit ROM files or ROM hashes of private dumps.
## Switch Phase 0 — hardware report
- Operator:
- Date:
- Console model:
- Atmosphère / HOS version:
- gen1recomp commit:
- love-nx tag: 11.5-nx1
- love.nro SHA-256 (local):
- game.love SHA-256 (local, pre-send):
- MTP round-trip SHA-256 (gen1recomp.nro):
- MTP round-trip SHA-256 (game.love):
- Title override used: yes / no
- Applet Mode observed: yes / no (should be no for P0)
- Probe getOS():
- Probe dimensions:
- Probe save directory shown:
- Gamepad events logged: yes / no
- Touch events logged: yes / no
- Unpatched launcher boot: pass / fail
- Joy-Con launcher navigation: pass / fail / not tested
- Notes:
Fast dev loop (loose mode)
While iterating on Lua/assets:
- Edit on Mac; run
scripts/test.sh --quick. - Rebuild
.bazinga/work/game.love(scripts/build.sh mac --no-notarizeor project pack step). - Close Gen1Recomp on Switch.
- DBI →
Run MTP responder. - OpenMTP →
1: SD Card/switch/gen1recomp/. - Replace only
game.love; wait for queue + refresh listing. - Exit MTP responder; launch via title override.
- Keep
gen1recomp.nrounchanged until the love-nx pin changes.
scripts/test.sh --quick
scripts/build.sh mac --no-notarize
scripts/build_switch.sh --loose
shasum -a 256 .bazinga/work/game.love
Controller input mapping (NX)
Measured on Switch OLED (feat/switch-nx, love-nx 11.5-nx1, 1280×720). Both joystickpressed and gamepadpressed fire for Joy-Con; prefer the gamepad path when joystick:isGamepad() is true.
| Path | Control | Mapping |
|---|---|---|
gamepadpressed |
D-pad / left stick | move (via GamepadMap.DEFAULT_GAMEPAD_BINDINGS) |
gamepadpressed |
a / b |
GB A / B |
gamepadpressed |
start / back |
Start / Select |
joystickpressed (raw) |
#1 Nintendo B |
GB A |
joystickpressed (raw) |
#2 Nintendo A |
GB B |
joystickpressed (raw) |
#3 Y |
GB B (measured) |
joystickpressed (raw) |
#4 X |
GB A (measured) |
joystickpressed (raw) |
#9 / #10 |
Select / Start (− / +) |
Implementation: src/core/GamepadMap.lua (NX_RAW_* tables). Launcher (RomImporter) and gameplay (Input) share the same converter.
Opt-in diagnostics: create an empty switch-debug.txt in the save directory; events flush to switch.log at ≤1 Hz with build identity (no ROM/save bytes).
Hardware re-test: P0-07/08 Joy-Con launcher + naming screen — pending operator after T15 software (T16).
Suspend/resume audio: after resume, chip music is stopped to avoid duplicate streams; confirm on hardware during P0-09/10 (T19).