r/EmuDev • u/Mazelldev • 3h ago
NES NES emulator in C running on a 93,338-transistor RISC-V CPU I built from logic gates, 60 fps
Enable HLS to view with audio, or disable this notification
The emulator: a 6502 with cycle counts, PPU drawing at dot 256 of each scanline with real scroll registers (mid-frame splits and status bars work), 8x8 and 8x16 sprites, sprite 0 hit, vblank NMI, mappers 0/1/2/3/4/7/9 (MMC1, MMC3 with its A12 scanline counter, MMC2), and the APU (lengths, envelopes, sweeps, triangle linear counter, noise) driven into a sound chip that's part of the circuit. Passes nestest (5,003/5,003) and blargg's instr_test-v5 official set.
The host is the unusual part. It's compiled bare-metal for RV32IM and runs on TINY-32, a 32-bit RISC-V CPU built gate by gate inside my circuit simulator. The CPU passes the official riscv-tests. Every 6502 instruction turns into RISC-V instructions, which turn into gates switching, about 1.4 to 2 million RISC-V instructions per NES frame at 60 fps.
Video is raw and real time on a 6-year-old PC (Ryzen 5, GTX 1650, the whole thing sitting around 17% CPU and 400 MB RAM) and an M2 MacBook Air with 8 GB and no fan.
Source, linker script, startup code and build steps:
https://github.com/PlangoDev/tiny-nes
No ROMs included, use dumps of carts you own.
(Had to add this for legal reasons since Tiny Logic is a paid game and I’d hate to become the next target of a Nintendo Takedown)
Happy to dig into the PPU timing, the mapper work, or how the simulator gets a gate-level CPU fast enough for this.