Credits to Petuh for this tutorial, and for Lunos for finding an archived version. This feature and any updates should be directly pulled from Pyredrid's [mgba_printf](https://github.com/Pyredrid/pokeemerald/tree/mgba_printf) branch. This tutorial is slightly out-of-date. TODO: rewrite to be in line with the standards of other tutorials. As of now, this is (almost) identical to Petuh's original post. This is for having an mGBA Debug printf function. Note that calling printf takes a lot of cycles and **should NOT be included in release builds**. ## 1. Getting the printf and mgba Files First, download [this](https://cdn.discordapp.com/attachments/744575017051881492/744961612200542288/mGBA_Debug_printf.zip). Place the .c files in `src/` and the .h files in `include/`. These files contain an implementation of printf and functions for communicating with mGBA. ## 2. Add the new files to the build. We need tell the linker about the new files we just added. Open `ld_script.txt`. Find the section that begins with `.text :`. At the end of this section, add the following: ```c src/mgba.o(.text); src/printf.o(.text); ``` Next find the section that begins with `.rodata :`. At the end of this section, add the following: ```c src/printf.o(.rodata); ``` ## 3. Initialize mGBA logging In order to print anything to the debugger, we need to first initialize it. Open `src/main.c`. At the top, add `#include "mgba.h"`. Then edit the starting function to start mGBA logging: ```diff void AgbMain() { ... ResetBgs(); SetDefaultFontsPointer(); + mgba_open(); InitHeap(gHeap, HEAP_SIZE); ... ``` ## 4. Add the ability to print ASCII strings In order to print human-readable strings, we need to add a utility function to `gflib/string_util.h`. Open this file and add the following declaration at the end (above the `#endif`). ```diff ... void ConvertInternationalString(u8 *s, u8 language); void StripExtCtrlCodes(u8 *str); +char *ConvertToAscii(const u8 *str); #endif // GUARD_STRING_UTIL_H ``` Now we need to add the implementation of `ConvertToAscii`. Open `gflib/string_util.c`. Add `#include "malloc.h"` to the top. Then, add the following C function to the end of the file: ```c char *ConvertToAscii(const u8 *str) { s32 i; char * textBuffer = malloc(128); for (i = 0; *str != EOS; i++, str++) { char modifiedCode = '?'; if (*str >= CHAR_a && *str <= CHAR_z) { modifiedCode = *str-(CHAR_a-'a'); // lower-case characters } else if (*str >= CHAR_A && *str <= CHAR_Z) { modifiedCode = *str-(CHAR_A-'A'); // upper-case characters } else if (*str >= CHAR_0 && *str <= CHAR_9) { modifiedCode = *str-(CHAR_0-'0'); // numbers } else if (*str == CHAR_SPACE) { modifiedCode = ' '; // space } else if (*str == CHAR_EXCL_MARK) { modifiedCode = '!'; // exclamation point } else if (*str == CHAR_QUESTION_MARK) { modifiedCode = '?'; // question mark } else if (*str == CHAR_PERIOD) { modifiedCode = '.'; // period } else if (*str == CHAR_DBL_QUOTE_LEFT || *str == CHAR_DBL_QUOTE_RIGHT) { modifiedCode = '"'; // double quote } else if (*str == CHAR_SGL_QUOTE_LEFT || *str == CHAR_SGL_QUOTE_RIGHT) { modifiedCode = '"'; // single quote } else if (*str == CHAR_CURRENCY) { modifiedCode = '$'; // currency mark (pokemonies in game, dollar sign in logs) } else if (*str == CHAR_COMMA) { modifiedCode = ','; // comma } else if (*str == CHAR_MULT_SIGN) { modifiedCode = '#'; // pound, hashtag, octothorpe, whatever } else if (*str == CHAR_SLASH) { modifiedCode = '/'; // slash } else if (*str == CHAR_LESS_THAN) { modifiedCode = '<'; // less than sign } else if (*str == CHAR_GREATER_THAN) { modifiedCode = '>'; // greater than sign } else if (*str == CHAR_PERCENT) { modifiedCode = '%'; // percentage } else if (*str == CHAR_LEFT_PAREN) { modifiedCode = '('; // opening parentheses } else if (*str == CHAR_RIGHT_PAREN) { modifiedCode = ')'; // closing parentheses } textBuffer[i] = modifiedCode; } textBuffer[i] = 0; return textBuffer; } ``` ## 5. Testing the code Printf is now functioning! Let's test it out. We'll add a print statement every time we encounter a wild pokemon. Open `wild_encounter.c`. You'll need to add the following include statements at the top. ```c #include "printf.h" #include "mgba.h" ``` **Note that you'll have to add those includes to any file you want to call `mgba_printf` from!** Now let's edit the function that's called whenever a wild Pokémon is encountered. At the end of that function, add the `mgba_printf` call as below: ```diff static void CreateWildMon(u16 species, u8 level) { ... + mgba_printf(MGBA_LOG_DEBUG, "%d", species); CreateMonWithNature(&gEnemyParty[0], species, level, 32, PickWildMonNature()); } ``` This will print out the species number for the wild Pokémon about to be encountered. This is already useful, but we can do even better. Let's modify our statement to print the species name as well. We'll add two more includes to the top of the file: ```c #include "data.h" // for gSpeciesNames, which maps species number to species name. #include "../gflib/string_util.h" // for ConvertToAscii() ``` **Note that any time you want to call `ConvertToAscii` you'll need to `#include "../gflib/string_util.h"`!** Now we'll change our `mgba_printf` call to the following: ```c mgba_printf(MGBA_LOG_DEBUG, "%d %s", species, ConvertToAscii(gSpeciesNames[species])); ``` ## 6. Viewing the logs In order to view our logs, we'll need to use the [mGBA](https://mgba.io/) emulator. Open the log viewer by going to the "Tools" menu and selecting "View Logs...". Make sure the "Debug" checkbox is checked and you should see a message like this one when you encounter a wild Pokémon: `[DEBUG] GBA Debug: 286 POOCHYENA`.