• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Research: Egg Move Table

457
Posts
10
Years
    • Seen Apr 9, 2024
    Why nobody have researched about the data structure of the Egg Move table? Is it complicated to understand? To do it manually? Well, it is not really that hard nor complicated. The table structure is not pointer base. It is just the first slot ends with the entry of the second slot next to it. Anyway, let's proceed to how it is structured for anyone who would want to do it manually.

    First of all, here are the locations of the vanilla Egg Move table:

    Emerald: 0x0832ADD8
    FireRed: 0x0825EF0C
    Ruby: ???

    The table size is 0x8E4. If you're going to study the table with a hex editor, the table with the data of the first three slots appear like this:

    Code:
    21 4E 71 00 82 00 DB 00 CC 00 50 00 59 01 40 01 AE 00
    24 4E BB 00 F6 00 9D 00 2C 00 C8 00 FB 00 0E 00 5D 01
    27 4E F3 00 72 00 36 00 C1 00 AF 00 1F 01 2C 01 19 01
    ...
    (until) FF FF

    So, how it works? Recognize the hwords with XX 4E? That's how the Pokemon's index number is controlled. How do I know if which Pokemon is that 0x4E21? Subtract it with 0x4E20. Then, you'll get 0x0001, so that's Bulbasaur. I'll explain that later on. The next hwords after the Pokemon index number are the move index numbers. G3T has the great program of viewing the index number of moves while editing the moves in G3T's Move Editor, or look at Bulbapedia for the list of moves and if those aren't hexadecimal, then convert it in Windows Calculator. It's terminator is another Pokemon slot plus 0x4E20, or an 0xFFFF which actually ends the Egg Move table. Now, let's proceed to modify, make a custom table, repoint and add entires for expanded 'mons, or whatever.

    Pokemon
    But, why Pokemon Index Number is like that? 20 4E? I'm not really sure what it really does but I think it had to be like that because that will be for the Pokemon's number, and it will be confusing with the move index numbers too (that's why). Anyway, there is a part in the routine that you can change 0x4E20 to something else. But, I really don't know what really does do, so let's just leave it for now. To do that, it is really simple. You'll just have to add the Pokemon's index number with 0x4E20.

    For example: Turtwig's index number is 0x01B8. Add 0x01B8 with 0x4E20. Then, it will result as 0x4FD8.
    That hword will be the start of Egg Move slot of Turtwig. So, your scratch would be like this:

    Code:
    D8 4F

    Moves
    Now, we proceed to the moves. The Pokemon's index number plus 0x4E20 should be proceeded by hwords of Move Index Number. You may put as many as you can until you need to cut it off with another Pokemon's slot, or by FF FF if the entire Egg Move table is completed and nothing to add more.

    Now, to the example: You might want to have Amnesia and Seed Bomb to Turtwig. You will have to look for index numbers of those moves. Amnesia and Seed Bomb are 0x0085 and 0x0192, so that's what you will have to put after the Pokemon's index slot:

    Code:
    D8 4F 85 00 92 01

    To limit it, just put the next slot. For example if Chimchar and Piplup are 0x01BB and 0x01BE:

    Code:
    D8 4F 85 00 92 01 DB 4F 02 01 03 01 04 01 DE 4F 05 01 06 01 07 01 (and so on)

    Or, if that's already the end of the Egg Move Table, put 0xFFFF instead:

    Code:
    D8 4F 85 00 92 01 FF FF

    Limiter/Table's Size
    Lastly, we now proceed to the limiter. As usual, limiters are for scaling to where and which the table ends, the size of the table is, etc. The limiter location for each ROM:

    Emerald: 0x08070464
    FireRed/LeafGreen: 0x08045CC4
    Ruby/Sapphire: 0x08041BB8

    The limiter is hword (might be a word but further research will be continued). But, what should I put there? The answer is the length of your Egg Move Table (do not count the FF FF), divided by two, then minus one. If the original is 0x0471, then the length of the original table should be 0x08E4 bytes long (again, the FF doesn't count).

    Repoint
    The last thing you will do is to repoint the table to your new Egg Move table. I'm not going to explain on how to repoint. Nevertheless, the research is universal. There can only be two instances of words that points to the table (unless you have a custom ASM that uses the Egg Move table).

    That's it! You're done! That's all the research about it, and you can now modify the Egg Move table with knowledge and without the G3HS tool.
     

    MrDollSteak

    Formerly known as 11bayerf1
    858
    Posts
    15
    Years
  • Why nobody have researched about the data structure of the Egg Move table? Is it complicated to understand?

    That's it! You're done! That's all the research about it, and you can now modify the Egg Move table with knowledge and without the G3HS tool.

    Well actually I went through and documented it first for G3HS. Since I thought the tool was fine I decided not to post about it, because it was pretty simple, but then the tool was buggy.

    So yeah good job on actually writing a great explanation about it!
     

    Blah

    Free supporter
    1,924
    Posts
    11
    Years
  • Why nobody have researched about the data structure of the Egg Move table?

    That's neat. Actually the table isn't terminated by 0xFF, it's terminated by 0x471 entries. Ater 0x471 entries are read, it assumes the Pokemon is invalid and returns 0x0 with an empty egg move buffer.

    The egg move buffer generation is all done in a very very badly programmed loop. Here it is in FR:

    Code:
    ROM:08045C58 loc_8045C58:
    ROM:08045C58                 ADDS    R0, R2, #1
    ROM:08045C5A                 LSLS    R0, R0, #0x10
    ROM:08045C5C                 LSRS    R2, R0, #0x10
    ROM:08045C5E                 LDR     R0, =0x471
    ROM:08045C60                 LDR     R5, =eggmoves
    ROM:08045C62                 CMP     R2, R0
    ROM:08045C64                 BHI     loc_8045C7A
    ROM:08045C66                 LSLS    R0, R2, #1
    ROM:08045C68                 ADDS    R0, R0, R5
    ROM:08045C6A                 LDRH    R1, [R0]
    ROM:08045C6C                 LDR     R7, =0x4E20
    ROM:08045C6E                 ADDS    R0, R3, R7
    ROM:08045C70                 CMP     R1, R0
    ROM:08045C72                 BNE     loc_8045C58

    As you can see it compares every entry...yes every entry in the table to determine that it's got the species right (facepalm material right here). It's quite an unfortunate loop. From here, you can see that the 0x4E20 is actually just some arbitrary number they used since they were going to loop through each entry of the table to check the species. That means that just having the species ID would have been impossible for them to distinguish between a move and an actual species.

    To add a little more of a contribution, currently it seems like you're only allowed to have 8 egg moves per Pokemon species. The reason for this is because of the check over here:

    Code:
    ROM:08045CA6                 CMP     R2, #9
    ROM:08045CA8                 BHI     loc_8045CB6
    The loop here starts with r2 = 0x1, hence the 8 moves. Change the 0x9 at 08045CA6 to adjust that. In FireRed this seems to be the only time the egg move table is browsed.

    One more thing, 0x202456C (which is the default eggmove buffer in Fire Red) is only 0x14 bytes, which is enough for only 10 moves. You will need to repoint this if you're adjusting the number of moves. I suggest just using malloc with a hook since 08045CD0 is the only function which uses it :)

    Hopefully this info helped!


    Well actually I went through and documented it first for G3HS. Since I thought the tool was fine I decided not to post about it, because it was pretty simple, but then the tool was buggy.

    So yeah good job on actually writing a great explanation about it!

    The table is simply formatted, but the code is a mess. Also, expanding it is non-trivial as just a simple repoint would not be enough. The entire code is a limiting factor same with the RAM locations used.
    -


    I suggest someone who wants to practice their ASM rewrite the loop to be more effective. It's a relatively simple task, and I don't wanna do peasant work :D
     
    Back
    Top