An NES emulator written in Rust

Related tags

Emulators pinky
Overview

Build Status

Pinky

Pinky is an NES emulator written in Rust completely from scratch based only on publicly available documentation.

You can run it in your Web browser!

Features

  • Accurate-ish (cycle accurate) 6502, PPU and APU emulation.
  • A testsuite based on test ROMs.
  • A PPU testsuite automatically generated from a transistor-level simulation of a real PPU.
  • Supports NROM (0), MMC1 (1), UxROM (2), AxROM (7) and UNROM 512 (30) mappers.
  • Can be compiled as a libretro core.
  • Can be compiled into WebAssembly.

There are still many things missing, including:

  • Most unofficial 6502 instructions.
  • Support for other mappers.
  • Accurate PPU sprite overflow.
  • Savestate support.
  • PAL support.

Currently this is not a production quality emulator, though whatever games it can play (due to limited mapper support) it can play quite well (e.g. such games as Super Mario Brothers, Donkey Kong or Tetris; you can check out nesmapper.txt which will tell you which game use which mapper).

Getting started

Internally this project is split into multiple crates.

The pinky-libretro contains the libretro core of this emulator, which is the intended way to run it. It should be compatible with any libretro frontend, but it was only tested with RetroArch.

To compile the libretro core go into the pinky-libretro directory and type:

cargo build

