DoesntKnowHowToPlay
Tiny Umbrella with Lots and Lots of Good
- 265
- Posts
- 12
- Years
- Seen Feb 24, 2024
In this thread, I will explain how to expand the pokedex. You will need the following:
-A GBA emulator (or flashcart if you're crazy)
-An FR 1.0 English ROM
-JPAN's save block hack
-A hex editor
-A solid understanding of hacking concepts. I won't be teaching you how to use a hex editor, or how to repoint things. If you're qualified to do this, odds are all you really need is the offsets, which is pretty much all this post is.
Step 1: Get free RAM for the dex flags
The first obstacle to expanding the Pokedex is the need for flags to store what new Pokemon the player has seen/caught. To do this, we need free memory.
First things first, install JPAN's save block hack to your ROM. It can be found here: https://www.pokecommunity.com/posts/6993092/
You will need to also disable the LR Help menu- otherwise, if the player opens it, they will corrupt all the newly saved memory. Do this by placing 1D E0 at x13b8c2.
Now, before doing anything else, you should decide how many pokedex entries and how many pokemon you want. These don't have to be the same- it's entirely possible to map multiple pokemon to a single dex entry, or have unmapped pokemon- vanilla does just this with the limbo slots between Celebi and Treecko. Consider the limbo slots and Unown sprite slots- while slots 252-275 are actually quite safe to use, slots 412-439 store the sprites for eggs and every Unown form bar A. As such, if you use Unown, you will probably want to leave those alone.
Once you've decided, figure out how many bits it will take to encode the number of dex entries- the answer is (number of dex entries)/8, rounded up. Using this, pick two locations in the RAM freed by JPAN's hack to be where Seen and Caught flags will go. Note that later steps will be easier if you put them next to each other. Now:
Change x104B10 to point to new SEEN flags.
Change x104B00 to 00 00.
Change x104B02 to 00 00.
This makes the game read using the new SEEN flags.
Change x104B5C to point to new CAUGHT flags.
Change x104B16 to 00 00.
Change x104B18 to 00 00.
Change x104B1A to 00 00.
Change x104B26 to 16 E0.
This makes the game read using the new CAUGHT flags.
Change x104B34 to 0F E0.
This makes both of the above bypass redundant SEEN flags.
Test. At this point, if you start a new file, your pokedex should refuse to open- this is because the game is writing to the old flags but reading the new flags.
Change x104B94 to point to new SEEN flags.
Change x104B6A to 01 1C.
Change x104B6C to 00 00.
Change x104B78 to 1A E0.
This makes the game write to the new SEEN flags.
Change x104BB8 to point to new CAUGHT flags.
Change x104BA2 to 01 1C.
Change x104BA4 to 00 00.
This makes the game write to the new CAUGHT flags.
Again, test. Your dex should work normally now, but it works on the new memory. If you fiddle with Memory Viewer you should be able to watch the flags get set, and set them yourself.
It's worth noting that normally, there are 3 sets of Seen flags. Why there are three sets is a mystery, but if you don't want to use JPAN's save hack for this, you can rewrite the method the game uses to access the flags and repurpose the redundant ones. I won't be explaining how to do that, though- you'll have to figure it out and write the routine yourself.
We also need to make the game clear these flags properly when the player selects New Game at the main menu. We can do this with the following edits:
Put a pointer to whichever set of flags comes first at x549D0.
Put 20 1C 00 00 at x549b0.
Put XX 22 at x549b6, where XX is the number of bytes taken by your dex flags.
Put 20 1C at x549bc.
Put YY 30 at x549be, where YY is the number of bytes between the sets of flags. YY is probably the same as XX, but it doesn't have to be.
Put XX 22 at x549c2, where XX is the number of bytes taken by your dex flags.
Alternatively, instead of these byte changes, you can instead make an OW script that clears the dex with writebytetooffset, and make sure it runs before the player gets the pokedex. Your choice.
Step 2: Repoint goddamn everything
Fire up Notepad and get ready to write out some offsets, we'll be here a while.
Repoint and expand the Pokemon name table.
This begins at x245EE0 and is 11 bytes per entry.
In vanilla, it is x11B4 bytes long.
There should be 40 pointers to it.
Repoint and expand the base stat table.
This begins at x254784 and is 28 (x1C) bytes per entry.
In vanilla, it is x2D10 bytes long.
There should be 57 pointers to it.
There are two pointers to egg hatching time in the ROM that will need repointing.
They are to x254795, and should point to the 18th byte of base stat data.
Repoint and expand the level-up movepool table.
This begins at x25d7b4 and is 4 bytes per entry.
In vanilla, it is x670 bytes long.
There should be 6 pointers to it.
Test. If you put valid filler data in these tables, you should be able to get legit mons from the expanded slots and battle with them:
Place 00 00 00 00 00 00 (that's six 00s) at x41000.
This will cause the repointed name table to actually get used.
Repoint and expand the front sprite table.
This begins at x2350AC and is 8 bytes per entry.
To my knowledge, the latter four bytes are not used.
In vanilla, it is xDC0 bytes long.
There should be 28 pointers to it.
Repoint and expand the back sprite table.
This begins at x23654C and is 8 bytes per entry
To my knowledge, the latter four bytes are not used.
In vanilla, it is xDC0 bytes long.
tl;dr same as above.
There should be 10 pointers to it.
Put 07 E0 at xed72.
Put 07 E0 at xf1b6.
These will break the limiters preventing sprites from showing up.
Test. You should get valid sprites, but with broken palettes and position data:
Repoint and expand the pokemon palette table.
This begins at x23730C and is 8 bytes per entry.
Same as above, last four bytes unused, xDC0 total.
There should be 5 pointers to it.
Repoint and expand the shiny palette table.
This begins at x2380CC and is the same as the above.
There should be 3 pointers to it.
Put 04 E0 at x44104.
This breaks the limiter on the palette tables.
Test. You should have a reasonably colored extended mon now.
In fact, with a spare .ini, you can now add sprites using A-Series.
Repoint and expand the Player Y table.
This is at x235E6C, and is four bytes per mon.
Despite what Wichu's readme may have you believe, it's x6E0 bytes long.
There should be 8 pointers to it.
Repoint and expand the Enemy Y table.
This is at x2349cc, and is four bytes per mon.
It's also x6E0 bytes long.
There are 16 pointers to it, oddly enough.
Repoint and expand the Altitude table.
This is at x23A004, and is one byte per mon.
This time it's only x19C bytes long. Alt-Unowns don't have altitude.
Put 03 E0 at x7472e.
Put 03 E0 at x7465e.
Put 06 E0 at x74788.
These break limiters, allowing these tables to be read.
Test. I advise playing with A-Series again.
Repoint and expand the icon pointer table at x3D37A0.
Four bytes per mon. 6E0 bytes long.
Each icon uses one of three palettes.
This is controlled by the table at x3D3E80.
It's x1B8 bytes long. One byte per mon.
Put 00 00 at x96f90.
This should make the icon show up, but with the wrong palette.
Put 00 00 00 00 at x96e7a.
This fixes the palette reads for extended mons in the party menu.
Put 00 00 at x971da.
This will fix the palette reads for extended mons in the dex once we get there.
Once again, test.
Step 3: Dealing with dex entries
Repoint and extend the national pokedex order.
This is a list at x251fee that denotes what dex entries mons get.
The main use of this is to give the scattered Hoenn mons proper order.
It is x336 bytes long, 2 per entry.
Note that the limbo slots between Celebi and Treecko have entries on this table.
You don't have to worry about Kanto dex order- that's just the first 151 things in nat dex.
It'd be a good idea to fill this table out now instead of later. Make sure every dex page is tied to some mon.
Repoint and extend the pokedex entries.
These is at x44E850.
Each entry is 36 (x24) bytes long.
The table has 387 entries (one for 00, oddly enough), or x366C bytes.
Unlike most other data, this is in actual pokedex order.
Test, make sure your dex functions normally.
You shouldn't be able to view entries past the regular ones though.
At x1025ec, you'll find a byte. This byte times eight is the amount of memory allocated for the pokedex.
If you have less than 510 mons, replace the byte with 1/2 your dex length.
If you have less than 1020 mons, set it to 1/4 your dex length and put 40 01 at x1025EE.
If you have more than 1020 mons, you should probably rethink what you're doing since 4-digit numbers aren't going to get along with the FR interface unless you do adjustments outside the scope of this tutorial.
At x103920, put the number of dex entries you have minus one.
If this is more than what got malloc'd, the game will crash.
At x43220, put 00 00.
Your dex should now load the full length:
If it locks up, make sure every entry maps to something in dex ordering!
Step 4: Misc. repointing
Change x88ea4 to the number of dex entries minus one.
This fixes the dex count on the title screen & trainer card.
Change x104c28 to the number of dex entries minus one.
This fixes the dex count on the pokedex menu.
Repoint the TM compatability table.
This is at x252bc8. Each entry is 8 bytes.
The table as a whole is xCE0 bytes long.
Repoint the tutor compatability table.
This is at x459B80. Each entry is two bytes.
The table as a whole is x338 bytes long.
Repoint the evolution table.
This is at x259754. Each entry is 40 (x28) bytes.
The table as a whole is x4060 bytes.
Repoint the item animation table.
This is at x45FD50.
Each entry is 5 bytes long. Entire thing is x811 bytes.
Put 07 E0 at xec9a.
This fixes the evolution animation.
Put E0 at x97011.
This fixes the stamps on the back of the trainer card.
At your own leisure, add the new entries to the habitats list.
This list is at x452c4c. More information can be found here: https://www.pokecommunity.com/posts/6263014/
Add cries for the new mons. As you may know, cries after Celebi are handled unusually- the limbo slots are all hard-wired to Unown's cry (doubt this is hard to fix but lazy), while slots starting from Treecko use an auxilary table to find their cry. This table is at x2539D4- repoint and extend it.Note that you don't need to repoint the cry table itself- immediately after it is a second, unused copy of the cry table.
You do need to repoint the cry table. You also need to repoint the secondary cry table, which is right after it and contains the same pointers with different accompanying data- this is used by the move Growl and possibly others.
Put 01 1C 11 E0 at x720CA. This will enable cries past #511 to function.
Repoint the footprint table. It can be found at x43FAB0, and is on a per-mon basis instead of a per-entry basis.
As such, it is x674 bytes long.
To fix breeding, write the ID of your last slot with meaningful evolution data at x459EC (pick an odd number; it's okay to go higher as long as it's not past the number of mons you actually have)
Then, write half of one less than that at x459CC.
If that requires more than one byte, write a quarter of one less than that instead, and change the x40 at x459CE to an x80.
If you are also expanding the number of evolutions, change the x28s at x4598A and x4598E to the new size of the evolution struct.
Given how many things need to be fixed, I probably missed something! Please let me know if you stumble upon anything not mentioned here.
-A GBA emulator (or flashcart if you're crazy)
-An FR 1.0 English ROM
-JPAN's save block hack
-A hex editor
-A solid understanding of hacking concepts. I won't be teaching you how to use a hex editor, or how to repoint things. If you're qualified to do this, odds are all you really need is the offsets, which is pretty much all this post is.
Step 1: Get free RAM for the dex flags
Spoiler:
The first obstacle to expanding the Pokedex is the need for flags to store what new Pokemon the player has seen/caught. To do this, we need free memory.
First things first, install JPAN's save block hack to your ROM. It can be found here: https://www.pokecommunity.com/posts/6993092/
You will need to also disable the LR Help menu- otherwise, if the player opens it, they will corrupt all the newly saved memory. Do this by placing 1D E0 at x13b8c2.
Now, before doing anything else, you should decide how many pokedex entries and how many pokemon you want. These don't have to be the same- it's entirely possible to map multiple pokemon to a single dex entry, or have unmapped pokemon- vanilla does just this with the limbo slots between Celebi and Treecko. Consider the limbo slots and Unown sprite slots- while slots 252-275 are actually quite safe to use, slots 412-439 store the sprites for eggs and every Unown form bar A. As such, if you use Unown, you will probably want to leave those alone.
Once you've decided, figure out how many bits it will take to encode the number of dex entries- the answer is (number of dex entries)/8, rounded up. Using this, pick two locations in the RAM freed by JPAN's hack to be where Seen and Caught flags will go. Note that later steps will be easier if you put them next to each other. Now:
Change x104B10 to point to new SEEN flags.
Change x104B00 to 00 00.
Change x104B02 to 00 00.
This makes the game read using the new SEEN flags.
Change x104B5C to point to new CAUGHT flags.
Change x104B16 to 00 00.
Change x104B18 to 00 00.
Change x104B1A to 00 00.
Change x104B26 to 16 E0.
This makes the game read using the new CAUGHT flags.
Change x104B34 to 0F E0.
This makes both of the above bypass redundant SEEN flags.
Test. At this point, if you start a new file, your pokedex should refuse to open- this is because the game is writing to the old flags but reading the new flags.
Change x104B94 to point to new SEEN flags.
Change x104B6A to 01 1C.
Change x104B6C to 00 00.
Change x104B78 to 1A E0.
This makes the game write to the new SEEN flags.
Change x104BB8 to point to new CAUGHT flags.
Change x104BA2 to 01 1C.
Change x104BA4 to 00 00.
This makes the game write to the new CAUGHT flags.
Again, test. Your dex should work normally now, but it works on the new memory. If you fiddle with Memory Viewer you should be able to watch the flags get set, and set them yourself.
It's worth noting that normally, there are 3 sets of Seen flags. Why there are three sets is a mystery, but if you don't want to use JPAN's save hack for this, you can rewrite the method the game uses to access the flags and repurpose the redundant ones. I won't be explaining how to do that, though- you'll have to figure it out and write the routine yourself.
We also need to make the game clear these flags properly when the player selects New Game at the main menu. We can do this with the following edits:
Put a pointer to whichever set of flags comes first at x549D0.
Put 20 1C 00 00 at x549b0.
Put XX 22 at x549b6, where XX is the number of bytes taken by your dex flags.
Put 20 1C at x549bc.
Put YY 30 at x549be, where YY is the number of bytes between the sets of flags. YY is probably the same as XX, but it doesn't have to be.
Put XX 22 at x549c2, where XX is the number of bytes taken by your dex flags.
Alternatively, instead of these byte changes, you can instead make an OW script that clears the dex with writebytetooffset, and make sure it runs before the player gets the pokedex. Your choice.
Step 2: Repoint goddamn everything
Spoiler:
Fire up Notepad and get ready to write out some offsets, we'll be here a while.
Repoint and expand the Pokemon name table.
This begins at x245EE0 and is 11 bytes per entry.
In vanilla, it is x11B4 bytes long.
There should be 40 pointers to it.
Repoint and expand the base stat table.
This begins at x254784 and is 28 (x1C) bytes per entry.
In vanilla, it is x2D10 bytes long.
There should be 57 pointers to it.
There are two pointers to egg hatching time in the ROM that will need repointing.
They are to x254795, and should point to the 18th byte of base stat data.
Repoint and expand the level-up movepool table.
This begins at x25d7b4 and is 4 bytes per entry.
In vanilla, it is x670 bytes long.
There should be 6 pointers to it.
Test. If you put valid filler data in these tables, you should be able to get legit mons from the expanded slots and battle with them:
Place 00 00 00 00 00 00 (that's six 00s) at x41000.
This will cause the repointed name table to actually get used.
Repoint and expand the front sprite table.
This begins at x2350AC and is 8 bytes per entry.
To my knowledge, the latter four bytes are not used.
In vanilla, it is xDC0 bytes long.
There should be 28 pointers to it.
Repoint and expand the back sprite table.
This begins at x23654C and is 8 bytes per entry
To my knowledge, the latter four bytes are not used.
In vanilla, it is xDC0 bytes long.
tl;dr same as above.
There should be 10 pointers to it.
Put 07 E0 at xed72.
Put 07 E0 at xf1b6.
These will break the limiters preventing sprites from showing up.
Test. You should get valid sprites, but with broken palettes and position data:
Repoint and expand the pokemon palette table.
This begins at x23730C and is 8 bytes per entry.
Same as above, last four bytes unused, xDC0 total.
There should be 5 pointers to it.
Repoint and expand the shiny palette table.
This begins at x2380CC and is the same as the above.
There should be 3 pointers to it.
Put 04 E0 at x44104.
This breaks the limiter on the palette tables.
Test. You should have a reasonably colored extended mon now.
In fact, with a spare .ini, you can now add sprites using A-Series.
Repoint and expand the Player Y table.
This is at x235E6C, and is four bytes per mon.
Despite what Wichu's readme may have you believe, it's x6E0 bytes long.
There should be 8 pointers to it.
Repoint and expand the Enemy Y table.
This is at x2349cc, and is four bytes per mon.
It's also x6E0 bytes long.
There are 16 pointers to it, oddly enough.
Repoint and expand the Altitude table.
This is at x23A004, and is one byte per mon.
This time it's only x19C bytes long. Alt-Unowns don't have altitude.
Put 03 E0 at x7472e.
Put 03 E0 at x7465e.
Put 06 E0 at x74788.
These break limiters, allowing these tables to be read.
Test. I advise playing with A-Series again.
Repoint and expand the icon pointer table at x3D37A0.
Four bytes per mon. 6E0 bytes long.
Each icon uses one of three palettes.
This is controlled by the table at x3D3E80.
It's x1B8 bytes long. One byte per mon.
Put 00 00 at x96f90.
This should make the icon show up, but with the wrong palette.
Put 00 00 00 00 at x96e7a.
This fixes the palette reads for extended mons in the party menu.
Put 00 00 at x971da.
This will fix the palette reads for extended mons in the dex once we get there.
Once again, test.
Step 3: Dealing with dex entries
Spoiler:
Repoint and extend the national pokedex order.
This is a list at x251fee that denotes what dex entries mons get.
The main use of this is to give the scattered Hoenn mons proper order.
It is x336 bytes long, 2 per entry.
Note that the limbo slots between Celebi and Treecko have entries on this table.
You don't have to worry about Kanto dex order- that's just the first 151 things in nat dex.
It'd be a good idea to fill this table out now instead of later. Make sure every dex page is tied to some mon.
Repoint and extend the pokedex entries.
These is at x44E850.
Each entry is 36 (x24) bytes long.
The table has 387 entries (one for 00, oddly enough), or x366C bytes.
Unlike most other data, this is in actual pokedex order.
Test, make sure your dex functions normally.
You shouldn't be able to view entries past the regular ones though.
At x1025ec, you'll find a byte. This byte times eight is the amount of memory allocated for the pokedex.
If you have less than 510 mons, replace the byte with 1/2 your dex length.
If you have less than 1020 mons, set it to 1/4 your dex length and put 40 01 at x1025EE.
If you have more than 1020 mons, you should probably rethink what you're doing since 4-digit numbers aren't going to get along with the FR interface unless you do adjustments outside the scope of this tutorial.
At x103920, put the number of dex entries you have minus one.
If this is more than what got malloc'd, the game will crash.
At x43220, put 00 00.
Your dex should now load the full length:
If it locks up, make sure every entry maps to something in dex ordering!
Step 4: Misc. repointing
Spoiler:
Change x88ea4 to the number of dex entries minus one.
This fixes the dex count on the title screen & trainer card.
Change x104c28 to the number of dex entries minus one.
This fixes the dex count on the pokedex menu.
Repoint the TM compatability table.
This is at x252bc8. Each entry is 8 bytes.
The table as a whole is xCE0 bytes long.
Repoint the tutor compatability table.
This is at x459B80. Each entry is two bytes.
The table as a whole is x338 bytes long.
Repoint the evolution table.
This is at x259754. Each entry is 40 (x28) bytes.
The table as a whole is x4060 bytes.
Repoint the item animation table.
This is at x45FD50.
Each entry is 5 bytes long. Entire thing is x811 bytes.
Put 07 E0 at xec9a.
This fixes the evolution animation.
Put E0 at x97011.
This fixes the stamps on the back of the trainer card.
At your own leisure, add the new entries to the habitats list.
This list is at x452c4c. More information can be found here: https://www.pokecommunity.com/posts/6263014/
Add cries for the new mons. As you may know, cries after Celebi are handled unusually- the limbo slots are all hard-wired to Unown's cry (doubt this is hard to fix but lazy), while slots starting from Treecko use an auxilary table to find their cry. This table is at x2539D4- repoint and extend it.
You do need to repoint the cry table. You also need to repoint the secondary cry table, which is right after it and contains the same pointers with different accompanying data- this is used by the move Growl and possibly others.
Put 01 1C 11 E0 at x720CA. This will enable cries past #511 to function.
Repoint the footprint table. It can be found at x43FAB0, and is on a per-mon basis instead of a per-entry basis.
As such, it is x674 bytes long.
To fix breeding, write the ID of your last slot with meaningful evolution data at x459EC (pick an odd number; it's okay to go higher as long as it's not past the number of mons you actually have)
Then, write half of one less than that at x459CC.
If that requires more than one byte, write a quarter of one less than that instead, and change the x40 at x459CE to an x80.
If you are also expanding the number of evolutions, change the x28s at x4598A and x4598E to the new size of the evolution struct.
Given how many things need to be fixed, I probably missed something! Please let me know if you stumble upon anything not mentioned here.
Last edited: