Advertisements
Astrododge for Chip8

Write a Chip8 retro gaming emulator in one day. Introduction.

Are you passionate about retrogaming? I am. And I just made my own retro gaming emulator. So now I want to write an article to show you how you can create your own emulator in one day. The platform we are going to emulate is Chip8, and it is extremely easy to learn. At the same time you can run actual classic games on it such as Tetris, Pong, Space Invaders and a lot more. So read on if you want to code your own retro gaming emulator.

It took me three days in total to have this thing completely running and bug free. But the emulator itself really took only one day. And this is the result at the end of day one

Astrododge for Chip8
See the complete code on GitHub

Writing an emulator is not the simplest task. But it’s a very good exercise and the result is very rewarding, trust me you’ll feel a lot cooler after this. I used Scala for this project, and so the code here will be in Scala. However I didn’t do crazy stuff with it and it should be easily understandable by anyone. If you know java you should be fine. Also, you can use any language you want, the ideas of course are the same.

The Chip8 platform

Joseph Weisbecker, a researcher and designer of microprocessors, created Chip8 during the 70s to allow easy game development for some early 8 bit hardware platform. Chip8 was never an hardware device itself. It was a language that could be compiled and run on a virtual machine. It looks like assembly code, in fact it is

LD  boxx, 1
LD  dirx, 1
LD  boxy, 10
LD  I, sprite1
DRW boxx, boxy, 8

This code is assembled into a binary format which runs on the Chip8 virtual machine. As you can see there are opcodes such as LD and DRW. Chip8 only has 35 opcodes in total, this is one of the main reasons why it is so easy to emulate.

Chip8 registers

The virtual machine is register based, meaning that all computations happen between values stored inside registers. There are 16 value registers, each of them can hold one byte. The last value register (the sixteenth) is used as carry flag and for collision detection, see the graphics section for more on this. Chip8 also uses a 16 bit index register for instructions that read and store values in memory.

There are two time based registers, both of them are 8 bit. The first one is the delay register and the second one is the sound register. The programmer uses an opcode to set the delay register to some value, the system then decrements this register sixty times per second until it reaches zero. This is very convenient for programs to have precise timing regardless of the cpu frequency, which might change depending on the actual machine the interpreter is running on. The sound register works in a similar way, the system decrements is sixty times per second until it reaches zero. The difference is that while the value of this register is greater than zero, the system plays a tone. An that is the whole audio capability of this system. I still did not implement the tone in my emulator and I’m not sure I ever will.

Chip8 graphics

Chip8 draws sprites on a 64×32 pixels screen. The screen is black and white, so each pixel is one bit. It really doesn’t get much easier than that. Chip8 can only draw sprites, never single pixels, unless a sprite is made by only one pixel being turned on. All the sprites are always 8 bits wide (so 8 pixels wide) and their height is specified in the instruction used to draw the sprite. The maximum height of a sprite is 8 pixels.
If a sprite of 4 pixels by 4 pixels is needed Chip8 still has to draw it 8 bit wide so the last four bits of each of its rows will be zero.

Chip8 8x8 Sprite
Example of an 8 pixels by 8 pixels sprite from Astrododge.
Chip8 4x4 sprite
Example of a 4 pixels by 4 pixels sprite. Notice that only four rows are drawn, the instruction used to draw the sprite specifies how many rows to draw. However Chip8 draws all 8 columns. Sprites are always 8 bits wide.

When drawing sprites on the screen each pixel is xorred with the existing content of the screen, the result of the xor is set as the new value of the pixel. If the previous value of the pixel was 1 and the new value of the pixel is also 1, the Chip8 sets the last value register to 1. This is how games detect collisions between sprites. The actual pixel on the screen in case of a collision will be zero, as a result of 1 XOR 1.

The controller

The controller is quite simple, it provides 16 buttons and the classic layout is the following

  1 | 2 | 3 | C
  --+---+---+--
  4 | 5 | 6 | D
  --+---+---+--
  7 | 8 | 9 | E
  --+---+---+--
  A | 0 | B | F

There are two opcodes to deal with key presses. One opcode skips the next instruction if a certain key is pressed, another opcode skips the next instruction if a certain key is not pressed. All games use these two instructions to figure out what the user is doing.

Chip8 memory layout

When the Chip8 interpreter starts it loads the program byte by byte starting from memory address 0x200. This means that programs never use addresses from 0x000 to 0x1FF as this is where the interpreter lives. The total addressable memory space is 4kb, or 4096 bytes. With an emulator the interpreter lives outside the Chip8 memory so we could in theory use these initial  512 bytes, however we are going to run old roms that are still thinking that there is an interpreter there, so they won’t use that address range. However there is still some use for this memory space, more on this later. As you can see the memory layout is pretty easy, first 512 bytes are reserved, the program lives starting at byte 512 and that’s it.

The stack

Finally there is the stack. Chip8 only uses the stack to store return addresses when it calls subroutines, therefore every entry in the stack is 16 bits, or two bytes. There is a limitation on how many calls programs can do. The stack should be limited to a maximum of 16 entries. This means that after 16 calls to subroutines without a return we should error out with a stack overflow.

The fonts

A Chip8 interpreter must provide fonts. These are just sprites like any other sprite and they only range from 0 to F, meaning 16 characters, or “0123456789ABCDEF”. Games usually come with their own font and do not use these. At startup the interpreter copies the font sprites in memory at some arbitrary location. Chip8 has one opcode to point the index register at the location of any character, so the interpreter can put these sprites anywhere in memory. This is where the first 512 bytes of memory come in handy.

End of the introduction

So this is the system in a nutshell. I prefer to split things up into different focused posts to avoid having a gigantic article so in the next articles I will explain the steps required to create the emulator, and how to debug it. Stay tuned!

Unique opportunity! Help a fellow grow his blog!

Hi there! If you’ve read this far maybe you think this was useful, or fun, or I don’t know what but for some reason You Got Here! Great! Please consider sharing this post with your network, I am trying to get The Code Butchery to grow so I can provide more content like this, will you help me in my journey? Thank you!

Series NavigationWrite a Chip8 retro gaming emulator in one day. Loading the first ROM. >>
Advertisements
Share this

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.