GitHub - Arthi-chaud/FuNes: A experimental NES emulator written in Haskell

3 min read Original article ↗

image FuNes

FuNes is a Nintendo Entertainment System (NES) emulator, written in Haskell.

Warning

This emulator is for research purposes. Do not use as your daily emulator. You can easily find more mature NES emulators on GitHub!

⭐ Characteristics

  • NTSC
  • Audio (although not perfect)
  • Mappers
    • NROM

🔧 Installation

To build the emulator, you will need to have Stack and the SDL2 library installed.

# In the cloned repository
stack build
stack run -- ./my_rom.nes # The path to the rom to use

Note: stack install will install the emulator as funes-exe

🎮 Controls

NES Controller Physical Buttons
A A
B S or Z
Start Enter
Select Space
Directional Pad Arrows

Press Q or esc to quit.

✅ Testing and accuracy

We use the nestest ROM and trace to test the CPU's behaviour and instructions.

While accuracy is not the ultimate goal, we use the AccuracyCoin ROM to evaluate the correctness of the emulator.

Latest results

Do not be scared of the failing tests. Please check out this video to understand what this ROM checks for.

Score: 83 / 131

Screenshot 2025-11-21 at 16 27 00

Results from Nov. 21 2025

🎥 Demo (w/ sound) 🔉

Click to expand

⚠️ Turn down your headphones before playing!

out.mp4

🔍 Why another NES emulator?

FuNes is an experiment before anything else. The goal was to see if the functional paradigm would apply well to writting virtual machines and emulator, thus being written in Haskell.

While the goal is to have a working emulator, it is in no way 100% compliant. Some features are not (yet) implemented (see here) and some behaviour may be invalid.

Results of this little experiment

  • The different parts of the emulator (CPU, PPU, Bus) are isolated objects and computations on them were designed using Monads. This made testing a real pleasure. Moreover, I find the code overal quite elegant (e.g. for the opcodes).
  • The typeafety prevented some bit-level mistakes (especially when handling 2-byte addresses and 1-byte data), which is always welcome.
  • However, it feels like the functional paradigm didn't bring much else to the table, compared to a regular object-orented approach. Although, it should be noted that the functional paradigm never felt like an obstacle when designing and implementing the emulator.

⚙️ Technicalities

  • Main stateful computations (operations on the CPU, APU, PPU, etc.) are modeled using continuation-passing style (CPS) monads
  • Multi-threading for rendering and sound filtering
  • Using SDL2

📚 Resources used

This project wouldn't exist without the following resources. Many thanks to their respective authors 🙏

Why FuNes?

It's simple: Functional Programming + NES = FuNes

The fact that it shares the name with the late french actor Louis de Funes is accidental.