Tracing

Ever dreamed of being a wizard? Well, this won’t give you magical powers, but let’s see how emulators can be used to control time!

First, make sure to focus the debugger window. Let’s first explain the debugger’s layout: Top-left is the code viewer, bottom-left is the data viewer, top-right are some registers (as we saw in the registers lesson), and bottom-right is the stack viewer. What’s the stack? We will answer that question a bit later… in Part Ⅱ 😅

Setup

For now, let’s focus on the code viewer. If you focus the debugger while the emulator is running, it will pause, as indicated by the screen window’s title changing to bgb (debugging).

Okay, but what’s with this weird syntax? Well, there are several syntaxes for Game Boy assembly, and BGB doesn’t use RGBDS’ by default. We can fix that in the options, which we can access by either:

  • Right-clicking the screen and selecting “Options”
  • In the debugger, open the “Window” menu, and select “Options”
  • Press F11 while focusing either the screen or debugger

BGB has a ton of options, but don’t worry, it’s got good defaults, so we don’t need to look at most of them for now. Select the “Debug” tab, and set “Disasm syntax” to “rgbds”. Oh, and check the “Local symbols” box, too. Now, click “OK” to apply the options.

Screenshot of the options window

You can also customize a lot of key bindings in the options, but I will stick to the default ones for this tutorial for the sake of simplicity.

Alright, great! But where are the labels? Well, as we have seen a couple of lessons ago, labels are merely a convenience provided by RGBASM, but they are not part of the ROM itself. It is very much inconvenient to debug without them, and so sym files (for “symbols”) have been developed. Let’s run RGBLINK to generate a sym file for our ROM:

rgblink -n hello-world.sym hello-world.o

‼️

The file names matter! When looking for a ROM’s sym file, BGB takes the ROM’s file name, strips the extension (here, .gb), replaces it with .sym, and looks for a file in the same directory with that name.

Then, in the debugger, we can go in the “File” menu and select “reload SYM file”.

Screenshot of the debugger showing the labels in the code viewer

Much better!

🔍

If a sym file is loaded, pressing Tab allows toggling whether labels are displayed or not.

Stepping

When pausing execution, the debugger will automatically focus on the instruction the CPU is about to execute, as indicated by the line highlighted in blue. Screenshot of the debugger showing that the highlighted line corresponds to PC

ℹ️

The instruction highlighted in blue is always what the CPU is about to execute, not what it just executed. Keep this in mind.

If we want to watch execution from the beginning, we need to reset the emulator. Go into the debugger’s “Run” menu, and select “Reset”, or tap your numpad’s * key.

The blue line should automatically move to address $01001, and now we’re ready to trace! All the commands for that are in the “Run” menu.

  • “Run” simply unpauses the emulator. Clicking on the screen also does the same.
  • “Trace” (more commonly known as “Step Into”) and “Step Over” advance the emulator by one instruction. They only really differ on the call instruction and interrupts, neither of which we are using here, so we will use “Trace”.
  • The other options are not relevant for now.

We will have to “Trace” a bunch of times, so it’s a good idea to use the key shortcut. If we press F7 once, the jp EntryPoint is executed. And if we press it a few more times, can see the instructions being executed, one by one!

Now, you may notice the WaitVBlank loop runs a lot of times, but what we are interested in is the CopyTiles loop. We can easily skip over it in several ways; this time, we will use a breakpoint. We will place the breakpoint on the ld de, Tiles at 00:0162; either double-click on that line, or select it and press F2. The line will turn red:

Debugger screenshot showcasing the breakpoint

Then you can resume execution either by clicking the screen or pressing F9, and BGB will automatically pause. Whenever BGB is running, and the (emulated) CPU is about to execute an instruction a breakpoint was placed on, it automatically pauses.

Debugger screenshot showcasing execution paused on the breakpoint

You can see where execution is being paused both from the green arrow and the value of PC.

If we trace the next three instructions, we can see the three arguments to the CopyTiles loop getting loaded into registers.

The state of some registers at the beginning of the CopyTiles loop

For fun, let’s watch the tiles as they’re being copied. For that, obviously, we will use the data viewer, and position it at the destination. As we can see from the image above, that would be $9000!

Select the data viewer (either click somewhere in it, or use Ctrl+Tab to switch focus, as indicated by the grey bar on the left), and press Ctrl+G (for “Goto”). In the popup, type the address you wish to go to, in our case 9000 (sans dollar sign!!).

Awesome, right?

What next?

Congrats, you have just learned how to use a debugger! We have only scratched the surface, though; we will use more of BGB’s tools to illustrate the next parts. Don’t worry, from here on, lessons will go with a lot more images—you’ve made it through the hardest part!


1

Why does execution start at $0100? That’s because it’s where the boot ROM hands off control to our game once it’s done.