An 8080 Space Invaders emulator in Rust

Related tags

space-invade.rs
Overview

Space Invade.rs

An 8080 Space Invaders emulator written in Rust

space-invaders-1

This is an 8080 emulator running the 1978 Space Invaders game by Taito, written in Rust. space-invade.rs is my third emulator (the first one was Chip-8 and then an Apple ][ emulator, both written in Kotlin). I chose Rust for this project to experiment with a different design and see how far I could push the performance.

Running the emulator

On Windows, you can just cargo run --release.

On macOS, you will need to install SDL2 first (brew install sdl2).

I haven't tested on Linux.

cargo test will run the cpudiag emulator test.

Playing it

  • Press C to insert a coin.
  • Press 1 or 2 to select the number of players.
  • Player 1: left and right arrows to move, space to shoot.
  • Player 2: a and d to move, s to shoot.
  • 'p' will pause the game, any key will resume.
  • ESC to close the window.

The 8080 processor

The 8080 turned out to be quite an advanced processor and even though it came out before the 6502 (1974 and 1975 respectively), I grew to appreciate its rich set of instructions (the 6502 only has 56, the 8080 has over 200) and how elegantly you can write some algorithms.

The emulator in this project is close to complete, including:

  • All the instructions
  • Correct cycle count
  • Implementation of binary coded decimal (DAA)
  • Interruptions (EI and SI and some RST but not all since Space Invaders only uses a few)

The emulator also passes the cpudiag diagnostic application, which you can run with cargo test.

Space Invaders

The arcade game had quite an interesting architecture, please see the resources section if you need in-depth details. In a nutshell:

  • The resolution is 224x256 with one bit of depth, so just black and white. The arcade used tranparent green and red tapes on top of the screen to simulate additional colors, which this emulator does as well.
  • The graphic memory starts at 0x2400 with each byte representing eight bits (note: the screen is flipped 90 degrees).
  • The video generates two interrupts: one when the beam is halfway through the screen and one at the end of the screen (VBL). Each of these interrupts calls a RST which tells the CPU to jump at $08 and $10 respectively. These two addresses are in charge of updating the half of the screen that the beam just finished drawing (quite a clever hack). My emulator doesn't go to that level of details and simply refreshes the graphic during the VBL.
  • While the 8080 knows how to shift bits, it only has instructions to shift by one bit, and these are pretty slow, which makes shifting variable numbers of bits costly. This is unfortunate since it's the only way that this hardware can animate its graphics, so the designers created a multiple bit shifter outside in the game hardware itself and hooked it up with its input and output instructions. Refer to the detailed architecture (or the code) to understand how this works, but I thought this was another very clever design around hardware limitations of the time.

The main logic is in the file sdl2.rs, which spawns the emulator in a separate thread. That thread updates the graphic memory which the SDL 2 main loop uses to draw the graphics on the main screen.

The emulator is calibrated to run at 2Mhz with the following logic, which you will find in run_one_frame() in emulator.rs:

  • Run as many cycles as necessary to reach the first half of the screen (about 16,500)
  • Generate the first interrupt
  • Run as many cycles as necessary to reach the end of the screen (33,000)
  • Generate the second interrupt

This function is called for each frame but the caller will sleep if needed so that the next frame isn't drawn until 16ms have elapsed (60Hz). You can find this code in sdl2.rs. Without this delay, this is what the game at normal speed will look like, running at about 70Mhz instead of 2Mhz:

space-invaders-2

Note that letting the game run like this for a little while is a good way to test that your code doesn't have any bugs that only show up on the long run...

Despite this, I can't shake the feeling that my Space Invaders is running a bit faster than the original, based on watching some footage of the actual arcade game, but I'm not 100% sure. Feel free to let me know if you find a bug in my timing routine that might explain my impression.

Lessons learned

cpudiag is not enough.

