MCPcopy Create free account
hub / github.com/Shim06/Anemoia-ESP32

github.com/Shim06/Anemoia-ESP32 @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
350 symbols 583 edges 47 files 7 documented · 2% updated 2d ago★ 47912 open issues

Browse by type

Functions 303 Types & classes 47
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Anemoia Anemoia-ESP32

Anemoia-ESP32 is a rewrite and port of the Anemoia Nintendo Entertainment System (NES) emulator running directly on the ESP32. It is written in C++ and is designed to bring classic NES games to the ESP32 with support for both TFT displays and composite video output. This project focuses on performance, being able to run the emulator at native speeds and with full audio emulation and save states implemented.

Flash the emulator instantly using the Web Flash!

Anemoia-ESP32 is available on GitHub under the GNU General Public License v3.0 (GPLv3).


Sponsor

NextPCB

This project is proudly sponsored by NextPCB. Their support helps fund the development and continuation of this project, and I'm very grateful to have them as my first ever sponsor.

Want to make a PCB? NextPCB offers PCB fabrication and assembly services with fast turnaround times and affordable pricing to help bring your electronics projects to the next level.


Table of Contents


Performance

Anemoia-ESP32 is heavily optimized to achieve native NES speeds on the ESP32, running at ~60.098 FPS (NTSC) with 1 frame skip and full audio emulation enabled.

Here are the performance benchmarks for several popular NES games.

[!NOTE] The following benchmarks show average framerates recorded over 8192 frames (~2 minutes) of emulation time. Some games, such as Kirby's Adventure, which frequently switch banks may experience significant FPS drops in certain sections.

Game Mapper Average FPS
Super Mario Bros. NROM (0) 60.10 FPS
Contra UxROM (2) 60.10 FPS
The Legend of Zelda MMC1 (1) 60.10 FPS
Mega Man 2 MMC1 (1) 60.10 FPS
Castlevania UxROM (2) 60.10 FPS
Metroid MMC1 (1) 60.10 FPS
Kirby's Adventure MMC3 (4) 59.57 FPS
Donkey Kong NROM (0) 60.10 FPS

Compatibility

As of now, Anemoia-ESP32 has implemented six major memory mappers: * Mapper 0 * Mapper 1 * Mapper 2 * Mapper 3 * Mapper 4 * Mapper 69

Totalling to around 79% of the entire NES game catalogue.

If you'd like to check if a certain game is supported, visit NesCartDB and search for the game on the right-hand side of the site. Select the specific game version and look for the iNES Mapper number in the cart properties. The game should be supported if the iNES Mapper number is in the list of implemented mappers above.

Feel free to open an issue if a game has glitches or fails to boot.


Hardware Overview

Anemoia-ESP32 requires a dual-core ESP32 with a minimum of 1 MB flash memory and NO PSRAM IS REQUIRED.

Composite Video Output

Anemoia-ESP32 supports composite video output via the COMPOSITE_VIDEO define in config.h, based on esp_8_bit by Peter Barrett. This lets the emulator output directly to a CRT television or any display with a composite input.

Additional hardware needed: - Any CRT or display with a composite RCA input - 1kΩ resistor and 10nF capacitor

Wiring:

-----------
|         |
|      25 |-------------------------------► Video out (RCA)
|         |
|      18 |----[1kΩ]----+---------------► Audio out
|  ESP32  |             |
|         |            ---
|         |            --- 10nF
|         |             |
|         |             ▼ GND
-----------
Signal ESP32 Pin
Video out GPIO25
Audio out GPIO18

[!NOTE] GPIO18 is the default audio pin and can be changed via AUDIO_PIN in config.h.

To enable composite video, open config.h and uncomment:

#define COMPOSITE_VIDEO

Then set your video standard and audio pin as needed:

#define VIDEO_STANDARD 1  // 0 = PAL, 1 = NTSC
#define AUDIO_PIN      18

[!IMPORTANT] Composite video and TFT output are mutually exclusive. Enabling COMPOSITE_VIDEO disables the SPI display pipeline entirely.

Original Hardware

  • ESP32
  • e.g. ESP32-DevKitC or ESP32-WROOM-32
  • A 240x320 SPI TFT screen (no touch needed)
  • Either an ST7789-based screen as depicted, or
  • an ILI9341-based screen with 240x320 pixels
  • Audio Amplifier
  • e.g. a PAM8403 or PAM8302
  • Speaker
  • MicroSD card module
  • 8 Tactile push buttons, or
  • Supported Controller
  • NES controller
  • SNES controller
  • PS1 controller
  • PS2 controller
  • Serial controller (WebSerial or UART adapter)

[!NOTE] ST7789-based displays are recommended as they seem to fare better with 80MHz SPI speeds and are the most compatible.

[!IMPORTANT] ILI9341 users: ILI9341-based screens may experience display problems at 80MHz. Reduce the SPI frequency to 40MHz in your User_Setup.h. This will cause the emulator to run a few FPS slower than ST7789 screens.

Default Pin Setup

Default pin schematic

TFT Display

Signal ESP32 Pins
MOSI GPIO23
MISO -1 (N/A)
SCLK GPIO18
CS GPIO5
DC GPIO2
RST EN

