5 Debugging using printf
voloved edited this page 2022-12-26 13:07:44 -05:00

When programming a common tool to debug is to log strings to a terminal / log file. On a GBA we don't necessarily have that ability, but many emulators will implement extensions that allow us to write to a log from within our running game. Please note that those debugging extensions are only valid for the respective emulator and will not work on other ones or real hardware. In fact they might break on other guest devices, therefore make sure to only use debugging when developing something and turn it off for productive builds.

The code for talking to the debug loggers is already included in pokeemerald since 9b6b164aad.

1. Enabling external Debugging

Go to include/config.h and comment #define NDEBUG:

-#define NDEBUG
+// #define NDEBUG

Make sure to remove the comment when you want to build without logging enabled, e.g. in a productive environment. Debug logs only work on the respective target devices and are potential hard hits on your game's performance if you do them a lot.

2. Print something

Wherever you want to use the debug log use the following syntax:

DebugPrintf(str, ...);

Like you would use printf from the C standard library. View man 3 printf or find a ressource online to see a list of format arguments you can provide and what they do, e.g.:

u32 a = 42;
DebugPrintf("a = %d. But also a = 0x%x", a, a);

should print the following string to the log: a = 42. But also a = 0x2a, since %d, %x can be used to print unsigned decimal / hexadecimal integers respectively.

Additionally if you are using the default configuration, a custom format option %S is added, which will print strings from the game, e.g.:

DebugPrintf("%S", gSpeciesNames[SPECIES_BULBASAUR]);

should print the following string to the log: BULBASAUR.

3. Assertions

This implementation supports 2 versions of Assertions.

  • AGB_ASSERT(expression) will print an error to the log if expression is violated. It will then crash the game.
  • AGB_WARNING(expression) will print a warning to the log if expression is violated. It will then continue to gracefully operate the program.

4. Viewing the logs

Since AGBPrintf is not widely supported by emulators it is recommended to use mGBA. The default configuration will use the mGBA handler for printing to the log.

In order to view our logs, we'll need to use the mGBA emulator. Open the log viewer by going to the "Tools" menu and selecting "View Logs...". Make sure the log level checkboxes for INFO, WARNING, ERROR are checked and run your game until it hits a DebugPrintf statement.

On newer versions of mgba you may want to disable some of the verbose logging to actually see your output over the rest of the log spam. Go to Tools->Settings->Logging and disable whatever is spamming your log:

image

5. Configuration

Apart from enabling debugging you can also change the LOG_HANDLER and the PRETTY_PRINT_HANDLER. See the comments in include/config.h. Note that when using LIBC as your PRETTY_PRINT_HANDLER it was discovered that the devkitPro libc does not link well against it and it does not support the %S format extension.

Screenshots from Someone Who Followed This Tutorial.

After following this tutorial, the biggest challenge found was setting up mGBA's logger correctly (either it's unintuitive or I'm dumb). Below are screenshots of how it's set up on my machine.
My mGBA version is 0.10.0. I set it up so it'll log in with the error flags.

Example of DebugPrintf being used in a file. print statement

Output of the logger and its setup:
setting1 setting2 setting3