Retro emulators for ESP32 FabGL (TTGO VGA and Olimex)
See the codeMulti-System Retro Emulator for ESP32-FabGL
License: GPL v3 Platform: ESP32 Display: VGA
Retro-Gamer is a multi-system retro emulator firmware for ESP32-based devices with VGA output via FabGL. It brings retro gaming to life on a big screen with crisp 320x240 resolution and 64 colors (RGB222).
This project is a port and enhancement of ducalex's Retro-Go, adapted to run on the FabGL VGA framework. It features a unified launcher for all supported systems, in-game menus, save states, and extensive customization options.
Unlike the original Retro-Go (which was designed for handheld devices with small LCD screens), Retro-Gamer is optimized for VGA displays and PS/2 keyboard input, making it perfect for DIY retro gaming consoles and arcade cabinets.
| System | Core | Extensions | Status |
|---|---|---|---|
| NES | nofrendo | .nes | ✅ Stable |
| Game Boy | gnuboy | .gb | ✅ Stable |
| Game Boy Color | gnuboy | .gbc | ✅ Stable |
| Sega Master System | smsplus | .sms | ✅ Stable |
| Sega Game Gear | smsplus | .gg | ✅ Stable |
| SG-1000 | smsplus | .sg | ✅ Stable |
| ColecoVision | smsplus | .col | ✅ Stable |
| PC Engine / TurboGrafx | pce-go | .pce | ✅ Stable |
| SNES / Super Famicom | snes9x | .sfc .smc | ⚠️ Slow |
| Atari Lynx | handy | .lnx | ✅ Stable |
| Mega Drive / Genesis | gwenesis | .md .gen .bin .smd | ⚠️ Slow |
| Feature | Description |
|---|---|
| 11 Emulators | NES, GB/GBC, SMS, GG, SG-1000, ColecoVision, PCE, SNES, Lynx, Genesis |
| In-Game Menu | Save/Load states (4 slots), turbo, palette, rotate, sound toggle, reset, quit |
| Favorites & Recent | Quick access to your favorite and recently played games |
| Save States | 4 slots per game |
| WiFi File Manager | Browser-based file upload/download |
| VGA Output | 320x240 resolution with 64 colors (RGB222) |
| PS/2 Keyboard | Full keyboard input with WASD support |
| ROM Cache | Fast boot times with cached ROM list |
| Sound Control | Toggle audio ON/OFF |
| Turbo / Fast Forward | 2× speed with continuous audio |
| Function | GPIO Pin |
|---|---|
| VGA Red 0 | GPIO 22 |
| VGA Red 1 | GPIO 21 |
| VGA Green 0 | GPIO 19 |
| VGA Green 1 | GPIO 18 |
| VGA Blue 0 | GPIO 5 |
| VGA Blue 1 | GPIO 4 |
| VGA HSYNC | GPIO 23 |
| VGA VSYNC | GPIO 15 |
| SD CS | GPIO 13 |
| Keyboard Clock | GPIO 33 |
| Keyboard Data | GPIO 32 |
| Audio DAC | GPIO 25 |
Same as above, except SD CS = GPIO 4
Create the following folder structure on your SD card:
SD Card
├── retro-go/
│ ├── config/
│ │ ├── favorites.txt
│ │ ├── recent.txt
│ │ └── wifi.json (optional)
│ └── saves/
│ ├── nes/
│ ├── gb/
│ ├── sms/
│ ├── gg/
│ ├── pce/
│ ├── snes/
│ ├── lnx/
│ ├── md/
│ └── misc/
└── roms/
├── nes/ (NES .nes, .fc)
├── gb/ (Game Boy .gb)
├── gbc/ (Game Boy Color .gbc)
├── sms/ (Master System .sms)
├── gg/ (Game Gear .gg)
├── sg1000/ (SG-1000 .sg)
├── pce/ (PC Engine .pce)
├── snes/ (SNES .sfc, .smc)
├── lnx/ (Lynx .lnx)
├── col/ (ColecoVision .col)
└── md/ (Mega Drive/Genesis .md, .gen, .bin, .smd)
esptool.py write_flash --flash_size detect 0x0 RetroGamer.bin
Or use the esptool web version for a GUI-based flashing experience.
Place your ROM files in the corresponding folders on the SD card (see SD Card Structure above).
| System | Folder | Extensions |
|---|---|---|
| NES | /roms/nes/ | .nes |
| Game Boy | /roms/gb/ | .gb |
| Game Boy Color | /roms/gbc/ | .gbc |
| Master System | /roms/sms/ | .sms |
| Game Gear | /roms/gg/ | .gg |
| SG-1000 | /roms/sg1000/ | .sg |
| PC Engine | /roms/pce/ | .pce |
| SNES | /roms/snes/ | .sfc, .smc |
| Lynx | /roms/lnx/ | .lnx |
| ColecoVision | /roms/col/ | .col |
| Mega Drive / Genesis | /roms/md/ | .md, .gen, .bin, .smd |
Save states are stored in:
/retro-go/saves/<system>/<rom_name>.sav<slot>
Example: /retro-go/saves/nes/Super_Mario_Bros.sav0
| Key | Action |
|---|---|
| ↑ / ↓ / W / S | Navigate ROM list |
| Enter | Play selected ROM |
| F | Toggle favorite |
| Tab | Switch view (All / Favorites / Recent) |
| ESC | Refresh ROM list and update cache |
| Key | Action |
|---|---|
| ↑ / ↓ / ← / → (or WASD) | D-Pad |
| Z / Space | A Button |
| X / Ctrl | B Button |
| Enter | Start |
| Right Shift | Select |
| Tab | Toggle Turbo Mode |
| ESC | Open In-Game Menu |
Press ESC during gameplay to open the in-game menu, which provides:
/retro-go/config/wifi.json on your SD card:{
"ssid0": "your-wifi-ssid",
"password0": "your-wifi-password"
}
Up to 4 networks can be configured (ssid0-ssid3).
http://<IP_ADDRESS>/ to manage files.Press Tab in-game to toggle turbo mode. When enabled:
Retro-Gamer uses a ROM cache to speed up boot times. The cache is stored at /retro-go/rom_cache.txt on your SD card.
When to refresh the cache:
How to refresh the cache:
/retro-go/rom_cache.txt from your SD card and restart the device. The cache will be rebuilt automatically./retro-go/ and delete rom_cache.txt, then restart the device.The cache is automatically updated when:
git clone https://github.com/foky26/Retro-Gamer.git
cd Retro-Gamer
. $HOME/esp/esp-idf/export.sh
idf.py build
idf.py flash
| Metric | Value |
|---|---|
| Flash Usage | ~1.9 MB / 3.14 MB (61%) |
| DRAM Usage | ~120 KB / 327 KB (36%) |
| Free DRAM | ~207 KB |
| PSRAM | ~4 MB (for ROM data, framebuffers, audio) |
The project includes a comprehensive debug system controlled by DEBUG_ENABLED:
// In config.h or debug.h
#define DEBUG_ENABLED 1 // Enable debug output
#define DEBUG_ENABLED 0 // Disable debug output
Debug macros available:
DBG_ERROR(tag, format, ...) - Critical errors (red)DBG_WARN(tag, format, ...) - Warnings (yellow)DBG_INFO(tag, format, ...) - Information (white)DBG_VERBOSE(tag, format, ...) - Detailed debug (gray)Retro_Gamer.ino ← Main: hardware init, launcher UI, game loop ├── src/ │ ├── debug.h ← Debug system (Serial) │ ├── nes_bridge.c/h ← NES emulator bridge │ ├── gb_bridge.c/h ← Game Boy bridge │ ├── sms_bridge.c/h ← SMS/GG/SG-1000/ColecoVision bridge │ ├── pce_bridge.c/h ← PC Engine bridge │ ├── snes_bridge.c/h ← SNES bridge │ ├── lynx_bridge.c/h ← Atari Lynx bridge │ ├── genesis_bridge.c/h ← Mega Drive bridge │ ├── wifi_manager.* ← WiFi + HTTP server │ └── sound_control.c/h ← Audio control
src/<system>_bridge.cbool <system>_bridge_init(int sample_rate)int <system>_bridge_load_rom(const char *path)void <system>_bridge_run_frame(bool draw)void <system>_bridge_set_input(uint32_t buttons)void <system>_bridge_shutdown(void)uint8_t* <system>_bridge_get_framebuffer(int *width, int *height)int16_t* <system>_bridge_get_audio(int *num_samples)emu_type_t in Retro_Gamer.inogetEmuType(), emuName(), and emuShortName()| Problem | Solution |
|---|---|
| Black/no VGA output | Check VGA cable connection. Ensure monitor supports 640×480@60Hz. |
| "PSRAM not found" | Your board must have ESP32-WROVER module (with PSRAM). Regular ESP32 not supported. |
| SD card not detected | Format as FAT32 (not exFAT). Check card is ≤32GB. |
| Keyboard not working | Must be PS/2 protocol (not USB-to-PS/2 adapter). Check CLK=33, DAT=32. |
| No audio | Audio output is on GPIO 25 (internal DAC). Connect amplified speaker. |
| ROM list empty | ROMs must be in /roms/{platform}/ directories. Check file extensions. |
| SNES very slow | Expected — ESP32 at 240MHz struggles with SNES emulation. |
| WiFi won't work | Check wifi.json format. Ensure SD card is properly inserted. |
| Compile error: DRAM overflow | Set DEBUG_ENABLED 0 to reduce memory usage. |
This project is licensed under the GNU General Public License v3.0 - see the COPYING file for details.
Retro-Gamer - Bringing retro gaming to VGA displays, one pixel at a time! 🎮
18 commits
C
93.4%
C++
6.6%
Retro emulators for ESP32 FabGL (TTGO VGA and Olimex)
See the codeMulti-System Retro Emulator for ESP32-FabGL
License: GPL v3 Platform: ESP32 Display: VGA
Retro-Gamer is a multi-system retro emulator firmware for ESP32-based devices with VGA output via FabGL. It brings retro gaming to life on a big screen with crisp 320x240 resolution and 64 colors (RGB222).
This project is a port and enhancement of ducalex's Retro-Go, adapted to run on the FabGL VGA framework. It features a unified launcher for all supported systems, in-game menus, save states, and extensive customization options.
Unlike the original Retro-Go (which was designed for handheld devices with small LCD screens), Retro-Gamer is optimized for VGA displays and PS/2 keyboard input, making it perfect for DIY retro gaming consoles and arcade cabinets.
| System | Core | Extensions | Status |
|---|---|---|---|
| NES | nofrendo | .nes | ✅ Stable |
| Game Boy | gnuboy | .gb | ✅ Stable |
| Game Boy Color | gnuboy | .gbc | ✅ Stable |
| Sega Master System | smsplus | .sms | ✅ Stable |
| Sega Game Gear | smsplus | .gg | ✅ Stable |
| SG-1000 | smsplus | .sg | ✅ Stable |
| ColecoVision | smsplus | .col | ✅ Stable |
| PC Engine / TurboGrafx | pce-go | .pce | ✅ Stable |
| SNES / Super Famicom | snes9x | .sfc .smc | ⚠️ Slow |
| Atari Lynx | handy | .lnx | ✅ Stable |
| Mega Drive / Genesis | gwenesis | .md .gen .bin .smd | ⚠️ Slow |
| Feature | Description |
|---|---|
| 11 Emulators | NES, GB/GBC, SMS, GG, SG-1000, ColecoVision, PCE, SNES, Lynx, Genesis |
| In-Game Menu | Save/Load states (4 slots), turbo, palette, rotate, sound toggle, reset, quit |
| Favorites & Recent | Quick access to your favorite and recently played games |
| Save States | 4 slots per game |
| WiFi File Manager | Browser-based file upload/download |
| VGA Output | 320x240 resolution with 64 colors (RGB222) |
| PS/2 Keyboard | Full keyboard input with WASD support |
| ROM Cache | Fast boot times with cached ROM list |
| Sound Control | Toggle audio ON/OFF |
| Turbo / Fast Forward | 2× speed with continuous audio |
| Function | GPIO Pin |
|---|---|
| VGA Red 0 | GPIO 22 |
| VGA Red 1 | GPIO 21 |
| VGA Green 0 | GPIO 19 |
| VGA Green 1 | GPIO 18 |
| VGA Blue 0 | GPIO 5 |
| VGA Blue 1 | GPIO 4 |
| VGA HSYNC | GPIO 23 |
| VGA VSYNC | GPIO 15 |
| SD CS | GPIO 13 |
| Keyboard Clock | GPIO 33 |
| Keyboard Data | GPIO 32 |
| Audio DAC | GPIO 25 |
Same as above, except SD CS = GPIO 4
Create the following folder structure on your SD card:
SD Card
├── retro-go/
│ ├── config/
│ │ ├── favorites.txt
│ │ ├── recent.txt
│ │ └── wifi.json (optional)
│ └── saves/
│ ├── nes/
│ ├── gb/
│ ├── sms/
│ ├── gg/
│ ├── pce/
│ ├── snes/
│ ├── lnx/
│ ├── md/
│ └── misc/
└── roms/
├── nes/ (NES .nes, .fc)
├── gb/ (Game Boy .gb)
├── gbc/ (Game Boy Color .gbc)
├── sms/ (Master System .sms)
├── gg/ (Game Gear .gg)
├── sg1000/ (SG-1000 .sg)
├── pce/ (PC Engine .pce)
├── snes/ (SNES .sfc, .smc)
├── lnx/ (Lynx .lnx)
├── col/ (ColecoVision .col)
└── md/ (Mega Drive/Genesis .md, .gen, .bin, .smd)
esptool.py write_flash --flash_size detect 0x0 RetroGamer.bin
Or use the esptool web version for a GUI-based flashing experience.
Place your ROM files in the corresponding folders on the SD card (see SD Card Structure above).
| System | Folder | Extensions |
|---|---|---|
| NES | /roms/nes/ | .nes |
| Game Boy | /roms/gb/ | .gb |
| Game Boy Color | /roms/gbc/ | .gbc |
| Master System | /roms/sms/ | .sms |
| Game Gear | /roms/gg/ | .gg |
| SG-1000 | /roms/sg1000/ | .sg |
| PC Engine | /roms/pce/ | .pce |
| SNES | /roms/snes/ | .sfc, .smc |
| Lynx | /roms/lnx/ | .lnx |
| ColecoVision | /roms/col/ | .col |
| Mega Drive / Genesis | /roms/md/ | .md, .gen, .bin, .smd |
Save states are stored in:
/retro-go/saves/<system>/<rom_name>.sav<slot>
Example: /retro-go/saves/nes/Super_Mario_Bros.sav0
| Key | Action |
|---|---|
| ↑ / ↓ / W / S | Navigate ROM list |
| Enter | Play selected ROM |
| F | Toggle favorite |
| Tab | Switch view (All / Favorites / Recent) |
| ESC | Refresh ROM list and update cache |
| Key | Action |
|---|---|
| ↑ / ↓ / ← / → (or WASD) | D-Pad |
| Z / Space | A Button |
| X / Ctrl | B Button |
| Enter | Start |
| Right Shift | Select |
| Tab | Toggle Turbo Mode |
| ESC | Open In-Game Menu |
Press ESC during gameplay to open the in-game menu, which provides:
/retro-go/config/wifi.json on your SD card:{
"ssid0": "your-wifi-ssid",
"password0": "your-wifi-password"
}
Up to 4 networks can be configured (ssid0-ssid3).
http://<IP_ADDRESS>/ to manage files.Press Tab in-game to toggle turbo mode. When enabled:
Retro-Gamer uses a ROM cache to speed up boot times. The cache is stored at /retro-go/rom_cache.txt on your SD card.
When to refresh the cache:
How to refresh the cache:
/retro-go/rom_cache.txt from your SD card and restart the device. The cache will be rebuilt automatically./retro-go/ and delete rom_cache.txt, then restart the device.The cache is automatically updated when:
git clone https://github.com/foky26/Retro-Gamer.git
cd Retro-Gamer
. $HOME/esp/esp-idf/export.sh
idf.py build
idf.py flash
| Metric | Value |
|---|---|
| Flash Usage | ~1.9 MB / 3.14 MB (61%) |
| DRAM Usage | ~120 KB / 327 KB (36%) |
| Free DRAM | ~207 KB |
| PSRAM | ~4 MB (for ROM data, framebuffers, audio) |
The project includes a comprehensive debug system controlled by DEBUG_ENABLED:
// In config.h or debug.h
#define DEBUG_ENABLED 1 // Enable debug output
#define DEBUG_ENABLED 0 // Disable debug output
Debug macros available:
DBG_ERROR(tag, format, ...) - Critical errors (red)DBG_WARN(tag, format, ...) - Warnings (yellow)DBG_INFO(tag, format, ...) - Information (white)DBG_VERBOSE(tag, format, ...) - Detailed debug (gray)Retro_Gamer.ino ← Main: hardware init, launcher UI, game loop ├── src/ │ ├── debug.h ← Debug system (Serial) │ ├── nes_bridge.c/h ← NES emulator bridge │ ├── gb_bridge.c/h ← Game Boy bridge │ ├── sms_bridge.c/h ← SMS/GG/SG-1000/ColecoVision bridge │ ├── pce_bridge.c/h ← PC Engine bridge │ ├── snes_bridge.c/h ← SNES bridge │ ├── lynx_bridge.c/h ← Atari Lynx bridge │ ├── genesis_bridge.c/h ← Mega Drive bridge │ ├── wifi_manager.* ← WiFi + HTTP server │ └── sound_control.c/h ← Audio control
src/<system>_bridge.cbool <system>_bridge_init(int sample_rate)int <system>_bridge_load_rom(const char *path)void <system>_bridge_run_frame(bool draw)void <system>_bridge_set_input(uint32_t buttons)void <system>_bridge_shutdown(void)uint8_t* <system>_bridge_get_framebuffer(int *width, int *height)int16_t* <system>_bridge_get_audio(int *num_samples)emu_type_t in Retro_Gamer.inogetEmuType(), emuName(), and emuShortName()| Problem | Solution |
|---|---|
| Black/no VGA output | Check VGA cable connection. Ensure monitor supports 640×480@60Hz. |
| "PSRAM not found" | Your board must have ESP32-WROVER module (with PSRAM). Regular ESP32 not supported. |
| SD card not detected | Format as FAT32 (not exFAT). Check card is ≤32GB. |
| Keyboard not working | Must be PS/2 protocol (not USB-to-PS/2 adapter). Check CLK=33, DAT=32. |
| No audio | Audio output is on GPIO 25 (internal DAC). Connect amplified speaker. |
| ROM list empty | ROMs must be in /roms/{platform}/ directories. Check file extensions. |
| SNES very slow | Expected — ESP32 at 240MHz struggles with SNES emulation. |
| WiFi won't work | Check wifi.json format. Ensure SD card is properly inserted. |
| Compile error: DRAM overflow | Set DEBUG_ENABLED 0 to reduce memory usage. |
This project is licensed under the GNU General Public License v3.0 - see the COPYING file for details.
Retro-Gamer - Bringing retro gaming to VGA displays, one pixel at a time! 🎮
18 commits
C
93.4%
C++
6.6%