Hacker News new | comments | ask | show | jobs | submit login
Show HN: Simple Gameboy Emulator (github.com)
82 points by sacert on Dec 29, 2017 | hide | past | web | favorite | 23 comments

Making a Gameboy emulator was one of my favorite and most instructive personal projects.

It's worth noting that there was actual extra hardware built into the carts, so you need to implement certain features like extra RAM based on the cart ID in the ROM file.

Not the cart ID, you're looking in the cart header at byte 0147 for the actual hardware (MBC1, MBC2, MMM01, etc) functionality in conjunction with bytes 0148 (ROM size) and 0149 (RAM size) for specific bank sizing/mapping.

Yeah that's what I meant. It's been more than 5 years so I didn't remember the exact details. Thanks for the specifics!

I love projects like these. Code looks very clear and organized. How long have you been working on it?

In total I've spent roughly a month and a half working on it but mostly only spending an hour or so every couple days on it. After understanding the architecture, the coding isn't too difficult and is immensely rewarding!

I know nothing about emulators, so it would be nice if the README provided instructions for how to build and run the emulator.

Here is some inspiration: https://github.com/dolphin-emu/dolphin

You're right, I should've included that from the get-go. Included one now, hope it helps :)

For reference, I got it running on my Linux system with the following changes:

Change LDFLAGS: LDFLAGS=`pkg-config sdl2 --libs --cflags` -g -lm

In interrupt.c, change the two #import lines to #include.

Great! The CPU.c code is quite instructive since I'm writing a toy VM in my free time. Starring this :)

They're using a relatively simple opcode map, but most instructions are logically redundant as can be seen here:


The next step in emudev, with most compiled/systems languages at least, would be to create macros (such as OP_LD or OP_ADD) that generates static instructions at compilation. Another, cleanish method, in C is to generate a 256-length function pointer (void*) based static array and map those generated functions to that, to make the dispatch step simpler. Small trade off, performance-wise, but rarely matters for 8-bit CPU's (where you would usually use an opcode table over an instruction decoder).

For Z80 emulation the most efficient method I found was indeed a big nested switch-case statement. Compilers turn this into a jump table (or several if there are gaps), but don't need the function entry/exit boilerplate if each instruction code block would be its own C function referenced through a function-pointer-table. The switch-case code is generated with a python script which uses the 'algorithmic decoding approach' described here: http://z80.info/decoding.htm

Here's what such a code-generated instruction decoder looks like: https://github.com/floooh/chips/blob/master/chips/_z80_decod... (this is for a "real" Z80 with all undocumented opcodes, so it has a lot more cases to handle than the simple Gameboy Z80 variant).

C macros would just take the place of your python script. It's literally the exact same idea.

The Gameboy CPU shares the same octal-structured opcode format as the Z80 from which it was derived, so it is possible to decode it even more concisely: http://www.z80.info/decoding.htm

You can see that in octal, 1xx are all moves while 2xx is all ALU ops.

Oh, it's definitely decodable. Most CPU's can be (though x86 post-386 wouldn't be fun), since that's what they're usually doing internally. But, with 8-bit CPU's, the opcode space is usually limited to a byte, which makes tables very doable and very efficient.

My rust-based GB emulator uses a decoder based on those very docs, in fact. Though, modified slightly since the GB's CPU only supports the CB-extended range operations.

A very nice idea. I did one for this dcpu or something like that, from a potential game from Notch (Minecraft guy).

More people should do projects like these, because many many people enjoy looking at them and studying them and contribute to them :D.

It would be really cool if someone web-assemblied the best of class game system emulators and exposed them all through a uniform web interface. All vintage game consoles accessible through a single site!

I'm impressed! Very clean code. I had no idea a Game Boy emulator could be expressed so simply. Thanks for sharing this, sacert.

Nice. Please share if this or any other of your repos help(ed) with finding new gigs/clients.

I personally just code for self interest and enjoy a challenge since my job is rather stale. I can't speak from experience but I'm sure having a portfolio relevant to the type of work you're aiming for would impress potential clients and enhance corresponding skills.

I assure you having even a few hobby projects to show to potential employers is always beneficial. When you can talk about actual code you've written, often you don't even have to do any tests and the usual questions about the basics are skipped completely.

That hasn't ever been my experience. I love talking about code I've written, details of how it works, and so on. It has never gotten me out of coding tests.

what a lovely project - thank you for sharing

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact