
The ESP32-S3 is by many metrics quite the powerful little computer, which has led to it being used even for things like emulating retro consoles and similar. Here [Ivan Svarkovsky]’s S3-MSX-PC project pushes the envelope by taking the multi-system Retro-Go project’s MSX component and optimizing it for the ESP32-S3’s Xtensa Lx7 CPU cores.
The project involves an ESP32-S3 as the core, requiring at least 8 MB of PSRAM (N16R8 configuration) to match the tested configuration. Any software is loaded into PSRAM before it’s executed, with the MSX1, MSX2 and MSX2+ supported.
For audio you have to wire up your own PDM filters to connect to the two GPIO pins that are used for audio output, while VGA output is handled by a basic 2-bit R-2R RGB222 DAC. For input devices you can use any USB keyboard, while software is added via the web interface or directly onto an SD card.
The Technical Deep Dive section goes into more detail as to what exactly got changed – with the blessing of the fMSX author – in the original fMSX core, such as targeting the Lx7 core’s cache dimensions and optimizing hot paths to avoid bottlenecks. Memory accesses were aligned for Xtensa and moving certain data from Flash to RAM was another change, along with the prevention of pipeline flushing due to certain branching decisions.
Considering that MSX specifications are based on a Z80 core, it’s not so crazy that one of these ESP32-S3 MCUs can effectively emulate them. The Retro-Go project itself claims to cover a whole swath of Nintendo and Sega consoles, as well as others, making it almost too easy to do some retrogaming without even having to drag out a Raspberry Pi SBC or so.

Cool! I remember fMSX from the good old Windows 3.1 days!
I think it’s really nice that MSX2 is supported on such limited hardware, too!
Too many users merely got in touch with the humble MSX1 standard, I’m afraid.
The Yamaha V9938 VDP really makes a difference!
Hi everyone, I’m the creator of this project. Thanks to the Hackaday team for the feature!
Just to add a bit of context for the hardware/C optimization nerds out there: getting an emulator to “run” on an ESP32-S3 is easy. Getting it to run at a flawless 60 FPS with studio-accurate audio (PSG+SCC+OPLL) is a nightmare because the Xtensa LX7 architecture suffers heavily from pipeline stalls and PSRAM latency.
To make this work, I had to deeply rewrite the legendary fMSX core:
1. Replaced the massive Z80 switch/case dispatcher with Computed Gotos (Threaded Code), pinning the PC and ICount to physical 32-bit registers to stop pipeline flushes.
2. Built a custom “Delta-Stride LZ” streaming compressor that understands the MSX VRAM geometry (128/256-byte strides) to save 4.4MB states to the SD card using exactly 0 bytes of heap RAM.
3. Hijacked the ESP32’s LCD_CAM peripheral with the
lcd_byte_order=1flag to DMA-blast VGA pixels with hardware byte-swapping (zero CPU cost), completely bypassing RGB math by pre-shifting MSX palettes to match the R-2R ladder pins.If anyone wants to dive into the disassembly, cache metrics, and the real hardware hacking behind this, I wrote a massive “Technical Deep Dive” at the bottom of the GitHub README. I’d love to hear your thoughts on the code!
With an rgb222 you’d lose some colour definition from MSX2 upward. MSX2 is RGB332. And probably no FM-PAC and SCC emulation.
Hi! A couple of technical corrections here:
First, the MSX2 (V9938) palette is actually RGB333 (512 colors), not RGB332. You are correct that an RGB222 resistor ladder (64 colors) reduces the color depth. However, this was a deliberate design choice to achieve ultimate hardware minimalism. You only need 6 basic resistors to get a vibrant, perfectly playable picture on a VGA monitor without requiring external DAC chips.
Second, regarding the audio: the exact opposite is true. The emulator runs full cycle-accurate Mitsutaka Okazaki studio engines for PSG, OPLL (FM-PAC), and SCC simultaneously at a flawless 60 FPS.
To prevent these heavy audio engines from choking the ESP32-S3, I stripped out all floating-point math, replaced it with 1-cycle integer bit-shifts, and relocated over 11KB of audio lookup tables from slow PSRAM directly into zero-wait-state Internal DRAM. It even features an integer-based One-Pole Low-Pass filter for the SCC and hardware-accurate stereo panning.
If you’re curious about how it actually works under the hood, feel free to check out the “Technical Deep Dive” section in the GitHub README!
I stand corrected! Good job! I was thinking of the screen 8 256 colours, but you’re right the palette mode is 512 colours.
For me it was a great machine to learn the inner workings of a computer. I created an expansion card with 62256 memory chips and a Ni‑Cd battery that captured cassette games into this memory card using interrupts. It also copied ROM cartridges. I think I actually programmed more than I played with that machine, a Sony MSX.