When I wrote my Apple ][ emulator, I first developed the 6502 emulator with a diagnostic file that was extremely thorough, and which gave me a pretty much 100% guarantee that once all these tests pass, my 6502 is flawless and I can now focus on the Apple ][ part without worrying about CPU bugs. I started this project with the same assumption and it was a mistake. Deep into the development, I was displaying graphics that made no sense and after hours of disassembling and understanding what the 8080 code actually does, I ended up finding two CPU bugs which cpudiag had not found.

And one of them was really trivial: I hadn't implemented the MOV E,A instruction correctly. This is a very simple instruction which moves the content of A into E, but I made a typo in my code and moved it into D instead... The other bug was in my implementation of DAD.

Moral of the story: you might have to add tests of your own, and at any rate, you cannot embark on such a project without developing a fluent ability to understand the assembly you are emulating.

Graphics in Rust are still not quite there.

It's becoming a meme now that Rust is struggling in the graphics library department (exhibit A) and in the game department (exhibit B). Finding a library that would make it easy for me to implement this project with very simple requirements (basically just need a frame buffer, possibly some simple GUI widgets) took me way too long. I ended up settling on SDL 2, but the bottom line is that developing GUI's and graphics in Rust on Windows is not exactly a walk in the park.

Next steps

I'm probably done with this project but if I were to come back to it to improve it, I would probably:

  • Make it run in the browser with WASM
  • Sound
  • The graphics still seem a bit janky to me, I'm probably doing something wrong in the SDL 2 event handling
  • Make it do less busy waiting
  • Show the controls so the user doesn't have to guess
  • Add a debugger, breakpoints, etc...

Resources

The following documentation was invaluable to pull off this fun project:

Owner
Cedric Beust
Creator of Android Gmail.
Cedric Beust
HNSW ANN from the paper "Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs"

hnsw Hierarchical Navigable Small World Graph for fast ANN search Enable the serde feature to serialize and deserialize HNSW. Tips A good default for

Rust Computer Vision 69 Sep 11, 2021
Tangram is an automated machine learning framework designed for programmers.

Tangram Tangram is an automated machine learning framework designed for programmers. Run tangram train to train a model from a CSV file on the command

Tangram 763 Sep 18, 2021
A Rust🦀 implementation of CRAFTML, an Efficient Clustering-based Random Forest for Extreme Multi-label Learning

craftml-rs A Rust implementation of CRAFTML, an Efficient Clustering-based Random Forest for Extreme Multi-label Learning (Siblini et al., 2018). Perf

Tom Dong 12 Apr 21, 2021
Barnes-Hut t-SNE implementation written in Rust.

bhtsne Barnes-Hut implementation of t-SNE written in Rust. The algorithm is described with fine detail in this paper by Laurens van der Maaten. Instal

Francesco Iannelli 22 Sep 9, 2021
A Rust machine learning framework.

Linfa linfa (Italian) / sap (English): The vital circulating fluid of a plant. linfa aims to provide a comprehensive toolkit to build Machine Learning

Rust-ML 1.2k Sep 13, 2021
Kalman filtering and smoothing in Rust

Kalman filtering and smoothing library written in Rust Access documentation for the library here. Library is also referenced in Cargo index. Currently

Rytis Bagdziunas 23 Jun 25, 2021
Machine learning crate for Rust

rustlearn A machine learning package for Rust. For full usage details, see the API documentation. Introduction This crate contains reasonably effectiv

Maciej Kula 496 Aug 27, 2021
Qdrant - vector similarity search engine with extended filtering support

Vector Similarity Search Engine with extended filtering support Qdrant (read: quadrant ) is a vector similarity search engine. It provides a productio

qdrant 560 Sep 12, 2021
Rust language bindings for TensorFlow

TensorFlow Rust provides idiomatic Rust language bindings for TensorFlow. Notice: This project is still under active development and not guaranteed to

null 3.3k Sep 16, 2021
Xaynet represents an agnostic Federated Machine Learning framework to build privacy-preserving AI applications.

xaynet Xaynet: Train on the Edge with Federated Learning Want a framework that supports federated learning on the edge, in desktop browsers, integrate

XayNet 149 Sep 12, 2021
Rust numeric library with R, MATLAB & Python syntax

Peroxide Rust numeric library contains linear algebra, numerical analysis, statistics and machine learning tools with R, MATLAB, Python like macros. W

Tae Geun Kim 239 Sep 5, 2021
l2 is a fast, Pytorch-style Tensor+Autograd library written in Rust

l2 • ?? A Pytorch-style Tensor+Autograd library written in Rust Installation • Contributing • Authors • License • Acknowledgements Made by Bilal Khan

Bilal Khan 136 Aug 17, 2021
个人的 rust 学习资料

?? 通知: 项目文档迁移到: https://github.com/higker/learn-rust learning-rust-zh 个人的 rust 学习资料 学习目录 目录 源代码地址 相关解析 第一个rust程序 https://github.com/higker/learning-ru

Jarvib Ding 14 Aug 31, 2021
Rust based Cross-GPU Machine Learning

HAL : Hyper Adaptive Learning Rust based Cross-GPU Machine Learning. Why Rust? This project is for those that miss strongly typed compiled languages.

Jason Ramapuram 79 Jul 9, 2021
FFSVM stands for "Really Fast Support Vector Machine"

In One Sentence You trained a SVM using libSVM, now you want the highest possible performance during (real-time) classification, like games or VR. Hig

Ralf Biedert 43 May 4, 2021
Rust crate to create Anki decks. Based on the python library genanki

genanki-rs: A Rust Crate for Generating Anki Decks With genanki-rs you can easily generate decks for the popular open source flashcard platform Anki.

Yannick Funk 31 Sep 1, 2021
Rust library for Self Organising Maps (SOM).

RusticSOM Rust library for Self Organising Maps (SOM). Using this Crate Add rusticsom as a dependency in Cargo.toml [dependencies] rusticsom = "1.1.0"

Avinash Shenoy 22 Jul 28, 2021
Open Machine Intelligence Framework for Hackers. (GPU/CPU)

Leaf • Introduction Leaf is a open Machine Learning Framework for hackers to build classical, deep or hybrid machine learning applications. It was ins

Autumn 5.5k Sep 10, 2021
https://getrust.tech

learn-rust 这是一个分享Rust学习资料的在线学习网站 https://getrust.tech ?? 。 微信群二维码过期你可以添加我微信: AA996DD 目的是什么 ❓ 通过连载文章的形式帮助有一定其他语言编程基础的人快速学习和入门 Rust 内容包括 Rust 基础、内置库、web

Jarvib Ding 300 Sep 17, 2021