dendy

module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 26, 2024 License: MIT

README

Kivi Logo

NES/Famicom emulator with network multiplayer written in Go


Dendy is a NES/Famicom emulator written in Go and named after the soviet Famicom clone, that I used to have back in my childhood. It’s nothing serious, so do not expect it to beat any of the existing emulators in terms of performance or accuracy. Yet, it is capable of running most of the games I tried, so it’s not completely useless.

Screenshots

Download

You can download the latest pre-built binaries for Windows, macOS, and Linux from the releases page: (not tested).

Alternatively, if you have Go installed, you can build it from source:

$ go install github.com/maxpoletaev/dendy/cmd/dendy@latest

For this, you may need to install additional dependencies required by raylib. See https://github.com/gen2brain/raylib-go#requirements for more details.

Play

There is no GUI, so you will have to run the emulator from the command line. Just point it to the ROM file you want to play (only .nes, .zip won’t work for now):

$ dendy romfile.nes

There’s a bunch of command line flags that you can know about by running dendy -help. Here are some of the most useful ones:

  • -scale=<n> - Scale the window by n times (default: 2)
  • -nospritelimit - Disable original sprite per scanline limit (eliminates flickering)
  • -listen and -connect - For network multiplayer (see below)
  • -nosave - Do not load and save the game state on exit

Controls

Controller

Player 1 controller is emulated using the keyboard. The default mapping is as follows. Multiplayer on a single keyboard is not supported.

                   ┆┆
┌───────────────────────────────────────┐
│                                       │
│    [W]                                │
│ [A]   [D]                             │
│    [S]                       [J] [K]  │
│           [Enter] [RShift]            │
│                                       │
└───────────────────────────────────────┘

Zapper (Light Gun)

Zapper is emulated using the mouse and can be used in games like Duck Hunt. Point the mouse cursor at the right position on the screen and click to shoot.

Hotkeys

  • CTRL+R or ⌘+R - Reset the game
  • CTRL+Q or ⌘+Q - Quit the emulator
  • CTRL+X or ⌘+X - Resync the emulators (netplay)
  • F12 - Take a screenshot
  • M - Mute/unmute

Network Multiplayer

Run the emulator with the -listen=<host>:<port> flag to start a netplay server that will be waiting for the second player to connect via the -connect=<host>:<port> flag. Once the connection is established, the game will start for both sides. The player who started the server will be controlling the first joystick. Ensure that both sides are using the same ROM file and the same version of the emulator.

The multiplayer feature is based on rollback networking, similar to how it is done in RetroArch and Fightcade. The emulation always runs at the full speed on both sides, and the player inputs for each frame are exchanged over the network.

It compensates for slight drifts in the clock speed and network latency by predicting input events for the other player when the real input has not yet been received. When the input from the remote player arrives, it corrects itself by "rolling back" to the last known synchronized state and replaying the inputs from that point. Theoretically, this should keep the game playable for both sides without any local input delay, even if the network connection is not very stable (e.g., over the Internet). When tested, latencies of up to 150ms felt pretty playable.

Tested Games

Game Status Issues
Bad Apple Playable
Balloon Fight Playable
Batman Playable
Battle City Playable
Battletoads Playable
Battletoads & Double Dragon Not Playable Freezes
Bomberman Playable
Captain America Playable
Castlevania Playable
Chip 'n Dale Playable
Chip 'n Dale 2 Playable
Contra Force Playable
Contra Playable
Darkwing Duck Playable
Donkey Kong Playable
Double Dragon 2 Playable
Double Dragon 3 Playable
Duck Hunt Playable
Duck Tales Playable
Ice Climber Playable
Jackal Not Playable Black screen
Kirby's Adventure Playable
Legend of Zelda Playable
Mario Bros. Playable
Megaman Playable
Megaman 4 Playable
Metal Gear Playable
Mighty Final Fight Playable
Ninja Cat Playable
Prince of Persia Playable Incorrect sprite/background priority
Super Contra Playable
Super Mario Bros. 3 Crash
Super Mario Bros. Playable
Teenage Mutant Ninja Turtles Playable
Teenage Mutant Ninja Turtles 2 Playable
Teenage Mutant Ninja Turtles 3 Playable
Teenage Mutant Ninja Turtles: Tournament Fighters Not Playable Graphical artifacts
Tiny Toon Adventures Playable

Status

CPU

  • Official opcodes
  • Unofficial opcodes
  • Runtime disassembly
  • Cycle-accurate emulation
  • Accurate clock speed
  • Interrupts

Graphics

  • Background rendering
  • Sprite rendering
  • 8×16 sprites
  • Palettes
  • Scrolling
  • Color emphasis

Input/Output

  • Graphics output
  • Controllers
  • Zapper

Sound

The sound chip emulation is still work in progress and is not very reliable yet. It may occasionally produce some pops and crackles, but it should be good enough for most games.

  • Square channels
  • Triangle channel
  • Noise channel
  • Length counter
  • Envelope
  • Sweep
  • DMC

Mappers

The goal is to support top 7 mappers covering the majority of games. The percentage indicates the number of games that use the mapper according to nescartdb.com.

  • MMC1 (Mapper 1) - 28%
  • MMC3 (Mapper 4) - 24%
  • UxROM (Mapper 2) - 11%
  • NROM (Mapper 0) - 10%
  • CNROM (Mapper 3) - 6%
  • AxROM (Mapper 7) - 3%
  • MMC5 (Mapper 5) - 1%

Resources

Although NES emulation is a pretty well-covered topic, It is still a very interesting and challenging project to work on. Here are some of the resources that I found particularly useful while writing this emulator. Big thanks to everyone who made them!

Documentation

Videos

  • The NES Emulator from Scratch series covers most of the topics from the CPU to the sound, but I found the two videos about the PPU to be the most useful for understanding the obscure details of the NES rendering pipeline: [1], [2].

Code

During bad times, it’s always nice to look at other people’s code to see how they solved the same problems. Here are some of the emulators written by other people that I often referred to when I was stuck:

Directories

Path Synopsis
cmd
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL