Skip to content

DIY FujiNet for the Intellivision

Thomas Cherryhomes edited this page Aug 20, 2026 · 1 revision

DIY FujiNet for the Intellivision

Turn a PiRTO II or PiRTO II DUO multicart plus an ESP32-S3 dev board into a FujiNet-enabled Intellivision cartridge, using only parts you can buy today.

Note

Source-verified as of August 2026 against fujinet-firmware master — every command, pin number and memory figure below was built and run, not remembered. See Intellivision Programming for the IntyBASIC mailbox API and Fujinet Intellivision Mailbox Protocol for the firmware-side protocol reference. This page is the hardware/build guide those two assume you already have working.


Contents

  1. What you're building
  2. Status and limitations
  3. Shopping list
  4. Host toolchain
  5. Part 1 — Build and flash the ESP32-S3
  6. Part 2 — Build and flash the cartridge
  7. Part 3 — Wire it up and get the power right
  8. Part 4 — First boot
  9. Part 5 — Diagnostics

What you're building

Intellivision --CP-1610 bus--> PiRTO II / II DUO --USB CDC--> ESP32-S3 (USB host)
   CONFIG          $9C00-$9F3F mailbox            device -> host   FujiBus/SLIP

The Intellivision talks to a FujiNet-aware boot ROM, CONFIG, running on the cartridge's own RP2040 (PiRTO II) or RP2350 (PiRTO II DUO). CONFIG reads and writes a shared-memory mailbox at $9C00-$9F3F to ask for WiFi setup, host slots, and ROM downloads. The cartridge's firmware relays those requests over USB to an ESP32-S3 running fujinet-firmware, which does the actual networking and hands a ROM back.

The important, easy-to-miss detail: the ESP32-S3 is the USB host, and the cartridge is the USB device. That is backwards from how most people wire up a microcontroller pair, and it's the reason Part 3 below is not "just plug both into power."

Status and limitations

Important

  • This firmware fork has not yet been verified on real Minty-based cartridge hardware. The protocol it carries — the mailbox layout, the USB link, the ESP32-side handling — was proven out end-to-end on an earlier, non-Minty PiRTO II prototype, reliably surviving repeated console resets. If something here doesn't work as described, that's the gap most likely to bite; please report back with ./build.sh -m output (see Part 5).
  • Flashing this firmware replaces your cartridge's stock multicart launcher entirely. The upstream Minty menu and ROM-selection UI are deleted in this fork — there is no menu, no button chord, no fallback. FujiNet CONFIG is the only boot ROM. Save a copy of your cartridge's current .uf2 before you start if you want to go back to running it as a plain multicart.
  • The firmware is GPLv3 and freely buildable — see pico/intellivision/PROVENANCE.md in the fujinet-firmware repo. The cartridge hardware design is not cleared for redistribution (no gerbers, BOM, or enclosure files are published), which is why this guide points you at buying or building a cartridge from its own upstream project rather than including board files.

Shopping list

Part Notes Where to buy
PiRTO II cartridge RP2040, 16 MB flash, USB-C. Assembled units; sellers come and go on Tindie, so check the listing before assuming it's live. oghugo.com, Chicagoland Retro Tech (Tindie), HAL's friends (Tindie)
PiRTO II DUO cartridge RP2350 (Pico 2), microSD storage. No assembled-unit listing as of August 2026 — DIY from KiCad files: diode, reset button, microSD holder, Pico 2. aotta/PiRTOIIDuo
ESP32-S3-WROOM-1 N16R8 dev board, two USB-C ports Must have a "USB" (native/OTG) port and a separate "UART" port (usually a CH340/CH343 bridge). This is a hard requirement — see Part 3. N16R8 = 16 MB flash + 8 MB octal PSRAM; N8R8 boards are not supported without adding a new build target. esp32s.com dual Type-C N16R8, Hosyond 3-pack (Amazon), AITRIP (Amazon)
USB-C to USB-C data cable Connects the cart's USB port to the S3's native USB port. Charge-only cables (no data lines) are the single most common cause of "nothing happens" — confirm it can transfer files before you rely on it. any
USB-C cable + 5 V power source Powers the S3 from its UART port — a PC USB port is easiest, since you'll want it there for flashing and monitoring anyway. any

Only build a PiRTO II or PiRTO II DUO cart — you don't need both. Part 2 below has a sub-section for each.

Host toolchain

Two separate build systems are involved: PlatformIO builds the ESP32-S3 firmware and is self-installing; the RP2040/RP2350 cartridge firmware needs the Raspberry Pi Pico SDK and its own toolchain installed by hand.

# Debian/Ubuntu — cartridge-side toolchain
sudo apt install -y git cmake ninja-build build-essential gcc-arm-none-eabi libnewlib-arm-none-eabi

# Pico SDK — the cartridge firmware needs at least 2.2.0
git clone https://github.com/raspberrypi/pico-sdk
cd pico-sdk && git submodule update --init
export PICO_SDK_PATH=$(pwd)

