Nicolas Electronics

Electronic projects and programming

CHIP-8 Emulator

Hey, it’s been a while since I posted something new here.

I’ve always wanted to try my hand at an emulator and didn’t want to start with something too difficult like a true retro console. I searched for something to emulate and found out about the CHIP-8.

It has 35 different instructions encoded in a 2 byte opcode, 16 one byte registers, 2 timers, a hexadecimal keypad, a memory of 4096 bytes where the program starts at address 0x200 and a screen with a resolution of 64 pixels by 32 rows. The display buffer starts at 0xF00 and ends at 0xFFF.

For more info on the CHIP-8, take a look at the wikipedia page and/or chip8.com.

The design of a simple emulator like the CHIP-8 is fairly easy.
– Initialize the emulator
– Read the ROM (aka CHIP-8 program)
– Read instruction
– Execute instruction
– Draw display buffer
– Read keys
– Loop back to read instruction

I’ve used the Gamma Engine Library by dridri as my graphics and timer library.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// pseudo-code
int main()
{
    CHIP8_struct myChip8;
    initCHIP8(&myChip8);
 
    readROM(&myChip8, ROMpath);
 
    while (1)
    {
        executeInstruction(&myChip8);
        drawBuffer(&myChip8);
        readKeys(&myChip8);
    }
 
    return 0;
}

Because there are only 35 instructions, my executeInstruction function is just a big switch checking the opcodes from the ROM and executing the appropriate branch.

Here’s a sneak peek at the switch:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    // Decode opcode
    switch (*opcode & 0xF000)
    {
        case 0x0000:
            switch (*opcode & 0x000F)
            {
                case 0x0000: // Clear Screen
                    memset(gfx, 0, CHIP8_GFX_SIZE);
                    ui_ClearWindow(pChip8);
                    *pc += 2;
                    break;
                case 0x000E: // Return
                    pChip8->pStack++;
                    *pc = (*(pChip8->pStack));
                    break;
            }
            break;
        case 0x1000: // Jump
            *pc = *opcode & 0x0FFF;
            break;
        case 0x2000: // Call
            *pChip8->pStack = *pc + 2;
            *pc = *opcode & 0x0FFF;
            pChip8->pStack--;
            break;
        // ...

I divided the emulator in 2 pieces, the cpu and the user interface. Because of this, a friend of mine has updated the code and added a libge-free solution using the windows API.
Use ui.libge.c if you want to try the Gamma Engine library or ui.wincli.c for the windows API.

Here’s the link to the github repo for those of you who are interested in the code : https://github.com/pyroesp/CHIP-8.

Here’s a quick printscreen of the emulator executing the program “Maze.ch8”.

CHIP-8 programs can be found at chip8.com.

Once you’ve compiled the emulator, open cmd, go to the folder containing the exe and type chip8.exe path_to_program.ch8.

Cheers.

– pyroesp

Leave a Reply

Your email address will not be published. Required fields are marked *

Please type the characters of this captcha image in the input box

Please type the characters of this captcha image in the input box