Skip to main content

Software Architecture

Firmware based on a Retro-Go fork with a custom display driver and target configuration for the ESP32 Emu Turbo hardware.


Platform: Retro-Go

Retro-Go is a multi-system emulator for ESP32 devices. It provides a launcher UI, save states, ROM browser (SD card), and a unified input/display/audio framework.

Why Retro-Go

CriteriaRetro-Goesp-box-emuCustom from scratch
Emulator count10+ systems6 systems1 at a time
ESP32-S3 supportMatureESP32-S3-BOX onlyManual porting
Launcher UIBuilt-inLVGL-basedMust build
Save statesYesYesMust implement
SD card ROM browserYesYesMust implement
Community / forksLargeSmallNone
SNES coresnes9x2010 (slow)WIPMust port

Supported Emulators

CoreSystemResolutionQEMU BenchmarkFPS on ESP32-S3
nofrendoNES / Famicom256x240655 fps (10.9x)60 fps
gnuboyGame Boy160x144432 fps (7.2x)60 fps
gnuboyGame Boy Color160x144393 fps (6.5x)60 fps
smsplusMaster System256x192481 fps (8.0x)60 fps
smsplusGame Gear160x144484 fps (8.1x)60 fps
pce-goPC Engine / TurboGrafx-16256x240617 fps (10.3x)60 fps
handyAtari Lynx160x10260 fps
gwenesisSega Genesis / Mega Drive320x22450-60 fps
gw-emulatorGame & Watchvarious60 fps
snes9xSNES / Super Famicom256x224556 fps CPU (9.3x)~60 fps (estimated)

All systems run at full speed on ESP32-S3 N16R8 @ 240MHz. QEMU benchmark confirms 6.5-10.9x headroom vs 60fps target. See QEMU Benchmark for full details.


Implementation Roadmap

PhaseDescriptionStatusDetails
Phase 1Hardware Abstraction (ESP-IDF bootstrap)✅ DoneFirmware
Phase 2Retro-Go Integration (fork + custom drivers)✅ DoneFirmware
Phase 3All Emulators at Full Speed⏳ Needs HWFirmware
Phase 4SNES Optimization (30→60 FPS)📋 PlannedSNES Optimization
Phase 5v2 Audio Coprocessor (ESP32-S3-MINI-1)📋 PlannedSNES Optimization

Display Driver

ILI9488 8-bit Parallel (i80 Bus)

Retro-Go ships with an SPI-only ILI9341 driver. Our hardware uses 8-bit 8080 parallel which requires a custom driver. The firmware uses the atanisoft/esp_lcd_ili9488 component with the esp_lcd_panel_io_i80 bus API.

There is no espressif/esp_lcd_ili9488

idf_component.yml required that non-existent component for months, so the firmware had never actually built. The namespace is atanisoft/ — see Virtual Bench findings.

ESP32-S3                      ILI9488 (3.95" 320x480)
───────── ──────────────────────────
GPIO 4-11 (D0-D7) ────────► DB0-DB7 (8-bit data bus)
GPIO 12 (CS) ────────► CS (chip select)
GPIO 14 (DC) ────────► DC (data/command)
GPIO 46 (WR) ────────► WR (write strobe)
+3V3 (RD) ────────► RD (tied HIGH, no read-back)
GPIO 13 (RST) ────────► RST (reset)
+5V via R27 (20 Ω) ────────► LED-A (always-on backlight, net LED_BLA)

GPIO4–11 form a contiguous 8-bit bus, enabling efficient DMA transfers.

Bandwidth

A full 320×480 RGB565 frame at 60 fps needs 18.4 MB/s:

InterfaceClockThroughput60fps 320x480 16-bit
SPI (ILI9341)40 MHz5.0 MB/s368% — impossible
8-bit i80 (ours)20 MHz20.0 MB/s92% utilization

The 8080 parallel bus has 4x the bandwidth of SPI. Full-screen 60 fps fits with ~8% margin; the real headroom for scaling and double-buffering comes from the fact that emulator frames are letterboxed, not full-screen.

Frame Scaling

Source systemNative res→ Display 320x480Method
NES256x240256x240 centered1:1 letterbox
SNES256x224256x448 (2x V)Integer 2x vertical
Game Boy160x144320x288 (2x both)Integer 2x
Genesis320x224320x448 (2x V)Integer 2x vertical
Master System256x192256x384 (2x V)Integer 2x vertical

The ILI9488 at 320x480 is well-suited: most systems are ≤320px wide and can be doubled vertically for a crisp image with black bars.


Memory Map

┌─────────────────────────────────────────────────┐
│ Internal SRAM (520 KB) │
│ ├─ FreeRTOS stacks ~32 KB │
│ ├─ DMA buffers (display) ~40 KB │
│ ├─ I2S audio DMA ~8 KB │
│ ├─ Emulator hot buffers ~150 KB (SNES) │
│ ├─ Input / misc ~10 KB │
│ └─ Free ~280 KB │
├─────────────────────────────────────────────────┤
│ Octal PSRAM (8 MB) │
│ ├─ ROM image up to 6 MB │
│ ├─ Emulator state / VRAM ~512 KB │
│ ├─ Frame buffer (x2) ~300 KB │
│ ├─ Save states ~256 KB │
│ └─ Free ~1 MB │
├─────────────────────────────────────────────────┤
│ Flash (16 MB) │
│ ├─ Firmware ~2-4 MB │
│ ├─ NVS (settings) ~64 KB │
│ ├─ OTA partition ~4 MB (optional) │
│ └─ Free / SPIFFS ~8 MB │
└─────────────────────────────────────────────────┘

Reference Projects

ProjectWhat it doesUseful for
ducalex/retro-goMulti-system emulator for ESP32Base framework (our fork)
fcipaq/snes9x_esp32Optimized SNES on ESP32-P4/S3IRAM optimizations, ~45fps on S3
ohdarling/retro-goRetro-Go fork for ESP32-S3S3-specific patches
esp-box-emuEmulators on ESP32-S3-BOXLVGL UI reference
atanisoft/esp_lcd_ili9488ILI9488 ESP-IDF driverDisplay driver reference
libretro/snes9x2010Lightweight snes9x forkSNES core source