MicroSD

Signal ESP32 Pins
MOSI GPIO13
MISO GPIO12
SCLK GPIO14
CS GND

[!IMPORTANT] 3V3-microsd-module-img

If using this 3.3V microSD card module, the pull-up resistor on MISO (GPIO12) must be removed. GPIO12 is a bootstrapping pin (MTDI) that must be LOW during boot. The external pull-up on the microSD module conflicts with the boot strapping process, preventing the ESP32 from booting correctly.

Audio Amplifier

Signal ESP32 Pins
Input GPIO25

Controller

There are currently four input methods: Tactile push buttons, an NES/SNES controller, a PS1/PS2 controller, and a Serial controller.

Tactile Push Buttons

Signal ESP32 Pins
A GPIO19 & GND
B GPIO26 & GND
Left GPIO32 & GND
Right GPIO33 & GND
Up GPIO15 & GND
Down GPIO4 & GND
Start GPIO27 & GND
Select GPIO16 (RX2) & GND

NES/SNES controller

NES/SNES controller Pinout

Signal ESP32 Pins
Clock GPIO32
Latch GPIO33
Data GPIO35

PS1/PS2 controller

PS1/PS2 controller Pinout

Signal ESP32 Pins
Data GPIO32
Command GPIO33
Attention GPIO26
Clock GPIO27

Also connect the power and ground lines if using a controller. Most controllers should work fine from 3.3V power supply.

Serial Controller

Button presses can be sent over serial via two independent methods, provided by the SerialGameControllerAdapter project. Both can coexist and are handled separately.

Method 1 — USB to Serial (WebSerial)

Button input is read over the main USB serial connection. Open WebSerialController.html in a Chromium-based browser — it translates keyboard, mouse, touch, or USB controller input into serial button commands. No extra hardware is required, making it ideal for testing Anemoia-ESP32 before any wiring or soldering.

Method 2 — UART Adapter (ESP32-to-ESP32)

A second ESP32 running SerialGameControllerAdapter firmware. The adapter reads inputs from an NES, SNES, PS1, PS2, or Bluetooth controller and forwards button presses over a secondary serial port (Serial1). A separate UART port is used specifically to avoid interfering with USB programming of the main board.

Signal CYD Pin
TX (Adapter) → RX (ESP32) GPIO22
RX (Adapter) ← TX (ESP32) GPIO27

Cheap Yellow Display

Cheap Yellow Displays (CYD) are an all-in-one ESP32 board that comes with most of the hardware needed in this project already integrated, making it ideal for Anemoia-ESP32. Because of the limited pins brought out by the CYD, it is only practical to use a NES controller or a serial controller.

Hardware Needed: - Cheap Yellow Display - NES/SNES controller (or serial controller — see Serial Controller) - Speaker (optional) - Can be attached with a 1.25mm JST connector to "SPEAK" or soldered directly

NES/SNES controller

Signal ESP32 Pins
Clock GPIO22 (CN1/P3)
Latch GPIO27 (CN1)
Data GPIO35 (P3)

Custom-made PCBs

The schematics, PCB design files, enclosures, and 3D models are available in the /hardware and /3d-model folder.

Module-based PCB

A PCB that provides a clean, organized way to connect and manage all peripheral modules in one place. Module-based PCB demo Module-based PCB schematic

Discrete PCB

A PCB that offers a more complete, permanent, and compact handheld by using discrete ICs instead of breakout modules. Discrete PCB demo Discrete PCB schematic


Where to Buy

These are the recommended parts to use for this project.

These are affiliate links. Buying through them helps support me at no extra cost to you. Thank you for your support.

Cheap Yellow Display


Controls

Menu Access

Press Start + Select simultaneously in a game to open the menu. Press Select to change the ROM backend. See ROM Storage Backends for details.

Controller Button Mappings

SNES Controller

NES Button SNES Buttons
A B, A, R
B Y, X, L
Start Start
Select Select
Up D-Pad Up
Down D-Pad Down
Left D-Pad Left
Right D-Pad Right

PS1/PS2 Controller

NES Button PS1/PS2 Buttons
A R1, R2, R3, X, O
B L1, L2, L3, Square, Triangle
Start Start
Select Select
Up D-Pad Up
Down D-Pad Down
Left D-Pad Left
Right D-Pad Right

ROM Backends

ROMs are always sourced from the SD card.

Core symbols most depended-on inside this repo

Shape

Method 186
Function 117
Class 38
Enum 9

Languages

C++100%

Modules by API surface

src/core/cpu6502.cpp83 symbols
src/composite_video.h32 symbols
src/core/ppu2C02.cpp23 symbols
src/core/cartridge.cpp23 symbols
src/ui.cpp18 symbols
src/core/apu2A03.cpp18 symbols
src/core/bus.cpp17 symbols
src/core/apu2A03.h16 symbols
src/core/mappers/mapper001.cpp14 symbols
src/core/mappers/mapper069.cpp13 symbols
src/core/mappers/mapper004.cpp13 symbols
src/controller.cpp11 symbols

For agents

$ claude mcp add Anemoia-ESP32 \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page