Mikelan98, BagBoy, DavveDP (Translation)
Target games:
This tutorial will consist of two parts: one explaining and modifying the type effectiveness chart and another one covering the graphical insertion of the fairy type. Although they are not explicitly divided in the tutorial, it is recommended that one follows the parts (effectiveness table and fairy graphics) separately when performing the modification as to not get confused.
Before starting one must have a clear understanding of the following:
With this in mind it won’t be possible to expand the type effectiveness table (from here on out known as TET), and even if it was, the table is so large that it becomes very difficult to find space for it anyway. This means that we must devise a different strategy for adding our beloved fairy type.
A Fairy-type Clefairy in Pokemon Platinum.
What strategy will we use then? Well, one that works very well when working with large strings of binary data in the arm9 or overlays and reducing them is: reducing bytes to nibbles. It should be noted that this strategy is valid only when it is worthwhile in certain cases, that is, when this reduction is more practical than looking for blank spaces. As the effectiveness table is very large and we also want to expand it with quite a few bytes (In theory more than 30 bytes) this strategy is justifiable. Reducing bytes to nibbles frees up space because many hex numbers can be represented with only 1 nibble, leaving space for other data.
To be able to actually apply this strategy we need to know precisely when and how these pieces of data are read and all the routines involved. Therefore, tracing* is going to be of great use to us.
*Tracing basically means to follow all the reading from RAM/writting to RAM instructions for a specific memory address, in order to find the subroutines with these instructions
Firstly the TET consists of groups of 3 bytes known as “triplets” in the formation AA | DD | EE. Here the AA byte is the type-ID of the attacking type, DD the type-ID of the defending type, and the EE byte the effectiveness.
AA | DD | EE | |
---|---|---|---|
Definition: | Attacking type-ID | Defending type-ID | Effectiveness |
Values: | 00 = Normal
01 = Fighting 02 = Flying 03 = Poison 04 = Ground 05 = Rock 06 = Bug 07 = Ghost 08 = Steel 09 = ??? 0A = Fire 0B = Water 0C = Grass 0D = Electric 0E = Psychic 0F = Ice 10 = Dragon 11 = Dark |
00 = Normal
01 = Fighting 02 = Flying 03 = Poison 04 = Ground 05 = Rock 06 = Bug 07 = Ghost 08 = Steel 09 = ??? 0A = Fire 0B = Water 0C = Grass 0D = Electric 0E = Psychic 0F = Ice 10 = Dragon 11 = Dark |
00 = Immune
05 = Not-very-effective 0A = Neutral 14 = Super-effective |
The original routine used by the game to read the data in the TET is activated whenever a move is used in battle and works as follows:
For the actual implementation of the theory things get interesting. Starting with the TET, as previously mentioned we are going to use the strategy of reducing bytes to nibbles. However the only bytes that we can reduce are the effectiveness bytes (EE) since they can only have 4 different values assigned to them. Additionally all of the values in the EE bytes (see table above) are multiples of five (0, 5, 10 and 20) meaning that we can store them as 0, 1, 2 and 4 and multiply them before use by using an instruction. By storing them as a smaller value we are creating more free space. In practical terms we will be creating a smaller table below the TET containing only the EE bytes reduced to nibbles (divided by 5), the reason for this will be explained later.
Compressed effectiveness table. Notice the separation between the AA | DD values and the EE ones.
In the offsets 0x1A01A and 0x01A074 in overlay 16 are the lines of code that compare the attacking Pokemon's type-ID to the defending one in the TET, checks the EE value, and passes it on to damage calculation. Now what we are going to do is branch the code before it checks the EE value to some free space in the arm9 and tell it to fetch the EE value from the smaller table of nibbles we created.
Additionally, the graphical part of the Pokédex also needs an ASM touch-up in order for it to correctly display the fairy type. This is because the Pokédex also uses a table, albeit a different one, to determine which type to display. Each entry in that table points to a set of instructions that does the actual displaying of the type. By changing the instructions or repointing them to some other place in memory we can make it display whatever we want. Conveniently this table has two entries that display the ghost type which means we could easily use one of those for our own purposes.
If we head over to overlay 21 at offset 0xE40A we find two asm instructions that are, by all means, “obsolete”. They appear to be the remnants of a 32-bit to 16-bit variable conversion during compilation. Nonetheless these 4 “obsolete” bytes will serve as our own “fairy type branch”. By repointing one of the two aforementioned ghost type entries to these 4 bytes we can replace it with something else.
Firstly we will create our new set of tables by pasting the following in overlay 16:
Game Code | Table Offset | Table Data | Table Read 1 Offset | Table Read 1 Code | Table Read 2 Offset | Table Read 2 Code | |
![]() ![]() |
CPUE | 0x33B94 (Overlay 16) | 00 05 00 08 0A 0A 0A 0B 0A 0C 0A 0F 0A 06 0A 05 0A 10 0A 08 0B 0A 0B 0B 0B 0C 0B 04 0B 05 0B 10 0D 0B 0D 0D 0D 0C 0D 04 0D 02 0D 10 0C 0A 0C 0B 0C 0C 0C 03 0C 04 0C 02 0C 06 0C 05 0C 10 0C 08 0F 0B 0F 0C 0F 0F 0F 04 0F 02 0F 10 0F 08 0F 0A 01 00 01 0F 01 03 01 02 01 0E 01 06 01 05 01 11 01 08 03 0C 03 03 03 04 03 05 03 07 03 08 04 0A 04 0D 04 0C 04 03 04 02 04 06 04 05 04 08 02 0D 02 0C 02 01 02 06 02 05 02 08 0E 01 0E 03 0E 0E 0E 11 0E 08 06 0A 06 0C 06 01 06 03 06 02 06 0E 06 07 06 11 06 08 05 0A 05 0F 05 01 05 04 05 02 05 06 05 08 07 00 07 0E 07 11 07 08 07 07 10 10 10 08 11 01 11 0E 11 07 11 11 11 08 08 0A 08 0B 08 0D 08 0F 08 05 08 08 FE FE 00 07 01 07 10 09 01 09 06 09 11 09 03 09 08 09 09 10 09 01 09 11 09 08 09 0A 09 03 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 11 11 44 41 14 41 14 41 41 10 41 14 11 41 14 11 14 14 44 11 44 11 11 44 44 11 11 04 41 40 14 41 44 41 14 41 01 14 11 14 14 14 41 14 41 04 12 44 11 44 12 11 14 41 00 00 11 14 44 44 11 1F FF FF FF FF FF | 0x1A01A (Overlay 16) | C0 46 00 49 88 47 01 94 0F 02 C0 46 | 0x1A074 (Overlay 16) | 00 49 88 47 01 94 0F 02 C0 46 C0 46 |
---|
Now we have successfully redirected the game’s code to offset 0x020F9400, a small region of free space in RAM. There we will put our code that fetches the values from our newly-inserted table of EE values. The code to be pasted in offset 0xF9400 (since arm9.bin starts from offset 0x02000000) in arm9.bin is the following:
Game Code | Effectiveness Subroutine Offset | Effectiveness Subroutine Code | |
![]() ![]() |
CPUE | 0xF9400 (ARM9) | 01 90 38 B4 0C 4B D2 1A 52 08 86 24 64 00 1B 19 52 08 9B 5C 03 D2 F0 25 2B 40 1A 09 02 E0 0F 25 2B 40 1A 46 05 25 6A 43 75 46 06 35 AE 46 38 BC 28 46 39 46 01 49 08 47 D4 EC 26 02 3D B6 25 02 |
---|
Unfortunately all of these insertions still won’t work. This is because of the way the game checks the TET. Since we have turned all of our triplets into doubles we now have to change the “loop-code” to add +2 to the starting address after each iteration instead of the original +3. This is done by changing the following values at the following addresses in overlay 16:
Game Code | Offset 0x19FB6 | Offset 0x1A084 | Offset 0x1A766 | |
![]() ![]() |
CPUE | C046 | 6100 C046 | C046 |
---|
If one wishes to add extra relationships to the TET it can be done by removing the first set of pair of FF bytes, adding extra relationships, then appending the two FF bytes afterwards (see image above). The last relationship must be followed by two sets of FF bytes or else the game won’t stop reading. Additionally one must add nibbles for type effectiveness in the EE value table too by appending them to the table followed by FF.
Here’s an example of how to make the dark type hit for neutral damage on steel types:
First we must find the matching double in the TET for the attacking type-ID of dark and the defending type-ID of steel. By looking at the values in the first image of this tutorial we know that dark = 11 and steel = 08. Now we just have to find the following double: 11 08
AA | DD and EE values for Dark-type attack against Steel-type Pokemon in the compressed effectiveness table.
Now we look for the EE value that corresponds to this relationship. We do this by calculating how many doubles from the starting offset our relationship is. In our case 102. And then we the nibble in the EE value table 102 nibbles from the start of that table. Now we simply change the value of that nibble from 1 (not-very-effective) to 2 (neutral).
For making the pokedex display the type correctly we will be creating our own fairy branch, as mentioned earlier, in overlay 21 at offset 0xE40A, overwriting the aforementioned “obsolete” bytes. This can be done by inserting the following code at Offset 0xE408 of overlay 21:
Game Code | Pokedex Display Subroutine Offset | Pokedex Display Subroutine Code | |
![]() ![]() |
CPUE | 0xE408 (Overlay 21) | 49 88 8F 44 22 00 26 00 2A 00 2E 00 32 00 36 00 3A 00 3E 00 42 00 66 00 46 00 4A 00 4E 00 52 00 56 00 5A 00 5E 00 62 00 00 20 70 47 06 20 70 47 0E 20 70 47 0A 20 70 47 08 20 70 47 05 20 70 47 0B 20 70 47 07 20 70 47 09 20 70 47 01 20 70 47 03 20 70 47 02 20 70 47 04 20 70 47 0F 20 70 47 0D 20 70 47 10 20 70 47 0C 20 70 47 12 20 70 47 |
---|
Now we only need to make the graphical changes because without them the game will display the ??? or ghost-type. In order to do this we must first change the type icon and palette in addition to the palette of the move selection box. We will be using Tinke 0.9.2 and ConsoleTool for this section.
Palettes for in-battle move boxes.
Inserting the Fairy type icon with Tinke.
New move box for Fairy-type moves.
DF 7E 3F F2 1E 6A DD 59 5B CD 17 C1 D6 B4 3F FB |
Color data for Fairy-type move boxes.
If you are planning to use this research on your project, credits for Mikelan98 and BagBoy are needed. You can cite this research by copying the following reference in the credits section of your project's thread or webpage:
Mikelan98, BagBoy: Fairy Type in Pokemon Platinum (pokehacking.com/r/20071800) |
Total or partial reproduction of this research in other site is forbidden without prior authorization of the authors.