Adventures in Retro Game Programming

During my first co-op term, I found myself with a few idle days during a long weekend. After the intense work load of my first study term, I was still readjusting to the notion of having spare time at all. It’s been great to have a chance to relax and decompress, but I still enjoy my spare time the most when I am creating something.
Having a lifelong fascination with console emulation, and some newly strengthened programming skills, I decided that it would be a fun experiment to try to make my own emulator. I figured the Game Boy would be a good place to start, as it has a simple architecture, and there are lots of resources available due to its popularity.
I realized, however, that it might be a good idea to attempt to write some software for the system first. This would allow me to get a feel for what the system is capable of, and how game software interacts with it. Having never written any assembly code before, I felt this would be a great way to start.
The first document I came across was the Game Boy Programming Manual. Having access to a document like this is invaluable when attempting to write software for such a specific architecture. Unlike writing software with modern programming languages, coding in assembly requires an intimate understanding of the hardware architecture. Each line of code involves interacting directly with CPU registers and memory addresses.
The programming manual took a surprisingly short amount of time to read. Fascinatingly there was a section on “content guidelines”. Informing developers that the content of their games will be held to what I would call a standard of “family friendliness”. We are all aware that this is a practice that Nintendo continues to this day, albeit perhaps to a lesser extent than in the past. It was interesting to see the innocence of the games I played as a kid described in deliberate terms on paper in such a way.

First page of the reference on the Game Boy’s CPU instruction set

After skimming my way through the instruction set reference, I more or less found myself at the end of what I would consider to be pertinent programming information. I was thinking, “that’s it?” as I felt although I understood the fundamentals of how to put software together for this thing, there was still a lot of steps between that and actually having some functional software running on the system.
I was then reminded of my ECE150 class, when we covered the “fundamental theory of programming.” This theory states, to paraphrase, that as long as you can do simple arithmetic, logical comparisons, and loops, you can write any software. That was essentially where I was at- I had the building blocks in hand, and all I had to do was build the structure.
Some tools would be necessary of course, as I still had no way to actually assemble my code into binaries, or to test and debug. I knew that writing homebrew software for the Game Boy was a road well travelled, so I was sure I would be able to find some resources on getting started.
A quick google search led me to this tutorial, which was extremely helpful in getting a development environment going, as well as some example code for my first piece of software. Along with the example code was included a quite comprehensive header file(hardware.inc) that included a lot of vital definitions that would make developing this software much easier.
The GB ASM tutorial covers important fundamentals in a really accessible way, and I would highly recommend it for anyone interested in getting into writing software for the Game Boy.
The setup process was fairly painless. It would have been even easier if I were on a machine running Linux or macOS, as some of the tools do not run natively on Windows. I chose to stick to my Windows installation regardless however, as I was interested in trying out the WSL. Once I had my WSL installation up and running, all I had to do was install RGBDS, which I would be using for an assembler, linker, and some other tools as well. I will also note that RGBDS has excellent documentation, not just on their own assembler syntax but on the Game Boy CPU instruction set as well. I eventually ended up favouring this reference over the programming manual I started with.
I decided to use VSCode as my text editor, as I was able to install the Retro Assembler extension for context highlighting. I could also run the session under WSL so I could write my assembling and linking commands into the build task rather than having to run them from the command line every time.
After getting my tools set up, I was able to assemble the provided example code: a classic “hello world”, with a twist.

Freshly Built “hello world” example code, courtesy of the GB ASM tutorial

Once I had this going, I knew I was ready to start messing around. The tutorial contained a great explanation of how tiles were loaded into VRAM at the beginning of the program. I still felt I didn’t fully understand how the tiles would be mapped to the actual display area, but that would come later.
I remembered when reading the programming manual that there is a specific register for the LCD scrolling.

In short, the Game Boy’s actual display area is larger than the viewing area displayed on the LCD. So the first thing I wanted to try was to just make the screen scroll in one direction indefinitely. Since the 8-bit register containing the scroll value would simply overflow, the viewing area would wrap around as we exceeded the maximum scroll values.
Coming from writing lots of code for Atmega and other embedded microcontrollers, I was already familiar with the concept of interrupts and registers, and knew that interrupts were a powerful way to get the CPU to do what I want. Setting up interrupts on these more modern CPUs can be somewhat complicated to understand for a beginner, as they are quite feature rich and there are a lot of options to set in order to get things working correctly.
In comparison, on the Game Boy, setup and use of interrupts is painfully easy. The CPU generates an interrupt for every vertical blanking interval(vblank), button press, and timer overflow. Excluding the timer overflow, you simply have to put code at a specific memory address, and provided that interrupts are enabled, you can be sure that the CPU will jump to that code each time that interrupt is triggered. For the timer overflow, setup requires a few extra steps, but it is still very simple.
Therefore, I figured for my little scroll experiment, the easiest way to get a constantly scrolling background would be to simply increment the SCX(x scroll value) register each time a vblank interrupt occurs. The speed at which it scrolls could be determined by how much the register is incremented by on each interrupt.

Hello world happily scrolling across the screen.

This is, of course, a long ways from having any sort of functional game or software running on the device, but I did learn a lot in the process about writing assembly code for the game boy, and what efforts go into such a process.
From this point on, I did manage to draw my own sprite, load it into the object memory, and shift it around the screen using inputs from the directional pad. That process deserves its own article in itself however, so stay tuned for a future article covering that process.

Previous
Previous

Breadboard Z80 Computer

Next
Next

Machining custom Acme screws to fix a lathe chuck