Writing a Chip8 emulator in C++ Part 5
One of the things I wanted to in this emulator was to show a startup message like “Ready” using the Chip 8 instructions. Nothing fancy, just print out the letters in the center (more or less) of the emulation screen. I would have to define the sprites for each of the letters to show on the screen, so that’s where I started:
|
|
I used 8x5 bitmaps to define all the letters, but used half width font (the upper nibble had the data, the lower nibble was all zeroes) to make the letters more compact. To prevent the spacing between the letters being too big as a result, I position each letter 5 pixels away by overwriting the blank right hand side of previous sprite. So, if X was 16 (decimal), the routine will first write 4 bits at 16, 17, 18, 19. For the next letter, it would change X to 16 + 5 = 21, which nicely also left 1 pixel space between each letter. And so on. Most of the heavy work is actually done by the DRAW instruction. I just had to ensure that the registers were setup correctly:
|
|
To begin with, I cleared the screen with the CLS command. Then the I register was set to point to 0x21a, which would be the start of the sprite data and immediately followed the above set of instructions. The address was easy enough to calculate: The instructions begin at 0x200, which is where all programs usually boot from. There are 13 instructions and since each instruction takes 2 bytes, that’s a total of 26 bytes, so any data must being at 0x21a.
I load the r4 register with 5, which will be used to offset the I register to point to the next set of sprite data (because each sprite has 5 bytes of data). I also set r1 to 1, to act as a sprite counter. The registers r2 and r3 are initialized to the X and Y co-ordinates to print to (18, 12 decimal respectively). These are used by the DRAW instruction to draw 5 bytes of data in the very next line.
Having drawn one character, I update r2 (the X co-ordinate) for the next character by moving right 5 pixels. I also update the I register to point to the next set of sprite data by adding r4 (which is set to 5) to it. I increment r1 (the sprite counter) by 1 for every character drawn. The SE instruction skips the next instruction if r1 = 6 (that is we have finished drawing 5 characters). If not, the next instruction is executed which is a JUMP instruction to 0x20C (the DRAW instruction address) and acts as a draw loop. However, if the SE instruction did skip this instruction, the emulator will land on the instruction below it which is a JUMP instruction to its own address thereby creating an infinite loop. If this is not done, the emulator will mindlessly continue to try to execute the following addresses but since there are no more valid instructions in our little program this will result in reading in garbage.
I stored the above in a character array to use as a boot ROM at startup, which would be uploaded to 0x200 just like any other ROM data :
|
|
And that’s it! This concludes most of what I had to say on the topic of Chip8 emulation. I had fun writing the emulator and while it seems all too easy at first glance, sometimes connecting the dots isn’t, which is why I thought I’ll pen this article to illustrate the steps I used in case it’s of use to someone just starting out own their own.
I didn’t talk about sound, input, openGL or the GUI system because that would have needlessly complicated the article as they deal with platform and non-Chip8 aspects of emulation and come with their own set of baggage and quirks. But for that there is the source code on the GitHub repository with all the source code. Feedback and comments are always welcome. Thanks for reading!