Chipolata is an emulator/interpreter for the CHIP-8 virtual machine, with configurable emulation modes for various popular extensions to the platform so as to provide compatibility with the majority of available CHIP-8 ROMs.
Chipolata is written in pure Rust, and comprises decoupled library and binary crates for the emulator engine and GUI respectively.
Does the world really need yet another CHIP-8 emulator? Probably not! So, why might this be of interest to anyone?
Chipolata was originally created as a learning project: an opportunity to get to grips with the Rust language and idioms whilst taking a first step into the world of emulator development. However, as I progressed with the project I found myself becoming far more interested and engrossed in the platform and its history than I expected, and so ended-up refactoring and extending my emulator to the point where perhaps someone, somewhere, may have a use for it. The two key elements of Chipolata that differentiate it from many other similar emulators are:
- Emulator "engine" library entirely decoupled from the GUI code (separate Rust crates), with all communication done through a public API
- Highly-configurable emulation compatibility options (with a design that supports taking this further in future)
The types of people who might be interested in Chipolata are:
- CHIP-8/retro gaming enthusiasts wanting to run a wide variety of CHIP-8 ROMs designed for a number of different historic CHIP-8 interpreters/extensions in a single, intuitive, robust desktop application.
- Programmers wanting to build a CHIP-8 front-end from an existing emulator library, rather than building the entire platform from scratch. For example, the current Chipolata GUI is built using the egui immediate mode UI library; building an alternative front-end as a way of learning or experimenting with one of the many other Rust UI libraries could make for an excellent project.
- Programmers new to Rust or to emulation who would like to try making some enhancements or improvements to an existing codebase before/instead of taking-on an entire project of their own. There are several ways in which Chipolata can be extended (for example the addition of a debugging UI, which was always my intention) that may be of interest to someone. Please feel free to take a look at the current open Issues for inspiration.
If you are looking for a very mature, fully-fledged web-based CHIP-8 IDE with associated tools and wider ecosystem then the de facto standard is Octo, and you may be better off looking there.
Here you can see Chipolata in action, briefly playing the game "Spacefight 2091!" and changing a few options within the GUI:
This is displayed when Chipolata is first launched and again whenever the current program is unloaded (via the Stop button), and displays basic operating instructions plus the keymap:
A modal dialogue box displayed whenever a new program is loaded or if the user clicks the Options button in the top bar. From here, key settings of the emulator can be configured to allow fine-grained control over compatability options for different generations of ROMs. Option sets can be saved to and loaded from JSON files for convenience:
While a program is running, the central pane is used to render the contents of the emulator's frame buffer (the resolution used will depend on whether we are in CHIP-8 or SUPER-CHIP emulation mode). Execution can be paused and resumed, restarted, or stopped entirely, and the emulation speed can be altered without interrupting execution:
Any errors generated by the emulation engine are bubbled-up and displayed within the UI above the bottom status bar:
The Chipolata library crate models the entire CHIP-8 virtual machine component-by-component, and favours the use of high-level abstractions over highly-optimised/in-lined code in an effort to prioritise ease of understanding and ease of use over the utmost efficiency. Full, up-to-date rustdoc
documentation is provided, and is linked within the Further Reading section.
- A clean, intuitive public API, with the majority of interactions taking place through the
Processor
struct - Cycle timings handled within the library itself as part of the
execute_cycle()
method (based on the specified processor speed), meaning the hosting UI can simply call into the function as often as it wishes/is able to and not have to worry about the resulting simulation speed - Ability to export the internal state of the Chipolata virtual machine on-demand with different degrees of verbosity for different purposes (e.g. a minimal export of the frame-buffer for screen-rendering purposes, or a more comprehensive export of all register and memory contents for debugging)
- Abstractions provided for both program ROMs and configuration option sets via the
Program
andOptions
structs, including methods for serialising and deserialising these to and from disk - A
ChipolataError
struct encapsulating anErrorDetail
enum with variants for many Chipolata/CHIP-8-specific error cases that may occur while running a ROM, bubbled-up gracefully to the hosting UI for handling or reporting - Comprehensive
rustc
unit test suite with over 320 test cases as per release v1.0.0 (run automatically as part of the CI workflow on every push to themain
anddevelopment
branches)
Via its Options
struct, Chipolata offers authentic emulation of all known quirks (such as implementation deviations from the original specification of certain opcodes) for the following historic CHIP-8 interpreters:
- The CHIP-8 interpreter for the RCA COSMAC VIP, created by Joseph Weisbecker in 1978 (the "original" CHIP-8)
- Configurable emulation of a COSMAC VIP with either 2KB or 4KB of RAM
- Optional simulation of original instruction execution timings as per the COSMAC VIP's 1.76Mhz RCA 1802 processor, based on Laurence Scotford's disassembly of the original CHIP-8 interpreter and his subsequent documentation of the CPU cycles required to execute each opcode (as per the detailed pages indexed here)
- The CHIP-48 interpreter for the HP-48 graphic calculators, created by Andreas Gustafsson in 1990
- The SUPER-CHIP 1.1 interpreter for the HP-48S and HP-48SX graphic calculators, created by Erik Bryntse in 1991
- The Octo deviations from SUPER-CHIP behaviour (please note Chipolata does not support Octo's own "XO-CHIP" extensions - yet!)
Chipolata implements all enhanced features of SUPER-CHIP including high-resolution mode (128 x 64) and the new display instructions (scrolling, double-width sprite draw etc).
Additionally, the following common configuration options are available in all emulation modes:
- Target processor speed, in terms of the number of opcodes Chipolata will execute per second (this can also be changed dynamically by the user during program execution). Please note this option is disabled when simulating original instruction timings in CHIP-8 mode as above, as in this case speed is fixed to be equivalent to the original COSMAC VIP
- Program start location in RAM
- Font start location in RAM
Please note: at present, Chipolata is only available for Windows. There is nothing intrinsic to Chipolata that precludes compilation for other platforms; I have simply not had the need or opportunity to look into cross-compilation yet. This is on the to-do list! For now, the remainder of this section assumes the reader is similarly running a 64-bit Windows architecture.
If you simply want to use Chipolata itself, the quickest way to get up-and-running is to download the latest binary from Releases. The zip file artefact attached to the release can be extracted to a location of your choosing, and contains the following:
- The chipolata.exe file
- A resources folder, containing:
- An options folder that contains a number of pre-defined option set .json files that can be loaded from the "Emulation Options" dialogue box within Chipolata
- A roms folder that contains a number of CHIP-8 and SUPER-CHIP ROMs (.ch8 files) available in the public domain, divided into the following category sub-folders:
- demos - largely non-interactive CHIP-8 demo programs
- games - interactive games
- superchip - games requiring SUPER-CHIP emulation support (be sure to select the appropriate emulation mode within Chipolata)
- tests - test ROMs mainly of use to interpreter developers to ensure their implementation of CHIP-8 is behaving as intended
Chipolata is configured to statically link the C runtime in addition to all its Cargo-added crate dependencies, so the .exe file has no additional dependencies that must be pre-installed on the host computer.
If you wish to modify/enhance Chipolata, or simply wish to compile the binary for yourself direct from the source code, then you will need a local development environment with the Rust toolchain installed, and some form of code editor to work with. A popular choice for the latter is Visual Studio Code (VS Code). The steps to configure a VS Code-based Rust development environment are as follows:
i) Install the Rust toolchain using rustup
, by following the simple instructions on the Install Rust page on the official Rust website.
ii) Install VS Code from the Visual Studio Code download page.
iii) Install the rust-analyzer extension for VS Code from within the Extensions view (Ctrl+Shift+X
) by searching for 'rust-analyzer'.
iv) If not already present on your computer, you will need to also Install Git in order to be able to interact with the GitHub repo.
Once installed, you can interact with the components of the Rust toolchain through a terminal window or the Command Prompt; if new to Rust you should familiarise yourself with these tools and commands (and in particular with cargo
) before proceeding as they are fundamental to interacting with the project.
This section assumes you already have a GitHub account. If not, please visit Join GitHub and sign up.
If you would like to modify and recompile the Chipolata source code then you will need to first Fork the Chipolata GitHub repo.
Next you will need to clone your forked repo to your local environment to start working on it. Please see Cloning a repository for instructions.
Once you have a local copy of the repo you can start working on the source code within VS Code by selecting File -> Open Folder
and choosing the corresponding local root chipolata
folder (i.e. the folder containing the cargo.toml
file).
Useful Rust toolchain commands (executed within the Chipolata working directory) are:
cargo build
This will create a .exe binary in the chipolata\target\debug
folder.
cargo build --release
This will create an optimised .exe binary in the chipolata\target\release
folder.
cargo run
This will build Chipolata in debug mode and run the executable for you.
cargo test
This will execute the entire unit test suite against the current codebase and report the results.
cargo test -- --include-ignored
This will execute the entire unit test suite including any tests that are ignored by default (typically those that involve performance/timings).
cargo doc
This will recreate all the html documentation held in the chipolata\target\doc
folder
structure.
cargo doc --no-deps
This will recreate the html documentation for the Chipolata library crate only (not the crates on which it is dependent).
Use Git either on the command line or within the VS Code UI to commit changes and push them back to your forked GitHub repo. Feel free to raise a Pull Request back to the development
branch of the upstream Chipolata repo if you've made changes that you think should be folded back in!
Chipolata is not published on crates.io as I don't anticipate any demand for this. However should you wish to use it - for example to write your own alternative UI - then you can still add a dependency to the Chipolata library crate by specifying the GitHub repository directly in your package's cargo.toml
manifest as follows:
[dependencies]
chipolata = { git = "https://github.com/jon-axon/chipolata.git"}
Once the dependency is added, please see the Further Reading section for links to the documentation to help you get started making use of the Chipolata library.
In the unlikely event that it is beneficial for anyone for Chipolata to be published on crates.io (for example if somebody wants to publish their own crate that in turn has a dependency on Chipolata) then please let me know.
If you have questions, please use GitHub Discussions.
The Chipolata repo currently follows a traditional workflow with a main
trunk branch and development
long-lived feature branch (although it may be preferable at somepoint to replace this with a more lightweight Git Flow approach). Specifically, the branching strategy is as follows:
- The
main
branch contains the latest release code (with appropriate tag assigned), and code may only be merged via Pull Request. - The
development
branch is used for staging sets of changes before they are ready to be merged intomain
as part of a new release. Up until v1.0.0 I have been pushing changes directly into thedevelopment
branch for convenience, however going forwards this branch should also only allow merges via Pull Request, and new code should instead by pushed to specific feature branches. - The
gh-pages
branch holds the HTML behind the Chipolata GitHub Pages site. This branch should not be pushed-to directly, and is handled entirely via the CI process (see below).
Continuous Integration workflows exist for pushes to both main
and development
:
- The
CI (dev)
GitHub Action builds and runs the unit test suite against thedevelopment
branch - The
CI (main)
GitHub Action builds and runs the unit test suite against themain
branch, and then also rebuilds all therustdoc
documentation and pushes this to thegh-pages
branch - The GitHub-generated
pages-build-deployment
workflow publishes changes to thegh-pages
branch to the Chipolata GitHub Pages site, and so completes the automated documentation generation process whenever new code is pushed tomain
.
Currently there is no automated release workflow; the CI process only goes as far as building, testing, and publishing documentation for new code pushed to main
. Creation of tags, releases, and uploading associated artefacts is a manual step. Automating this is on the to-do list.
Should you wish to contribute anything to Chipolata, please feel free to fork the repo and raise a PR back to the development
branch!
More detailed documentation around the design and inner-workings of Chipolata can be found on the Chipolata GitHub Wiki.
The latest rustdoc
documentation for the chipolata library crate can be found on Chipolata GitHub Pages, and is an essential reference if building a new UI on top of the chipolata emulator library. This documentation is automatically rebuilt via the Continuous Integration workflow whenever new code is pushed to the main
branch, so will always be in-sync with the latest release.
There are many, many CHIP-8 resources available on the web. Following are a small number I have found most useful while creating Chipolata.
Building a CHIP-8 emulator:
- Tobias Langhoff's Guide to making a CHIP-8 emulator
- Matt Mikolay's 'Mastering CHIP-8'
- Timendus CHIP-8 test suite
ROMs and other curated resources:
Advanced/detailed references:
- Laurence Scotford's series of articles on the original CHIP-8 interpreter for the RCA COSMAC VIP
- The CHIP-8 Research Facility documentation of extensions to CHIP-8
Forums:
Chipolata and all its associated artefacts are made available under the MIT license. See LICENSE for additional details. Contributions to this repository are welcome, with the understanding that they will fall under the same licensing conditions.