Put that export PICO_SDK_PATH=... line in your shell profile — Part 2 needs it every time. (This guide's steps were verified against Pico SDK 2.3.0, cmake 4.4, ninja 1.13, arm-none-eabi-gcc 16, and picotool 2.3.0.)

PlatformIO itself needs nothing preinstalled beyond Python 3 — ./build.sh creates its own virtual environment and installs PlatformIO into it on first run.

Part 1 — Build and flash the ESP32-S3

From the root of a fujinet-firmware checkout:

./build.sh -s fujiversal-intv   # one-time: writes platformio.local.ini for this board
./build.sh -cbu                 # clean, build, upload firmware
./build.sh -f                   # upload the filesystem (Web UI)

Note

-s BOARD only needs to be run once per checkout — it writes platformio.local.ini, which build.sh reuses on every later run. ./build.sh -S lists every supported board name if you want to double check fujiversal-intv is still current.

Note

The board file already sets upload_port/monitor_port to /dev/ttyACM0 — correct for the CH34x UART bridge these boards use, which enumerates as an ACM device on Linux rather than the /dev/ttyUSB* pattern most other ESP32 boards use. If your board enumerates elsewhere (a second /dev/ttyACM1, a Windows COMn, a macOS /dev/cu.*), override it in platformio.local.ini:

[env]
upload_port = /dev/ttyACM1
monitor_port = /dev/ttyACM1

Note

No WiFi credentials go in any build file. WiFi is configured at runtime, from the Intellivision's own CONFIG screen, after everything below is wired up and booted — see Part 4.

A successful build reports comfortable headroom: on this board the firmware measures roughly 20% RAM and 29% flash used, out of a 320 KB RAM / 10 MB app partition.

Part 2 — Build and flash the cartridge

Both cartridges are flashed the same way, from the same source tree, but need different cmake options. In both cases:

export PICO_SDK_PATH=/path/to/pico-sdk    # from Host toolchain, above
cd fujinet-firmware/pico/intellivision/firmware

Warning

-DCONFIG_FUJINET=ON is required on the command line for both boards below — neither board's default configuration turns it on. Omit it and the build fails at the link step looking for RunLauncher, because this fork deletes the stock Minty menu entirely (see Status and limitations).

Note

Don't use the scripts in firmware/scripts/ (build-all.sh, build-board.sh, build-release.sh). They're upstream Minty helpers that predate this fork, target boards that no longer link, and never pass -DCONFIG_FUJINET.

2a — PiRTO II (pirto_ii_default)

Builds with no source changes:

cmake -B build-pirto_ii_default -DPICO_BOARD=pirto_ii_default \
      -DCMAKE_BUILD_TYPE=Release -DCONFIG_FUJINET=ON -G Ninja
ninja -C build-pirto_ii_default
# -> build-pirto_ii_default/Minty_pirto_ii_default.uf2

The RP2040 is tight on RAM with FujiNet enabled — this build lands at roughly 98% of the chip's 264 KB, which is why boards/pirto_ii_default.cmake trims the maximum ROM size it will hand-map to 98K words to leave the mailbox room to breathe. That's expected, not a sign something is misconfigured.

2b — PiRTO II DUO (pirto_ii_duo)

Important

One-line edit required before building. Stock Minty only turns on the RP2350's USB device stack for Debug builds, since upstream only needs USB there for debug I/O. FujiNet needs that same USB link permanently in Release too — it's the entire channel to the ESP32-S3, not a debug convenience. Without this change, building pirto_ii_duo with -DCONFIG_FUJINET=ON fails with:

src/cartridge.c:45:13: fatal error: tusb.h: No such file or directory
   45 |    #include "tusb.h"

Edit boards/pirto_ii_duo.cmake and change the Release block from:

if(CMAKE_BUILD_TYPE STREQUAL "Release")
   set(CONFIG_USB_DEVICE 0)
   set(MAX_ROM_SIZE 1024*228)    # ~456 kb
endif()

to:

if(CMAKE_BUILD_TYPE STREQUAL "Release")
   set(CONFIG_USB_DEVICE 1)
   set(MAX_ROM_SIZE 1024*225)    # ~450 kb
endif()

This mirrors what boards/fujicard.cmake already does for its own (currently unbuildable integrated) board. As of August 2026 it is not committed upstream, so a git pull on fujinet-firmware will silently revert it — re-apply after updating before rebuilding.

With that edit in place:

cmake -B build-pirto_ii_duo -DPICO_BOARD=pirto_ii_duo \
      -DCMAKE_BUILD_TYPE=Release -DCONFIG_FUJINET=ON -G Ninja
ninja -C build-pirto_ii_duo
# -> build-pirto_ii_duo/Minty_pirto_ii_duo.uf2

The RP2350 has twice the RAM of the RP2040, but don't expect that headroom back — with the USB stack forced on, this build also lands at roughly 97% RAM used, essentially the same squeeze as the PiRTO II. ROMs on the DUO live on its microSD card rather than internal flash.

Flashing either cartridge

Hold the cartridge's BOOTSEL button, plug its USB-C port into your PC, and it will mount as a mass-storage drive named RPI-RP2. Drag the .uf2 file onto it; the board reboots into the new firmware automatically.

Boards this guide does not cover

Board Why not
pirto, pirto_ii_sd, pintycard Same CONFIG_USB_DEVICE 0-in-Release problem as the DUO, but the equivalent edit hasn't been tried against these — don't assume it's a drop-in fix.
fujicard Targets a single-board integrated RP2350 + ESP32-S3 cartridge design that hasn't been physically built yet.

Part 3 — Wire it up and get the power right

 Intellivision cart slot            USB-C (data)             USB-C (power)
 ───────────┬──────────    cart's native USB       S3's native USB   S3's UART port
            │              ─────────────────►      ◄────────────    ◄──────────────
     PiRTO II / II DUO                              ESP32-S3               PC / 5V supply
      (+5V from slot)                          (USB HOST — no VBUS out)
  1. The cartridge is powered by the Intellivision console through the cart slot, exactly like a normal game cartridge. Don't try to power it any other way.
  2. The ESP32-S3 is powered from its UART port, not its native USB port. Plug a USB-C cable from the UART port to a PC or 5 V supply. This is the same port you use for flashing in Part 1 and for monitoring in Part 5, so leaving it connected to your PC throughout bring-up is convenient, not just correct.
  3. The S3's native USB port is the data link to the cartridge — leave it free for that. The S3 acts as USB host on this port (fixed in silicon on GPIO19/20, invisible in any pin-map file); the cartridge is the USB device. Connect a USB-C data cable between the cartridge's USB port and the S3's native port.

Note

VBUS doesn't need to cross that data cable at all — the cartridge is already powered from the console, and is detected purely through its own USB D+ pull-up. If your particular S3 board does drive VBUS out its native port, that's tolerated rather than harmful: the cartridge firmware waits indefinitely for the console's MSYNC signal while continuing to service USB, so an early-powered cartridge just waits quietly. A full console power-cycle (MSYNC held low for more than 250 ms) unconditionally reboots the cartridge back into CONFIG, so a mistimed power-up self-corrects the next time you cycle the console.

The onboard WS2812 status LED doubles as both a WiFi indicator and bus activity light: solid white once WiFi is connected, a fast orange flicker on cartridge bus activity.

Part 4 — First boot

  1. Power the ESP32-S3 (UART port).
  2. Insert the cartridge and power on the Intellivision.
  3. The screen reads FUJINET CONFIG INTV. If the ESP32-S3 hasn't finished booting and enumerating yet, you'll briefly see:
    WAITING FOR FUJINET
    PRESS KEY TO SKIP
    
    This clears on its own within about 15 seconds once the link comes up; any keypress or controller button skips the wait early (useful if you're deliberately testing without an ESP32-S3 attached).
  4. Once linked, CONFIG offers WiFi setup. This is the only place WiFi is configured — there is nothing to set in any build file.
  5. From there: pick a network, add a TNFS/host slot, browse it, and boot a ROM. For the command-level detail of what CONFIG (and your own IntyBASIC programs) can do over the mailbox, see Intellivision Programming and Fujinet Intellivision Mailbox Protocol.

Part 5 — Diagnostics

Connect a PC to the ESP32-S3's UART port (the same one powering it) and run:

./build.sh -m

This is the primary window into what's happening — both the ESP32-S3's own logs and, once the cartridge is talking to it, mailbox activity. Also useful: lsusb (or your OS's device manager) should show a device with VID 0xCafe once the cartridge is running FujiNet firmware and plugged into the S3's native USB port — PID 0x4003 for a PiRTO II (pirto_ii_default, which also exposes a mass-storage endpoint), PID 0x4001 for a PiRTO II DUO. A device showing up with VID 0x2E8A instead means the cartridge is sitting in BOOTSEL mode, not running application firmware — the ESP32-S3 deliberately ignores that VID.

Symptom Likely cause Try this
Screen cycles colors, nothing boots The cartridge is in BOOTSEL mode, or its firmware crashed before reaching CONFIG Power-cycle the console; confirm the cart isn't mounted as an RPI-RP2 drive somewhere
Stuck on WAITING FOR FUJINET past ~15s ESP32-S3 unpowered, a charge-only USB cable, or the cart not enumerating on the S3's native port Confirm the S3's UART port is powered; swap in a known-good data cable; watch ./build.sh -m for enumeration messages
lsusb never shows VID 0xCafe Wrong USB port used for the data link, or the cart is stuck in BOOTSEL Move the data cable to the S3's native port (not UART); exit BOOTSEL by power-cycling the cart
./build.sh -u / -f can't find the port Your board's serial adapter enumerated somewhere other than /dev/ttyACM0 Override upload_port/monitor_port in platformio.local.ini, see Part 1
Please install platformio / venv errors PlatformIO's virtual environment didn't create cleanly Re-run ./build.sh; or point VENV_ROOT at a writable directory

If a cartridge firmware update ever leaves you unable to reach CONFIG, the BOOTSEL button is always available as a hard recovery path — hold it while plugging the cartridge's USB-C into a PC and re-flash the .uf2 as in Part 2.


Questions or corrections welcome — this is a new page and the hardware path it documents is still working through its first round of outside testing.

Clone this wiki locally