Skip to content

geaz/emu-gameboy

Repository files navigation

GGB - A Game Boy emulator written in C++

Compatibility

It is not intended to provide a full compatibility for all available cartridges or games. For example: I just did a naive bank switching implementation without ROM handling. Just enought to run Blarggs CPU test rom.

This is a programming experience project and it does not aim to be a daily use emulator to play with. Use other great emulators for this purpose. For example:

Screenshots

GGB

Zelda Tetris Tennis
Zelda Tetris Tennis
Blargg CPU Test Blargg Instr Timing
cpu_instrs instr_timing

Aims

Primary aims were:

  • get a common understanding of emulation and the interaction of the components
  • learn a bit about sound programming by implementing the APU

Further more I wanted to get the CPU to do its work correctly, but I did not want to get it as accurate as possible. Thats why this emulator uses a rather simple cycle count method to keep the components in sync (Components syned after each instruction). Which should be enough for most cases. There are more accurate methods like described here.

I also tried to get the timer implementation to behave like the real hardware. Most of the behaviours described in The Cycle-Accurate Game Boy Docs are working, passing most of Mooneyes Timer Tests. In contrast to other implementations, I let the timer use the correct internal clock in memory to increase the TIMA and DIV.

Given it was my first time doing sound programming, the APU works quite well, but not perfect.

Controls

SPACE = Select
ENTER = Start
Z = B
X = A
DIRECTIONS = Arrow Keys

P = Pause/Play
N = Next instruction
D = Open Debugger

Opcode Generator

After I started this project I used this table to create my opcode classes. Pretty fast I was frustrated by this tedious task. Therefore I created a python script to automate it. The script genOpcodes.py, in the gen folder, scrapes the table and creates C++ classes by using the templates in the gen/templates folder. By using this script I got great frame classes to work in.

The top instruction_set class contains two maps including all the different opcodes.

WARNING:

The Pastraiser OpCode Table has a few bugs. 0xE2 and 0xF2 are only one byte long! The Carry Flag indicator for the Right Shifting operations seems to be wrong, too. CBxBit 16 Bit operations are only 12 cycles, not 16! Just use this more accurate table by izik1, if you need it!

instruction_set

Furthermore the script creates frame classes for all opcode groups.

gen-group

Instruction struct

The top instruction_set class contains two arrays. Including all opcodes.

typedef uint8_t (*OpcodeFunc)(Cpu*);
struct Instruction
{
    uint8_t length;                 // Byte Length of the Instruction
    char* mnemonic;                 // Mnemonic of the Instruction
    OpcodeFunc executeInterpreter;  // Function Pointer to execute interpreter mode for given opcode
};

Ressources

Releases

No releases published

Packages

 
 
 

Languages