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

2. Connect the cart to the Pi

3. Power on the N64

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.