Connect your SummerCart64 to this server
n64sync pushes N64 ROMs onto a SummerCart64 (SC64) flashcart plugged into
this Raspberry Pi over USB-C. The sc64deployer tool and its USB libraries are
built into n64sync — nothing to install. You only do the physical setup below (once), then
drop ROMs on the Library page and the sync worker copies them to the card whenever it's connected.
1. Prepare the microSD
- Format the card FAT32 (or exFAT for very large cards) and insert it into the SC64.
- No need to copy the menu yourself — n64sync installs the boot browser
(
sc64menu.n64) onto a blank card automatically when the cart connects (with the N64 powered on), and keeps it up to date when a newer version ships. It's the ROM browser the SC64 auto-loads at power-on, and the "library" n64sync fills. - Placed your own menu on the card? It's left untouched — updates only ever replace a
menu n64sync installed. (Disable entirely with
AUTO_MENU=0.)
2. Connect the cart to the Pi
- Connect the SC64 to the Pi with a USB-C cable.
- The Library banner shows "SC64 connected" once it's detected — no setup needed, the deployer runs on the Pi inside n64sync.
- The microSD does not mount as a USB drive — n64sync writes it through the deployer over USB, so there's nothing to mount.
3. Power on the N64
- The cart is seen over USB even with the console off, but writing the SD can require the N64 powered ON. If ROMs stage but never flip to Synced, switch the console on and check the Library banner's last error.
- Then just add ROMs: they convert to
.z64, queue on the Pi, and copy to the card automatically. Browse them fromsc64menu.n64on the TV.
SC64 firmware
The cart's internal firmware — separate from the boot menu on the SD. n64sync bundles a matching version and can flash it over USB. Updating is optional; only do it to move to a newer version.
On the cart: … · Bundled in this app: …
Cart not detected?
The container needs access to the Pi's FTDI USB device. That's a one-time
host/deploy setting (USB passthrough + the plugdev/dialout group,
or a udev rule), configured in the stack — not something you do from this page. See the deploy notes.
SummerCart64 docs: github.com/Polprzewodnikowy/SummerCart64. Homebrew flashcart tools only — this app never provides game files.
Stuck? Hand this to an AI assistant
Copy the block below and paste it to an LLM (Claude, ChatGPT, …) together with what you're seeing. It has everything needed to help — including the USB / container connection steps that trip most people up.
n64sync — context for an AI assistant
WHAT IT IS
A self-hosted web app (Node + Fastify + SQLite) that stages N64 ROMs — a browser
upload (.z64/.v64/.n64, or a .zip containing one), or a mod installed from
romhacking.com — and pushes them onto a SummerCart64 (SC64) flashcart's microSD
over USB with the sc64deployer CLI. It runs as an arm64 Docker container on a
Raspberry Pi, non-root (uid 1000). A background worker polls every few seconds:
"sc64deployer list" to detect the cart, then "sc64deployer sd upload" for each
staged ROM. It also auto-installs the sc64menu.n64 boot menu on a blank SD and
pushes resized cover art to the SD's menu/metadata folder.
CONNECTING THE CART (most problems are here)
- The SC64 is an FTDI USB device, USB VID:PID 0403:6014. Use a USB-C DATA cable —
charge-only cables enumerate nothing.
- It is USB-bus-powered: it is detected with the N64 powered OFF. The console is
only needed to actually play; SD read/write works with the cart standalone.
- On the Pi HOST: lsusb | grep 0403:6014 (must list an FT232H)
nothing -> bad/charge-only cable, or dead/unpowered port; try another.
- In the CONTAINER: docker exec n64sync sc64deployer list (must list the SC64;
this is the exact check the Library "connected" banner runs)
HOST SEES IT BUT THE CONTAINER DOES NOT
- Permission: the app runs as uid 1000 and cannot open a root-owned USB device
node. Add a udev rule on the Pi so it is openable:
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="0666"' | sudo tee /etc/udev/rules.d/99-sc64.rules
sudo udevadm control --reload-rules
sudo udevadm trigger
then unplug and replug the cart.
- Hotplug: docker's "devices:" mapping only captures USB nodes that exist when the
container is created. If the cart was plugged in afterwards, recreate it with the
cart already plugged in:
docker compose up -d --force-recreate n64sync
- The compose service needs USB passthrough: devices: /dev/bus/usb:/dev/bus/usb
(or, bluntly, privileged: true).
STAGING / SYNC BEHAVIOUR
- A ROM sits as "staged" until the cart is connected, then flips to "synced" and
its staging copy is freed. A failed upload is almost always "SD not accessible"
(transient) and simply retries on the next poll.
DEPLOY
arm64 image on GHCR, run as a Dockge stack behind a Tailscale funnel. The image
compiles sc64deployer from source (upstream ships no arm64 build) and bundles
sc64menu.n64. Env knobs: SC64_POLL_MS, AUTO_MENU, AUTO_BOXART, AUTH_TOKEN.