This should build a shared object in target/debug called libpinky_libretro.so (on non-Linux systems the extension might be different, e.g. on Windows it'll be a .dll) which then you can use with RetroArch like this:

retroarch -L libpinky_libretro.so your_rom.nes

You can also run cargo build --release to build a significantly better optimized version (the debug build should run full speed on modern systems though).

There's also a simple standalone SDL2-based frontend in the pinky-devui directory; running it is just a matter of passing it a path to your game ROM on the command line.

The nes-testsuite contains an emulator agnostic testsuite of NES roms, which could be easily hooked to any other emulator simply by implementing a single trait (see nes/src/testsuite.rs).

The rp2c02-testsuite contains a PPU testsuite which is autogenerated with the help of Visual2C02, which is a transistor-level simulator of an actual NES PPU.

The nes contains the emulator itself. mos6502 has the 6502 interpreter, which could be useful for emulating other 6502-based machines.

There are already hundreds of NES emulators out there; why another?

Because why not? Writing a game console emulator is one of the most fun and rewarding projects out there, and nothing can compare with the feeling of beating one of your favorite games on an emulator you've wrote yourself.

The choice of NES is also an obvious one - it's the least time consuming console to emulate simply due to the fact that it's extremely well documented.

Comments
  • missing information on how to start

    missing information on how to start

    I saw your project on the changelog weekly newsletter and wanted to try it out. But now I have no idea how to start. I downloaded retroarch but there's no cli coming with it. Can you flesh this out in your documentation?

    opened by philippkeller 12
  • Fixed silencing of square 1 channel when sweep is disabled

    Fixed silencing of square 1 channel when sweep is disabled

    When the sweep is disabled, but the negate flag is set (%00001000 written to $4001), the frequency_generator_output() function shouldn't be called. In fact, because the last 3 bits are set to 0, the adjust_period_based_on_frequency_generator() function doesn't end up calling it.

    But, it's being called to check if the square channel should be silenced: !self.enabled || self.period < 8 || self.length_counter == 0 || self.frequency_generator_output() >= 0x7FF

    When frequency_generator_output() is called here (with the sweep disabled), self.period is shifted by 0 bits, so period_delta = self.period. Thus self.period.wrapping_sub( period_delta ).wrapping_sub( 1 ) = (0-1), underflowing to 0xFFFF which is indeed greater than 0x7FF. So the channel is silenced.

    Added an additional check to see if the sweep is enabled before checking its state.

    opened by xram64 4
  • Fix silencing of noise channel when envelope decay is on

    Fix silencing of noise channel when envelope decay is on

    The noise channel is silent any time the envelope decay bit (i.e. bit 4 of $400C) is set to 0.

    When bit 4 is 0, the envelope decay is disabled, so is_manually_controlled is set to false, and thus the volume of the noise channel gets set to self.generated_volume in VolumeGenerator's volume() function. The problem is, self.generated_volume is never updated, and so it stays at the default volume of 0, silencing the channel.

    As far as I can tell, the noise channel is supposed to work exactly the same as the square channels when it comes to the volume register (apart from duty bits), so my proposed fix is to duplicate the function used to update the square channels' volume generator, and update the noise channel along with the squares in clock_sequencer().

    opened by xram64 3
  • Unable to play NESMaker games

    Unable to play NESMaker games

    I tried to play the demo NES game from NESMaker trollburner_demo.nes.zip but it fails saying

    Unable to load ROM - unhandled mapper: 30
    
    Sorry about that! Maybe try another ROM?
    

    It would be amazing if this emulator could run NESMaker games! http://austinmckinley.com/8bit/the-tools.html

    opened by triptych 2
  • pinky-web stuck at

    pinky-web stuck at "Loading..." when compiled locally

    I wanted to poke at pinky-web on my own machine, so I cloned master and followed the native WebAssembly backend instructions in the Readme. The exact nightly I downloaded was rustc 1.25.0-nightly (616b66dca 2018-02-02).

    The local server started up just fine, but if I go to localhost:8000 in a browser that ran the version at http://koute.github.io/pinky-web/ without problems, then I see the description on the left as expected, but on the right I see just "Loading..." instead of the ROM selection menu.

    If I open the console on the local version, I see only the single line

    Finished loading Rust wasm module 'pinky_web'
    

    instead of the two lines

    WebGL support using context: webgl
    Finished loading Rust wasm module 'pinky_web'
    

    I see at http://koute.github.io/pinky-web/ .

    So I suppose something is going wrong with the wasm loading somehow?

    opened by Ryan1729 2
  • "Load your own ROM" does not work on pinky-web

    • macOS, issue exists on Firefox and Chrome (at least)
    • go to http://koute.github.io/pinky-web/
    • Click "Load your own ROM"
    • Try to load any file
    • See in Javascript console: TypeError: $1.files is not a function
    opened by blandinw 1
  • Fix JS TypeError when WebGL context is not defined.

    Fix JS TypeError when WebGL context is not defined.

    This addresses cases where WebGL is either broken or disabled. The error message on Chrome was a Cannot read property 'create'Shader' of null TypeError, however, the cause of this error was the variable gl being null after attempting to retrieve all valid WebGL rendering contexts.

    opened by ChrisRx 1
  • Square 1 not playing

    Square 1 not playing

    I noticed SQ_1 was not playing in the roms I tested (using RetroArch). I narrowed it down to virtual_apu.rs, line 577: self.period.wrapping_sub( period_delta ).wrapping_sub( 1 )

    That .wrapping_sub( 1 ) is the problem. If I change it to 0, or change it to .wrapping_add( 1 ), it seems to work fine. ~~I'd make a pull request, but I'm honestly not sure what that subtraction is there for, so I don't know if/how it should be changed.~~

    Edit: After reading over the APU doc again, I see that the subtraction is to account for the difference in SQ_1's sweep. Still not sure why a wrapping_sub there seems to silence the channel though. I can wrapping_add any number without a problem.

    opened by xram64 0
  • Add Action 53

    Add Action 53

    Perhaps the easiest way to pump up the number of games you can (legally) offer through the demo would be to add support for the Action 53 mapper (iNES mapper 28). This mapper is about as complex as MMC1 (iNES mapper 1) and makes the emulator compatible with Action 53 Volume 4, which contains over 50 homebrew games.

    opened by pinobatch 0
  • Backward A and B Buttons

    Backward A and B Buttons

    A on the left and B on the right is backward from how many NES games map their controls. Affects Lode Runner, Championship Lode Runner, and Thwaite. (I was lead programmer for Thwaite.)

    opened by pinobatch 0
  • Audio is a pop-fest

    Audio is a pop-fest

    Audio is a pop-fest, as if random values were written to $4011 several times per second, and games play too slow. This is in Firefox 72.0.2 (64-bit) on Xubuntu 18.04 on a Dell Inspiron 11-3168 laptop with a quad-core Pentium N3710 CPU, running on AC power.

    opened by pinobatch 0
  • Add BNROM (#34)

    Add BNROM (#34)

    "Unable to load ROM - unhandled mapper: 34"

    Lack of BNROM support affects Deadly Towers, Haunted: Halloween '85, Lizard, and 240p Test Suite (BNROM version) (pinobatch/240p-test-mini). I was lead developer on HH85 and 240p and can help explain the mapper if you need.

    opened by pinobatch 0
Owner
Koute
Koute
An NES emulator written in Rust

Pinky Pinky is an NES emulator written in Rust completely from scratch based only on publicly available documentation. You can run it in your Web brow

Koute 709 Dec 23, 2022
NES emulator written in Rust

sprocketnes is an emulator for the Nintendo Entertainment System written in the Rust programming language. Its purpose is to serve as a technology dem

Patrick Walton 725 Dec 27, 2022
a work-in-progress NES emulator written in rust.

sayaka-rs a work-in-progress NES emulator, written in Rust. the project image is an edit of a frame from the Mahou Shoujo Madoka Magica manga. the Mik

Lumine 1 Jan 16, 2022
A NES emulator written in Rust, with a focus on expandability and accuracy

A NES emulator written in Rust, with a focus on expandability and accuracy

Benjamin Mordaunt 4 Sep 19, 2022
NES emulator in rust

NES emulator in Rust plastic is a NES emulator built from scratch using Rust. This is a personal project for fun and to experience emulating hardware

Amjad Alsharafi 27 Dec 15, 2022
A simple NES emulator implemented in Rust. (WIP)

remu A ?? ?? BLAZINGLY FAST* ?? ?? NES emulator implemented in Rust. Status: Work in progress. About This emulator is mainly meant to be more of a lea

luna 10 Aug 25, 2022
🥔 MOS-6502 and NES emulator in Rust (SDL/WebAssembly)

?? Potatis /mos6502 - Generic CPU emulator. Passes all tests, including illegal ops. (No BCD mode). /nes - A very incomplete NES emulator. /nes-sdl -

Henrik Persson 28 Jan 9, 2023
A **BLAZINGLY FAST** rust emulator for the NES.

rust-nes A BLAZINGLY FAST rust emulator for the NES. Install / Usage Clone the repository and navigate to it git clone https://github.com/imagine-huss

null 7 Jan 20, 2023
Learn emulator and programming languages, target chip8, nes, gbc, gba ...

[WIP]learn emulator go-chip8 go run main.go source https://en.wikipedia.org/wiki/CHIP-8 http://devernay.free.fr/hacks/chip8/C8TECH10.HTM https://githu

早晨海风 4 Apr 30, 2021
Chip8 emulator written in pure rust, using rust-sdl2 for graphics

Rust-8 chip8 emulator written in rust, using rust-sdl2 for graphics. Features Fully implemented all 35 original chip8 opcodes. This emulator does NOT

Chris Hinson 7 Dec 28, 2022
Commodore 64 emulator written in Rust

Rust64 - a C64 emulator written in Rust This is my attempt to study the Rust programming language and have fun at the same time. The goal is to presen

Krzysztof Kondrak 214 Dec 27, 2022
A Flash Player emulator written in Rust

website | demo | nightly builds | wiki Ruffle Ruffle is an Adobe Flash Player emulator written in the Rust programming language. Ruffle targets both t

Ruffle 11.2k Jan 8, 2023
A Game Boy research project and emulator written in Rust

Mooneye GB Mooneye GB is a Game Boy research project and emulator written in Rust. The main goals of this project are accuracy and documentation. Some

Joonas Javanainen 802 Dec 28, 2022
RustBoyAdvance-NG is a Nintendoâ„¢ Game Boy Advance emulator and debugger, written in the rust programming language.

RustBoyAdvance-NG Nintendo GameBoy Advance â„¢ emulator and debugger, written in rust. WebAssembly Demo: https://michelhe.github.io/rustboyadvance-ng/ P

MishMish 510 Dec 30, 2022
ZX Spectrum emulator written in Rust

rustzx ZX Spectrum emulator which I writing in rust. I develop this project just for fun and for learning the basics of computer architecture. License

Vladislav Nikonov 162 Dec 27, 2022
CHIP-8 emulator written in Rust

CHIP-8 emulator written in Rust. This is intended to be a project for gaining experience writing emulators and practice Rust.

Pedro Rodrigues 4 May 21, 2021
A 6502 emulator written in Rust.

v6502 This package contains an emulator for the 6502 microprocessor. It doesn't support binary decimal (BCD) mode yet. To run the debug version: cargo

Andrew Young 4 Nov 14, 2021
Spaghetti Chip8 Emulator Written In Rust

How to run? Command is simple: cargo run FILENAME. files are stored in the /c8games folder, use one of them. Example: cargo run INVADERS Keymap use 1

Can 5 Apr 15, 2022
Non cycle-accurate emulator of the 6502 cpu, written in pure rust

CPU 6502 A non cycle-accurate emulator implementing all legal 6502 opcodes. What does non cycle-accurate mean? Every instruction on the 6502 takes a n

Pietro 10 Jul 15, 2022