{"id":13644048,"url":"https://github.com/maxpoletaev/dendy","last_synced_at":"2025-05-16T09:06:18.597Z","repository":{"id":161231641,"uuid":"628649642","full_name":"maxpoletaev/dendy","owner":"maxpoletaev","description":"NES/Famicom emulator with P2P network multiplayer and WASM support","archived":false,"fork":false,"pushed_at":"2025-02-26T01:44:23.000Z","size":930,"stargazers_count":402,"open_issues_count":2,"forks_count":21,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-20T09:04:47.251Z","etag":null,"topics":["6502","8bit","emulator","go","golang","hole-punching","nes","nes-emulator","netplay","nintendo","rollback-netcode","wasm"],"latest_commit_sha":null,"homepage":"https://maxpoletaev.github.io/dendy/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maxpoletaev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-04-16T15:54:57.000Z","updated_at":"2025-03-24T18:25:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"9cb739b8-cf8a-4647-bcaa-889fc27fdd8d","html_url":"https://github.com/maxpoletaev/dendy","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxpoletaev%2Fdendy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxpoletaev%2Fdendy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxpoletaev%2Fdendy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxpoletaev%2Fdendy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxpoletaev","download_url":"https://codeload.github.com/maxpoletaev/dendy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254501558,"owners_count":22081528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["6502","8bit","emulator","go","golang","hole-punching","nes","nes-emulator","netplay","nintendo","rollback-netcode","wasm"],"created_at":"2024-08-02T01:01:56.862Z","updated_at":"2025-05-16T09:06:13.590Z","avatar_url":"https://github.com/maxpoletaev.png","language":"Go","readme":"\u003cdiv align=\"center\"\u003e\n   \u003cimg src=\"logo.png\" width=\"300\" alt=\"Kivi Logo\"\u003e\n   \u003cp\u003eNES/Famicom emulator with network multiplayer written in Go\u003c/p\u003e\n   \u003cimg src=\"https://img.shields.io/badge/status-Stable-green?style=flat-square\" alt=\"\"\u003e\n   \u003cimg src=\"https://img.shields.io/badge/license-MIT-blue?style=flat-square\" alt=\"\"\u003e\n\u003c/div\u003e\n\n\u003chr\u003e\n\nDendy is a NES/Famicom emulator written in Go and named after the post-soviet Famicom\nclone, that I used to have back in my childhood. It’s nothing serious, so do not \nexpect it to beat any of the existing emulators in terms of accuracy and compatibility. \nYet, it is capable of running most of the games I tried, and it comes with a nice \nnetwork multiplayer feature, so it’s not completely useless.\n\n\u003cimg src=\"screenshots.png\" alt=\"Screenshots\"\u003e\n\n## WebAssembly\n\nThe WASM-compiled version for modern browsers is available at \nhttps://maxpoletaev.github.io/dendy/. It runs surprisingly smooth, though it does \nnot support netplay in its current form (there was an [experimental][wasm-netplay] \nimplementation of it over WebRTC, but it was too slow and unreliable to be \nusable).\n\n[wasm-netplay]: https://drive.google.com/file/d/1r3ZY20L168u3djRMWA_KLMrY0eIr1ify/view?usp=sharing\n\n## Download\n\nYou can download the latest pre-built binaries for Windows, macOS, and Linux\nfrom the releases page: https://github.com/maxpoletaev/dendy/releases (not\nguaranteed to work as I don’t have a Windows machine to check it).\n\nAlternatively, if you have Go installed, you either install it using:\n\n```sh\ngo install \"github.com/maxpoletaev/dendy/cmd/dendy@latest\"\n```\n\nOr clone the repo and build it from source (preferable):\n\n```sh\ngit clone https://github.com/maxpoletaev/dendy.git\ncd dendy\nmake build\n```\n\nFor this to work, you may need to install a C compiler (gcc or clang) and additional\ndependencies required by raylib. See https://github.com/gen2brain/raylib-go#requirements\nfor more details.\n\n## Play\n\nThere is no GUI, so you will have to run the emulator from the command line.\nJust point it to a`.nes` ROM file you want to play:\n\n```sh\ndendy romfile.nes\n```\n\nThere’s a bunch of command line flags that you can learn about by running\n`dendy -help`. Here are some of the most useful ones:\n\n * `-scale=\u003cn\u003e` - Scale the window by `n` times (default: 2)\n * `-nospritelimit` - Disable original sprite per scanline limit (eliminates flickering)\n * `-listen` and `-connect` - For network multiplayer (see below)\n * `-nosave` - Do not load and save the game state on exit\n * `-nocrt` - Disables the CRT effect, in case you don’t like it\n * `-gg` - Apply Game Genie codes (comma-separated)\n\n## Controls\n\n### Controller\n\nPlayer 1 controller is emulated using the keyboard. The default mapping is as\nfollows. Multiplayer on a single keyboard is not supported.\n\n```\n                   ┆┆\n┌───────────────────────────────────────┐\n│                                       │\n│    [W]                                │\n│ [A]   [D]                             │\n│    [S]                       [J] [K]  │\n│           [Enter] [RShift]            │\n│                                       │\n└───────────────────────────────────────┘\n```\n\n### Zapper (Light Gun)\n\nZapper is emulated using the mouse and can be used in games like Duck Hunt. Just \npoint the mouse cursor at the right position on the screen and click to shoot.\n\n### Hotkeys\n\n * `CTRL+R` or `⌘+R` - Reset the game\n * `CTRL+Q` or `⌘+Q` - Quit the emulator\n * `CTRL+X` or `⌘+X` - Resync the emulators (netplay)\n * `CTRL+Z` or `⌘+Z` - Undo/Rewind 5 seconds back in time\n * `F12` - Take a screenshot\n * `M` - Mute/unmute\n\n## Game Genie Codes\n\nGame Genie was a cartridge pass-through device that allowed players to modify\nthe game program ROM data with special codes, creating new effects and cheats.\nThe code was basically a memory address:value pair that was patched in the\ngame's memory when that value was read from the cartridge.\n\nYou can use various Game Genie codes available on the internet with the emulator \nby passing them as a comma-separated list to the `-gg` flag.\n\n## Network Multiplayer\n\nTo utilize the multiplayer feature, you need to start the emulator with the \n`-listen=\u003chost\u003e:\u003cport\u003e` argument on the host machine and the `-connect=\u003chost\u003e:\u003cport\u003e` \nargument on the client machine. Once the connection is established, the game \nwill start for both sides. The host machine will be the first player. The players \nmust ensure they are running the same ROM file and the same version of the emulator.\n\n```bash\ndendy -listen=0.0.0.0:1234 roms/game.nes       # Player 1\ndendy -connect=192.168.1.4:1234 roms/game.nes  # Player 2\n```\n\n### When players are behind NATs\n\nThere is also a way to connect two players behind NATs without having to set up\nport forwarding, with a little help from an external relay server. You can use\nthe `-createroom` flag to create a room on the public server, and the\n`-joinroom=\u003cid\u003e` to join it.\n\nTwo clients will exchange their public IP addresses and port numbers through the\nrelay server and establish a peer-to-peer UDP connection using a technique called\n\"hole punching\". The relay server will not be involved in the actual gameplay,\nso it should not affect the latency. This method won’t work if both players are\nbehind symmetric NATs (luckily, most home residential NATs are not symmetric).\n\n```bash\ndendy -createroom roms/game.nes            # Player 1 - get a room ID\ndendy -joinroom=XXX-XXX-XXX roms/game.nes  # Player 2 - use the room ID\n```\n\nI currently host a public relay server, which IP is hardcoded within the emulator.\nIn case it goes down at some point, you can run your own using the `dendy-relay`\nbinary (available when building from source), and then set the `-relay` flag in\nthe emulator to use it.\n\n### Behind the scenes\n\nThe multiplayer part works by using something called rollback networking. This \nis a fancy way of making sure that when you play a game with someone else over the \ninternet, it feels smooth and quick, just like playing side by side.\n\nHere’s how it works: the game runs full speed for both players, and every move \nyou make is sent over the internet to the other player. The cool part is, the \nlocal player should not notice any delay when they press buttons because the game \nguesses what the other player is going to do before their moves actually get to you.\nIf the guess is wrong, the game quickly fixes it by going back a tiny bit to when \nboth players agreed on what was happening, then moves forward again using the \ncorrect moves.\n\nIn addition to predicting and correcting player actions, it has a mechanism to \nensure frame rate synchronization between players, especially when there are \ndrifts in clock speed causing one player’s game running slower than the other’s. \nThe emulator can detect that one of the players is falling behind too much and\nadjust the frame rate accordingly or even pause the game for one player for a \nfew frames to let the other player catch up.\n\nWithin a reasonable latency, all of this should happen in a fraction of a second,\nwithout the players noticing anything weird. When tested, ping of up to 150ms \nfelt pretty playable.\n\n## Tested Games\n\n| Game | Status | Issues |\n|------|--------|--------|\n| [Bad Apple][badapple] | Playable ||\n| Balloon Fight | Playable ||\n| Batman| Playable ||\n| Battle City | Playable ||\n| Battletoads | Playable ||\n| Battletoads \u0026 Double Dragon | Not Playable | Freezes |\n| Bomberman | Playable ||\n| Bomberman 2 | Playable ||\n| Captain America | Playable ||\n| Castlevania | Playable ||\n| Chip 'n Dale | Playable ||\n| Chip 'n Dale 2 | Playable ||\n| Contra Force | Playable ||\n| Contra | Playable ||\n| Darkwing Duck | Playable ||\n| Dr. Mario | Playable ||\n| Donkey Kong | Playable ||\n| Double Dragon 2 | Playable ||\n| Double Dragon 3 | Playable ||\n| Duck Hunt | Playable ||\n| Duck Tales | Playable ||\n| Ice Climber | Playable ||\n| Jackal | Not Playable | Black screen |\n| Kirby's Adventure | Playable ||\n| Legend of Zelda | Playable ||\n| Mario Bros. | Playable ||\n| Megaman | Playable ||\n| Megaman 4 | Playable ||\n| Metal Gear | Playable ||\n| Mighty Final Fight | Playable ||\n| Ninja Cat | Playable ||\n| Prince of Persia | Playable | Incorrect sprite/background priority |\n| Super Contra | Playable ||\n| Super Mario Bros. 3 | Crash ||\n| Super Mario Bros. | Playable ||\n| Teenage Mutant Ninja Turtles | Playable ||\n| Teenage Mutant Ninja Turtles 2 | Playable ||\n| Teenage Mutant Ninja Turtles 3 | Playable ||\n| Teenage Mutant Ninja Turtles: Tournament Fighters | Not Playable | Graphical artifacts |\n| Tiny Toon Adventures | Playable ||\n\n[badapple]: https://www.nesdev.org/wiki/Bad_Apple\n\n## Status\n\n### CPU\n\n* [x] Official opcodes\n* [x] Unofficial opcodes\n* [x] Runtime disassembly\n* [x] Cycle-accurate emulation\n* [x] Accurate clock speed\n* [x] Interrupts\n\n### Graphics\n\n* [x] Background rendering\n* [x] Sprite rendering\n* [x] 8×16 sprites\n* [x] Palettes\n* [x] Scrolling\n\n### Input/Output\n\n* [x] Graphics output\n* [x] Controllers\n* [x] Zapper\n\n### Sound\n\nThe sound chip emulation is still work in progress and is not very reliable yet.\nIt may occasionally produce some pops and crackles, but it should be good enough\nfor most games.\n\n* [x] Square channels\n* [x] Triangle channel\n* [x] Noise channel\n* [x] Length counter\n* [x] Envelope\n* [x] Sweep\n* [x] DMC\n\n### Mappers\n\nThe goal is to support top 7 mappers covering the majority of games. The\npercentage indicates the number of games that use the mapper according to\nnescartdb.com.\n\n* [x] MMC1 (Mapper 1) - 28%\n* [x] MMC3 (Mapper 4) - 24%\n* [x] UxROM (Mapper 2) - 11%\n* [x] NROM (Mapper 0) - 10%\n* [x] CNROM (Mapper 3) - 6%\n* [x] AxROM (Mapper 7) - 3%\n* [ ] MMC5 (Mapper 5) - 1%\n\n## Dependencies\n\n * https://github.com/gen2brain/raylib-go/raylib - Go bindings for Raylib (graphics/audio)\n * https://github.com/xtaci/kcp-go - TCP-over-UDP for netplay\n\n## Resources\n\n* [NESDev Wiki](https://www.nesdev.org/wiki/Nesdev_Wiki)\n* [MOS 6502 CPU Reference](https://web.archive.org/web/20210429110213/http://obelisk.me.uk/6502/) by Andrew Jabobs\n* [Extra Instructions of the 65xx Series CPU](http://www.ffd2.com/fridge/docs/6502-NMOS.extra.opcodes) by Adam Vardy\n* [NES Rendering Overview](https://austinmorlan.com/posts/nes_rendering_overview/) by Austin Morlan\n* [Making NES Games in Assembly](https://famicom.party/book/) by Kevin Zurawel\n* [NES Emulator from Scratch](https://www.youtube.com/playlist?list=PLrOv9FMX8xJHqMvSGB_9G9nZZ_4IgteYf) series by javidx9\n* [Audio pseudo-code](https://forums.nesdev.org/viewtopic.php?t=13767) by oRBIT2002\n* [Retroarch Netplay README](https://github.com/libretro/RetroArch/blob/master/network/netplay/README)\n* [GameGenie Technical Notes](https://tuxnes.sourceforge.net/gamegenie.html)\n\n## Referenced Projects\n\n* [github.com/OneLoneCoder/olcNES](https://github.com/OneLoneCoder/olcNES)\n* [github.com/ad-sho-loko/goones](https://github.com/ad-sho-loko/goones)\n* [github.com/fogleman/nes](https://github.com/fogleman/nes)\n* [github.com/marethyu/nesty](https://github.com/marethyu/nesty)\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxpoletaev%2Fdendy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxpoletaev%2Fdendy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxpoletaev%2Fdendy/lists"}