I mentioned this already in another thread, but if you are interested in emulating hardware or just how CPUs and hardware work in general, writing a Game Boy emulator is about the most fun and educational project you can take.
The Game Boy hardware is, on its surface, extremely simple (as an example, there is no “operating system”, only a 256 byte (!) boot ROM that pretty much only serves to display and validate the Nintendo logo shown at start), and it has a vast library of games available for it that make use of that hardware to varying degrees.
This means that you can get really good results really fast. Especially the earlier games, like Tetris, don’t rely on fine grained implementation details too much, so even a sloppy, quickly put together emulation can run them well.
But if you then strive for accuracy or just being able to run more complex games, you can take things to almost arbitrarily detailed levels of this somewhat “fractal” complexity, uncovering and implementing all sorts of interesting hardware intricacies.
Contrast this with even slightly more recent game consoles, where you will have a lot of busywork ahead of you to even get the system past any reasonable definition of “booting”, without any gratifying visual feedback. With the Game Boy on the other hand, getting to a game’s title screen, with working buttons and all, is actually pretty simple.
I actually started C programming on Game Boy back in the days, but for me the Game Boy Advance really hit the sweet spot. ARM (nicer instruction set) and all of the close-to-the-metal characteristics you name above.
If you want to write a complete emulator, I can imagine that the Game Boy Advance can be a bit more of an undertaking with the different alternative graphics modes.
So, how does one guy not familiar with this low level stuff, nor with GB internals or those 8-bit processors starts writing an emulator like this? Is there any suggested road one could follow, or something like that?
> I also had plans to port to Mac OS X, but like with PS2, this proved too difficult since I was unable to install a working C compiler and development environment on Mac OS X.
I am surprised by this statement, as it's generally as easy as xcode-select --install to install the CLT (or failing that, installing full-blown Xcode). Slightly up in the article there is mention of Lion, so maybe this is related.
While this is true, I have a few major gripes with the toolchain that comes with XCode. For instance, I was recently working on a project using C++17 features. It works correctly on linux and windows, but making it compile on macOS was nigh impossible. The clang compiler that comes bundled with macOS has a "special" version that makes it very hard to know where exactly it stands compared to the normal LLVM repository.
Then there's the problem of libraries. You have to use homebrew or whatever to install libraries in /usr/local. Some libraries would conflict with the system though, so you have to fiddle with env variables to make the build system find it.
Overall, building on MacOS/Xcode is a frustrating experience. I ended up installing nixos and using its toolchain for my work...
I've been developing a Game Boy emulator with a friend as well, and struggling a lot with the poor documentation. There's a very thorough PDF with lots of information online but when it comes to Opcodes (and cpu flags) it's quite inaccurate. Most often than not I have to skim through several github projects to check that the implementations match. (which sometimes don't)
Perhaps we'll start doing a Nintendo64 emulator instead which is more complex but from what I've heard/read has much better documentation.
I've been doing the same thing, with the same .pdf, and hitting the same errors :)
http://gbdev.gg8.se/wiki/articles/Main_Page is my current documentation of choice - which seems to be based on the same .pdf but has a bunch of updates and errors corrected
The table here: [1] is very accurate. I wasn't able to find any bug either in the cycle counts or the affected flags list during the Coffee GB [2] development.
That can easily be part of the fun (and learning aspect), though: The detective work in researching what the real system does, based on analysis of a real system (if you have one) or just derived from what available software titles do and expect.
Some documentation is good to get you started, but at a certain point it’s the actual software that should be the guiding factor. Inaccurate documentation, which is not uncommon for the Game Boy, can be unnecessarily misleading though (on the other hand, there’s some satisfaction in essentially proving a different behavior, especially if you accept a piece of documentation to be likely inaccurate from the get go).
This would make a great undergraduate computer science class. I particularly like where author is somewhat forced by circumstances to fashion their own bespoke tooling. Rapid prototyping of minimal tools is a very real-world developer skillset.
If you are interested in this post, you might want to have a look at an older post on hackernews that gained some traction back then (see https://news.ycombinator.com/item?id=17134668). In contrast to this post, the aforementioned emulator was written in Java instead of C.
This is one of the more unique aspects of my emulator; since most other Game Boy emulators were written in an older C standard, (or an undesirable alternative like C++), they didn't have access to anonymous structs or unions
...unless you use MSVC, which has had that as an extension for a very long time (since MSVC6 at least.) I wonder if MS was the one who got that into C11.
You got to be kidding! The MSVC impl is a incompatible incomplete joke and everyone knows it. Even MS is investing more and more in llvm tooling because of this.
Honestly, writing a Game Boy emulator was the most instructive project I ever did on how computers work. Probably learned more on that project than from my OS and embedded systems classes combined.
It's less that other letters are reserved, and more that there are only eight general-purpose registers, and four of them already have special meanings.
A is the accumulator, F is flags, and as the sibling comment mentioned, H and L represent the high and low bytes of HL, which is the only 16-bit register you can use for indirect memory access in most instructions. It's also used in some control-flow instructions.
That leaves four remaining registers, which just so happen to fit perfectly into the remaining space: B, C, D, and E. (They can also be accessed as BC and DE with 16-bit instructions.)
The H and L registers are special in that they can be used for indirect addressing: some opcodes will combine H (high) and L (low) into a 16-bit number, interpret that as an address and read from that memory location.
> I used C11's anonymous structs and unions so that I could access individual registers, or grouped registers straight from the root structure: registers.a or registers.af for example.
That's excellent, when I wrote mine I wasn't aware of this feature and used a kludge of macros to handle it instead.
A usefull shortcut not highlighted in the article: Instead of implenting an emulator for the LCD display hardware, the author simply peaked at the frambuffer and dumped the contents.
For most target hardware, this shortcut provides a reasonable approximation of the intended output image. However, some older hardware relied upon specific characteristics of CRT displays to enhance the graphics. For example, some clever developers found that they could create extra colors by swapping the palate during the vertical blanking interval on interlaced NTSC video.
Of course, some of the earliest video game consoles don’t have a framebuffer since RAM was to expensive. For these consoles, you will be stuck writing a video display emulator.
[+] [-] anyfoo|7 years ago|reply
The Game Boy hardware is, on its surface, extremely simple (as an example, there is no “operating system”, only a 256 byte (!) boot ROM that pretty much only serves to display and validate the Nintendo logo shown at start), and it has a vast library of games available for it that make use of that hardware to varying degrees.
This means that you can get really good results really fast. Especially the earlier games, like Tetris, don’t rely on fine grained implementation details too much, so even a sloppy, quickly put together emulation can run them well.
But if you then strive for accuracy or just being able to run more complex games, you can take things to almost arbitrarily detailed levels of this somewhat “fractal” complexity, uncovering and implementing all sorts of interesting hardware intricacies.
Contrast this with even slightly more recent game consoles, where you will have a lot of busywork ahead of you to even get the system past any reasonable definition of “booting”, without any gratifying visual feedback. With the Game Boy on the other hand, getting to a game’s title screen, with working buttons and all, is actually pretty simple.
[+] [-] Legogris|7 years ago|reply
If you want to write a complete emulator, I can imagine that the Game Boy Advance can be a bit more of an undertaking with the different alternative graphics modes.
[+] [-] severino|7 years ago|reply
[+] [-] lloeki|7 years ago|reply
I am surprised by this statement, as it's generally as easy as xcode-select --install to install the CLT (or failing that, installing full-blown Xcode). Slightly up in the article there is mention of Lion, so maybe this is related.
[+] [-] roblabla|7 years ago|reply
Then there's the problem of libraries. You have to use homebrew or whatever to install libraries in /usr/local. Some libraries would conflict with the system though, so you have to fiddle with env variables to make the build system find it.
Overall, building on MacOS/Xcode is a frustrating experience. I ended up installing nixos and using its toolchain for my work...
[+] [-] unknown|7 years ago|reply
[deleted]
[+] [-] unknown|7 years ago|reply
[deleted]
[+] [-] jagger27|7 years ago|reply
[+] [-] the_spacebyte|7 years ago|reply
Perhaps we'll start doing a Nintendo64 emulator instead which is more complex but from what I've heard/read has much better documentation.
[+] [-] Shish2k|7 years ago|reply
http://gbdev.gg8.se/wiki/articles/Main_Page is my current documentation of choice - which seems to be based on the same .pdf but has a bunch of updates and errors corrected
[+] [-] t0mek|7 years ago|reply
[1] http://pastraiser.com/cpu/gameboy/gameboy_opcodes.html
[2] https://news.ycombinator.com/item?id=17134668
[+] [-] anyfoo|7 years ago|reply
Some documentation is good to get you started, but at a certain point it’s the actual software that should be the guiding factor. Inaccurate documentation, which is not uncommon for the Game Boy, can be unnecessarily misleading though (on the other hand, there’s some satisfaction in essentially proving a different behavior, especially if you accept a piece of documentation to be likely inaccurate from the get go).
[+] [-] FreeFull|7 years ago|reply
[+] [-] juliangoldsmith|7 years ago|reply
[0]: http://problemkaputt.de/pandocs.htm#cpuinstructionset
[+] [-] Sephiroth87|7 years ago|reply
https://gekkio.fi
[+] [-] zerr|7 years ago|reply
[+] [-] ArtWomb|7 years ago|reply
[+] [-] bandwitch|7 years ago|reply
[+] [-] userbinator|7 years ago|reply
...unless you use MSVC, which has had that as an extension for a very long time (since MSVC6 at least.) I wonder if MS was the one who got that into C11.
[+] [-] xmkfkg|7 years ago|reply
[+] [-] tnecniv|7 years ago|reply
[+] [-] samfriedman|7 years ago|reply
Why these letters? I'm assuming I, J and K are reserved for specific uses... is G likewise?
[+] [-] mhink|7 years ago|reply
A is the accumulator, F is flags, and as the sibling comment mentioned, H and L represent the high and low bytes of HL, which is the only 16-bit register you can use for indirect memory access in most instructions. It's also used in some control-flow instructions.
That leaves four remaining registers, which just so happen to fit perfectly into the remaining space: B, C, D, and E. (They can also be accessed as BC and DE with 16-bit instructions.)
[+] [-] bendmorris|7 years ago|reply
[+] [-] sk1pper|7 years ago|reply
That's excellent, when I wrote mine I wasn't aware of this feature and used a kludge of macros to handle it instead.
[+] [-] bmurray7jhu|7 years ago|reply
For most target hardware, this shortcut provides a reasonable approximation of the intended output image. However, some older hardware relied upon specific characteristics of CRT displays to enhance the graphics. For example, some clever developers found that they could create extra colors by swapping the palate during the vertical blanking interval on interlaced NTSC video.
Of course, some of the earliest video game consoles don’t have a framebuffer since RAM was to expensive. For these consoles, you will be stuck writing a video display emulator.
[+] [-] earenndil|7 years ago|reply
Just curious, why use anything except dolphin for emulating gamecube?
[+] [-] saredust|7 years ago|reply
[deleted]