A middleware system for a Raspberry Pi 5 based 86Box Win95/i486 emulation appliance. Bridges the 86Box emulator (via its unix socket control interface) with physical hardware — status LEDs and NFC-based disc swapping — through an ESP32-C6 microcontroller.
Async bridge between the 86Box unix control socket and a serial-connected ESP32-C6.
- Forwards
!ledand!mediastatus events from 86Box to serial for LED control - Receives
fddload/cdload/fddeject/cdejectmount commands from serial (NFC tag reads) and relays them to 86Box with an optional path prefix - Optionally polls
screencrcand sendsexitwhen the screen matches a target CRC + dimensions (for auto-shutdown when the emulated OS has shut down) - Reconnects automatically when 86Box restarts
pi486 --socket /tmp/86box.sock \
--serial /dev/ttyAMA0 \
--fdd-prefix /mnt/floppy/ \
--cd-prefix /mnt/cdrom/ \
--screencrc "27CDAD2E 656 416"
| Flag | Required | Description |
|---|---|---|
--socket, -U |
yes | 86Box unix control socket path |
--serial, -S |
no | Serial port device (falls back to stdio) |
--baud, -b |
no | Baud rate (default: 115200) |
--screencrc, -C |
no | "<CRC> <WIDTH> <HEIGHT>" — auto-exit trigger |
--fdd-prefix |
no | Path prefix for floppy mount commands |
--cd-prefix |
no | Path prefix for CD-ROM mount commands |
Connects to the Pi via 3.3V TTL UART on GPIO 14/15. Drives status LEDs and reads NFC tags.
- LEDs: Power, HDD, Floppy, CD, Network — driven by
!ledevents from serial - NFC reader: PN532 over I2C, polls NTAG215 tags every 500ms
- Tag insert: Reads tag data, sends
fddload/cdloadcommand over UART - Tag removal: 2 consecutive missed polls (~1s) triggers
fddeject/cdeject
USB-connected NFC tag writer. Accepts commands over USB serial:
| Command | Description |
|---|---|
write <data> |
Write tag (e.g. write F:0:Win95Boot.img) |
read |
Read current tag contents |
erase |
Zero all user pages |
Browser-based UI using the Web Serial API to communicate with the writer ESP32. Built with TypeScript, Vite, React, TailwindCSS, and shadcn/ui components. Requires Chrome/Edge.
NTAG215 tags (504 bytes). Simple text format:
<type>:<write_protect>:<path>
| Field | Values | Description |
|---|---|---|
| type | F, C |
Floppy or CD-ROM |
| write_protect | 0, 1 |
Write protection (floppy only) |
| path | string | Image filename (prefix added by pi486) |
Examples:
F:0:Win95Boot.img→fddload 0 /mnt/floppy/Win95Boot.img 0C:0:Quake.iso→cdload 0 /mnt/cdrom/Quake.iso
pi486/
├── Cargo.toml
├── flake.nix # Nix dev shell
├── src/
│ ├── main.rs # CLI, entry point
│ ├── bridge.rs # Socket ↔ serial event loop
│ ├── protocol.rs # Command parsing, path prefix, screencrc
│ ├── serial.rs # Serial port / stdio abstraction
│ └── socket.rs # Unix socket connection + reconnect
├── esp32-appliance/
│ └── esp32-appliance.ino # Appliance firmware (LEDs + NFC reader)
├── esp32-writer/
│ └── esp32-writer.ino # Writer firmware (USB serial + NFC writer)
└── writer-ui/ # Web UI (Vite + React + TypeScript)
├── src/
│ ├── App.tsx
│ ├── lib/serial.ts # Web Serial API abstraction
│ └── components/ui/ # shadcn-style components
└── package.json
cargo build --releasecd writer-ui
npm install
npm run buildOpen esp32-appliance/esp32-appliance.ino or esp32-writer/esp32-writer.ino in the Arduino IDE with ESP32-C6 board support installed. Requires the Adafruit_PN532 library.
With Nix:
nix developThis provides Rust toolchain, Node.js, and Arduino CLI in a single shell.