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 and connecting them together.
Building and installation
Pre-built
There are pre-built binaries in the releases tab, Plastic comes in different UIs, some work in Windows and Linux and some are for one of them, check Interfaces for more details.
Building
If you want to experience the latest development version, you can build Plastic
yourself. You would need Rust itself and any UI dependency for the UI you want to use if needed. For example:
Recommended UI for linux is GTK:
cargo run --release -p nes_ui_gtk
Recommended UI for windows is Native_Windows:
cargo run --release -p nes_ui_native_windows
Note:
--release
should be used as running the emulator indebug
mode would slow it down very much that it would make games unplayable.
Components
- 6502 CPU, all official and unofficial instructions with accurate timing (without BCD mode).
- Picture Processing Unit, almost accurate with some small timing issues that would not effect most games.
- Cartridge and INES file handling (still missing INES2.0)
- Mappers:
- Mapper 0
- Mapper 1
- Mapper 2
- Mapper 3
- Mapper 4
- Mapper 5 (Milestone)
- Mapper 6
- Mapper 7
- Mapper 8
- Mapper 9
- Mapper 10
- Mapper 11
- Mapper 66
- Audio Processing Unit:
- 2 Pulse wave(square)
- Triangle
- Noise
- DMC
- IRQ support
- Controller: controllable using the keyboard and controller (tested with PS4 controller)
Interfaces
One advantage of this emulator is the great abstraction, for example, adding UI handlers for the emulator is very easy and straight forward. All you have to do is to write a UiProvider
, and simply use it with NES
like so:
use plastic_core::nes::NES;
// Provider implement trait `UiProvider`
let mut nes = NES::new("path/to/rom.nes", Provider {})?;
nes.run();
For now all UI providers can reset the game through <CTRL-R>
Using this design, I have implemented some providers which have different purposes:
SFML
SFML is a game development UI library, it has a good and easy to use API and is the most performing UI in the list.
Advantages
- Designed for Canvas and raw drawing, which makes it faster.
- Has support for gamepad (only tested with PS4).
GTK
GTK is a casual GUI library that is used to make all kinds of applications and not designed for games.
The reason I chose to go with it is for future plans to add a debugger, which would be a lot easier to add in this UI compared to SFML.
From the screenshot, it looks exactly like SFML, and that's because I haven't added anything specific to GTK yet. But it has almost the same performance as SFML, so hopefully there will not be much different in performance even after adding the debugger.
Advantages
- Ability to add buttons and menus which enable easier integration for debuggers and anything similar.
- Ability to open a NES file through the menu or by dragging the .NES file into the app.
- Can run without specifying a ROM from the command line.
- Ability to pause and resume emulation through
<ESC>
key and from the menues.
Disadvantages
- Does not offer gamepad support, but it can be added through other external libraries.
Native Windows GUI
Has the same UI and usages as the GTK version, but is targetted for windows as GTK require additional libraries to work for windows.
Advantages (in addition to GTK)
- Run on the native windows APIs, which is fast and does not need any additional libraries.
Disadvantages
- Does not offer gamepad support, but it can be added through other external libraries.
TUI
This is just for fun, but it is actually working way better than I expected. Check the demo.
I used gilrs for gamepad support and its working very nicely, keyboard on the other hand is not very responsive, so it is advised to use gamepad. Also since this uses one character for each pixel, it is advised to use the smallest font size your terminal emulator supports. Have fun.
Controls
In all the UI providers I followed the same controlling scheme, as well as the ability to reset through <CTRL-R>
:
Keyboard
keyboard | nes controller |
---|---|
J | B |
K | A |
U | Select |
I | Start |
W | Up |
S | Down |
A | Left |
D | Right |
Gamepad
gamepad (PS4) | nes controller |
---|---|
X | B |
O | A |
Select | Select |
Start | Start |
Button Up | Up |
Button Down | Down |
Button Left | Left |
Button Right | Right |
For now its static, and there is no way to change it except for doing it in the code, TODO later.
License
This project is under MIT license.
NES is a product and/or trademark of Nintendo Co., Ltd. Nintendo Co., Ltd. and is not affiliated in any way with Plastic or its author
References
Most of the documentation for NES components can be found in the NES dev wiki
For the CPU(6502), this has the instruction set, and I used Klaus2m5's tests for testing the CPU alone without the other NES components.