1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
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`.
|