blog-static/content/blog/02_learning_emulation.md

73 lines
3.9 KiB
Markdown

---
title: Learning Emulation, Part 2
date: 2016-11-23 23:23:18.664038
tags: ["C", "Emulation"]
---
_This is the second post in a series I'm writing about Chip-8 emulation. If you want to see the first one, head [here]({{< relref "/blog/01_learning_emulation.md" >}})._
Now that we have an understanding of the physical capabilities of a Chip-8 system, we can write code that will represent such a system on our computer. In this post we'll start writing some basic code - be prepared.
### A Simple Representation
We'll start with the memory. Chip-8 has, as we remember, 4096 memory locations, all of which are bytes. We will create an array of 4096 bytes to match that.
```
unsigned char memory[4096];
```
If we have instructions in memory, we also need what's called a program counter, a variable that points to the next instruction in memory we have to execute. This variable would never need to be negative, and hold a value of up to 4095. The type we use for the program counter would thus have to be bigger than a `char` (max unsigned value of 256). The next biggest type we can have would be a `short`.
```
unsigned short int pc;
```
Next up, the registers. They all hold an 8-bit value, which is always positive. We can represent them with a 16-long array.
```
unsigned char v[16];
```
_Note: I used `v` for the variable name as the registers are named `V0`-`VF`_ in the Chip-8 specs.
We also need to create the `I` register. As it's used to handle memory locations, it needs to be able to hold values up to 4095, just like the program counter. So we write it as a short integer.
```
unsigned short int i;
```
Now, the stack. The stack is, unsurprisingly, a [stack datastructure](https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29). According to the Wiki page on Chip-8,
> modern implementations [of the stack] normally have at least 16 levels
Because of that, we're going to represent the stack as a 16-long array of short integers. These integers will represent locations in memory at which a jump was made to a subroutine. If this sounds confusing, it'll be explained when we implement it. Additionally, we'd need a stack pointer, which holds a number up to 15 and gives the index in the stack of the latest value that was added.
```
unsigned short int stack[16];
unsigned char stackp;
```
We're almost there. We now need to add the timers. I do not remember seeing the size of these timers on the Wiki, so we'll represent them with generous integers.
```
unsigned int delay_timer;
unsigned int sound_timer;
```
Finally, we need a variable to hold the display pixels (which are true or false values). My code is in C, and C did not have a primitive boolean type out of the box unti C99. Because I'm mildly crazy, I will avoid this new feature and use, instead, a char. If your language of choice supports booleans (and / or you don't exhibit compulsive behaviors), by all means use them. Anyway, since the display is 64x32, we can make a display variable like this:
```
unsigned char display[64 * 32];
```
If we were to use booleans, this might look something like:
```
bool display[64 * 32];
```
Those are all the variables that we have to keep track of!
Let's group them under a single chip `struct`.
```
struct chip_s {
unsigned char memory[4096];
unsigned short int pc;
unsigned char v[16];
unsigned short int i;
unsigned short int stack[16];
unsigned char stackp;
unsigned int delay_timer;
unsigned int sound_timer;
unsigned char display[32 * 64];
};
```
Since this is C, if we were to just use a `struct` we'd have to use the `struct` keyword every time. To avoid doing that, I'll use a `typedef` to define a `chip_t` type:
```
typedef struct chip_s chip_t;
```
That's it for today! By the end of this post you should have a data type representing a simple Chip-8 machine. I think the next two posts will be independent of each other: one for basic rendering with GLFW, and one for actual Chip-8 code.