• Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
  • Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
  • Which Pokémon Masters protagonist do you like most? Let us know by casting a vote in our Masters favorite protagonist poll here!
  • 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.

[ASM & Hex✓] [Fire Red] Identical evolution methods

  • 352
    Posts
    8
    Years
    • Seen Mar 10, 2022
    I was thinking about the new Alolan evolutions like Pikachu>>>Alolan Raichu and Exeggute>>>Alolan Exeggutor, they evolve exactly the same way of it's non-Alolan counterpart , then how to do the 2 evolutions in the same game without using another stone or without creating a new evolution line? I was thinking in some Stone+Location evolution method and Day Time+Location for Alolan Marowak too. (But the Location will be better if is set only to Map Bank, then it will work on all Maps of the same Map Bank, in theory.)

    It sounds a high level of difficulty, but if there is a way to merge 2 evolution methods it will work. Well, it's my opinion, I'm not ASMer, then I don't know if it's possible.
     
    Last edited:
    a cheap way of doing it is having, for example, 2 different pikachu.
    they have the same image, same sprites, same moves, but different evolutions.
    during development, you treat them as different pokémon, but in-game the player only see them as one specie.
    the problems with this cheap method are the pokedex numbers/indexes
     
    There shouldn't be an issue, at least for Pikachu and Exeggcute. I'm not very familiar with evolutions tiggered on level-up, so it may or not be a problem for Cubone.

    You'll have to change it anyway to add support for it, but the existing routine that checks if a Pokemon is compatible with an Evolutionary Stone just stops when it finds one that works. Taking advantage of this, all you'd need to do to support a separate Thunder Stone evolution and a Thunder Stone/Map Bank evolution is that you'd list the more specific (map bank) one first in the evolution table.
     
    a cheap way of doing it is having, for example, 2 different pikachu.
    they have the same image, same sprites, same moves, but different evolutions.
    during development, you treat them as different pokémon, but in-game the player only see them as one specie.
    the problems with this cheap method are the pokedex numbers/indexes
    this was forever ago but
    the pokédex numbers/indices are easy to fix; just assign them to the same index in any pokédex editor :P

    if you wanted to merge like a stone routine and a map check routine, it really shouldn't be that hard. the method i'm thinking of doing it would probably result in the game showing that the evolution stome could evolve the pokémon, but it wouldn't until you get in the area necessary. hmm...
    you could do this all hardcore-style and make it reliant on some byte in the pokémon structure; if the pokémon has no second form, then it simply won't show. if it does and the byte is set, then the pokémon will show it's second form
    i'm overthinking ahaha
     
    this was forever ago but
    the pokédex numbers/indices are easy to fix; just assign them to the same index in any pokédex editor :P

    if you wanted to merge like a stone routine and a map check routine, it really shouldn't be that hard. the method i'm thinking of doing it would probably result in the game showing that the evolution stome could evolve the pokémon, but it wouldn't until you get in the area necessary. hmm...
    you could do this all hardcore-style and make it reliant on some byte in the pokémon structure; if the pokémon has no second form, then it simply won't show. if it does and the byte is set, then the pokémon will show it's second form
    i'm overthinking ahaha

    The Pokédex thing is not a problem, I use this method, but the only problem is the evolution, I'm not an ASMer but I think it would be hard to do, I don't know if someone wants to do it, but it would be a great addition to some roms with Alolan Pokémon, and the problem is, I'm still not an ASMer. =\
     
    The Pokédex thing is not a problem, I use this method, but the only problem is the evolution, I'm not an ASMer but I think it would be hard to do, I don't know if someone wants to do it, but it would be a great addition to some roms with Alolan Pokémon, and the problem is, I'm still not an ASMer. =\
    here's my idea, then, this requires like very little asm generation
    so, you know the evolution table? 08042FC4 and all that?
    well, you do if you repointed it to new evo methods.
    basically, add the map-check evolution but then replace the "levelcheckloc" define with the address of the evolution stone's routine. thus, when it runs, it will check if you are in the certain map, and then if you are, it will branch off to the stone routine. the parameters, naturally, would still be the the map bank/number.
    and now, the bad news: the stone's index that it accepts will be the same as (i think) the map bank. i might look into modifying this for you sometime tomorrow to accept a certain item index (does it only affect the thunder stone?), but it really shouldn't be that hard at all~
     
    here's my idea, then, this requires like very little asm generation
    so, you know the evolution table? 08042FC4 and all that?
    well, you do if you repointed it to new evo methods.
    basically, add the map-check evolution but then replace the "levelcheckloc" define with the address of the evolution stone's routine. thus, when it runs, it will check if you are in the certain map, and then if you are, it will branch off to the stone routine. the parameters, naturally, would still be the the map bank/number.
    and now, the bad news: the stone's index that it accepts will be the same as (i think) the map bank. i might look into modifying this for you sometime tomorrow to accept a certain item index (does it only affect the thunder stone?), but it really shouldn't be that hard at all~

    It affects the Thunder Stone and the Leaf Stone, because of Exeggutor's Alolan Form.

    EDIT: I think the only way to work is creating a new evolution line. (Pichu>Pikachu>Alolan Raichu / Exeggute>Alolan Exeggutor)
     
    Last edited:
    I already had some ASM laying around from the last time I adjusted Stone-triggered evolutions, so I did this:

    Spoiler:


    The evolution table (0x08259754) actually has an extra two bytes of padding for every evolution. The structure is 2 bytes for evolution type, 2 bytes for the condition (what this means depends on the evolution type), 2 bytes for what it evolves into, and 2 bytes of padding.

    My code just uses a new evolution type (0x00 - 0x0F are taken, so Stone+Location is 0x10). The required stone is the condition (as it is for normal stone evolutions), and then it uses the padding bytes to specify the map it evolves on.

    Then, as I said before, it's just a matter of putting the evolution into normal Raichu second in the evolution table to the evolution to Alolan Raichu (or in my case, Zapdos).

    That's what you wanted, right?
     
    I already had some ASM laying around from the last time I adjusted Stone-triggered evolutions, so I did this:

    Spoiler:


    The evolution table (0x08259754) actually has an extra two bytes of padding for every evolution. The structure is 2 bytes for evolution type, 2 bytes for the condition (what this means depends on the evolution type), 2 bytes for what it evolves into, and 2 bytes of padding.

    My code just uses a new evolution type (0x00 - 0x0F are taken, so Stone+Location is 0x10). The required stone is the condition (as it is for normal stone evolutions), and then it uses the padding bytes to specify the map it evolves on.

    Then, as I said before, it's just a matter of putting the evolution into normal Raichu second in the evolution table to the evolution to Alolan Raichu (or in my case, Zapdos).

    That's what you wanted, right?

    It's exactly what I want, but my evolution table is expanded to 16 evolutions, how I can do it? Can you explain me with a little tutorial? (Please...) xD
     
    Sure, I'll have some time a little later today and I'll write it up for you.

    Just out of curiosity, why did you expand it so much? 16 evolutions per Pokemon seems kind of excessive.

    Thank you so much. ^^

    It is because of Eevee's evolutions (All versions of it's evolutions including the two ways to evolve into Espeon/Umbreon by daytime and by stone and others) and some beta Pokémon I've added, and I like to do it because someday can have new evolutions, and I don't want to expand everytime it reaches the limit. xD
     
    Since you've already expanded the evolution table, all you really need to is insert a custom ASM routine to replace the existing code that handles checking stone compatibility, as well as a hook from the old to the new code.

    The source code for the routine:

    Spoiler:

    And here's what it looks like assembled:

    Spoiler:


    Open up your ROM, find some free space, and insert that. Make sure the address you choose is word aligned - that is, it should end with 0, 4, 8, or C.

    And the source code for the hook:

    Spoiler:

    Assembled, it looks like:

    Spoiler:


    The X's should be wherever you inserted the main routine, plus one. And it has to be in reverse hex. So if, for example, you inserted it at 0x08800000, they would be 01 00 80 08.

    Write it to 0x08043182.

    After you do that, you're done inserting things. It won't currently have any visible effect in-game, because there's no Pokemon set to evolve via the new Stone + Location method we just made. However, our code also handles the regular stone evolutions, so you can try one of those in-game to verify that they're working and you've done this properly.

    Now you just need to set Pokemon to actually use this new method of evolution. This will have to be done by hex editing. If you're not familiar with how the evolution table is laid out, I suggest you look at this article.

    As an example, I will walk you through doing Pikachu -> Raichu, but Exeggcute -> Exeggutor will be very similar.

    In the vanilla games, you can skip to the part of the evolution table corresponding to a particular Pokemon using the formula 0x259754 + species * 5 * 8. 0x259754 is the pointer to the evolution table itself, 8 is the size of each evolution struct, and 5 because each Pokemon has 5 evolutions.

    Your repointed and expanded the evolution table, so you'd change 0x259754 to wherever you put it and the 5 into a 16. You never mentioned where exactly you placed your evolution table, so I'll just assume for the purposes of this example that it's at 0x800100.

    To get to the entry for Pikachu, do 0x800100 + 25 * 16 * 8, which is 0x800D80. Go there in your hex editor, and you should see the existing entry for Pikachu to evolve into Raichu. In cases like this where you want to evolve into two different things via the same stone (one by regular Stone, and one by Stone+Location), as I said before, you need to make sure the Stone+Location one is listed first. This is because, when looking through a Pokemon's list of evolutions for a stone-triggered evolution, it just takes the first one that works. Regular stone evolution always works, so if you listed it first, it would never get to the Stone+Location one (this is obviously not a problem if you're using different stones, though).

    Basically, copy the 8 bytes corresponding to the evolution into Kanto Raichu, and move them down 8 bytes so that it's in the second evolution slot. Return to the first slot, and set up the evolution into Alola Raichu.

    As explained in the linked article, the first two bytes are the type of the evolution. If you look at the source code of the routine, you'll see I arbitrarily chose 0x20 - you could change this, but it doesn't really matter what the value is, just that it's unique. The third and fourth bytes are the condition, which is just the type of stone you want to use (so, Thunderstone, which is 0x60).

    Bytes five and six are the Pokemon you want to evolve into. So, whatever index number you want Alola Raichu to be would go here. Bytes seven and eight are labeled by the article as padding, but we're using it to specify the map - byte 7 is the map bank, and byte 8 is the map number. I actually just noticed about 30 seconds ago that you were considering just specifying the map bank - let me know if you'd prefer that; it's just a trivial change for the routine to work like that instead.

    In the video, I pretended that Zapdos was Alola Raichu, and chose Cinnabar Island as the map that evolves it, so the 8 bytes for that would be 20 00 60 00 91 00 03 08.
     
    Last edited:
    Since you've already expanded the evolution table, all you really need to is insert a custom ASM routine to replace the existing code that handles checking stone compatibility, as well as a hook from the old to the new code.

    The source code for the routine:

    Spoiler:

    And here's what it looks like assembled:

    Spoiler:


    Open up your ROM, find some free space, and insert that. Make sure the address you choose is word aligned - that is, it should end with 0, 4, 8, or C.

    And the source code for the hook:

    Spoiler:

    Assembled, it looks like:

    Spoiler:


    The X's should be wherever you inserted the main routine, plus one. And it has to be in reverse hex. So if, for example, you inserted it at 0x08800000, they would be 01 00 80 08.

    Write it to 0x08043182.

    After you do that, you're done inserting things. It won't currently have any visible effect in-game, because there's no Pokemon set to evolve via the new Stone + Location method we just made. However, our code also handles the regular stone evolutions, so you can try one of those in-game to verify that they're working and you've done this properly.

    Now you just need to set Pokemon to actually use this new method of evolution. This will have to be done by hex editing. If you're not familiar with how the evolution table is laid out, I suggest you look at this article.

    As an example, I will walk you through doing Pikachu -> Raichu, but Exeggcute -> Exeggutor will be very similar.

    In the vanilla games, you can skip to the part of the evolution table corresponding to a particular Pokemon using the formula 0x259754 + species * 5 * 8. 0x259754 is the pointer to the evolution table itself, 8 is the size of each evolution struct, and 5 because each Pokemon has 5 evolutions.

    Your repointed and expanded the evolution table, so you'd change 0x259754 to wherever you put it and the 5 into a 16. You never mentioned where exactly you placed your evolution table, so I'll just assume for the purposes of this example that it's at 0x800100.

    To get to the entry for Pikachu, do 0x800100 + 25 * 16 * 8, which is 0x800D80. Go there in your hex editor, and you should see the existing entry for Pikachu to evolve into Raichu. In cases like this where you want to evolve into two different things via the same stone (one by regular Stone, and one by Stone+Location), as I said before, you need to make sure the Stone+Location one is listed first. This is because, when looking through a Pokemon's list of evolutions for a stone-triggered evolution, it just takes the first one that works. Regular stone evolution always works, so if you listed it first, it would never get to the Stone+Location one (this is obviously not a problem if you're using different stones, though).

    Basically, copy the 8 bytes corresponding to the evolution into Kanto Raichu, and move them down 8 bytes so that it's in the second evolution slot. Return to the first slot, and set up the evolution into Alola Raichu.

    As explained in the linked article, the first two bytes are the type of the evolution. If you look at the source code of the routine, you'll see I arbitrarily chose 0x20 - you could change this, but it doesn't really matter what the value is, just that it's unique. The third and fourth bytes are the condition, which is just the type of stone you want to use (so, Thunderstone, which is 0x60).

    Bytes five and six are the Pokemon you want to evolve into. So, whatever index number you want Alola Raichu to be would go here. Bytes seven and eight are labeled by the article as padding, but we're using it to specify the map - byte 7 is the map bank, and byte 8 is the map number. I actually just noticed about 30 seconds ago that you were considering just specifying the map bank - let me know if you'd prefer that; it's just a trivial change for the routine to work like that instead.

    In the video, I pretended that Zapdos was Alola Raichu, and chose Cinnabar Island as the map that evolves it, so the 8 bytes for that would be 20 00 60 00 91 00 03 08.

    It's awesome, worked perfectly, and yes it will be perfectly if you can set only the map bank for an entire Alola Region evolution and a possible way to do Daytime+Location for Alolan Marowak. (But the Marowak Evolution isn't very important) ^^ Thank you so much!
     
    It's awesome, worked perfectly, and yes it will be perfectly if you can set only the map bank for an entire Alola Region evolution and a possible way to do Daytime+Location for Alolan Marowak. (But the Marowak Evolution isn't very important) ^^ Thank you so much!

    Okay, to change it to only depend on the map bank is basically:

    Spoiler:

    And, assembled, that looks like:

    Spoiler:


    Just replace the first version of the routine with this (it's mostly the same, and takes up the same amount of space).

    The seventh byte in the evolution table structure is still the map bank, and you should just leave the 8th byte as zero.

    I don't have any experience creating evolution methods that are triggered on level-up, like Marowak's Daytime+Location. I know some resources for it, so I could do it, but it'll take me a few days. I just happened to be really familiar with the code that checks stone compatibility already, so making Stone+Location was really easy.
     
    Last edited:
    Okay, to change it to only depend on the map bank is basically:

    Spoiler:

    And, assembled, that looks like:

    Spoiler:


    Just replace the first version of the routine with this (it's mostly the same, and takes up the same amount of space).

    The seventh byte in the evolution table structure is still the map bank, and you should just leave the 8th byte as zero.

    I don't have any experience creating evolution methods that are triggered on level-up, like Marowak's Daytime+Location. I know some resources for it, so I could do it, but it'll take me a few days. I just happened to be really familiar with the code that checks stone compatibility already, so making Stone+Location was really easy.

    Simply awesome, thank you for the help, I've posted the links of your post at the ASM Resource Thread because it needs to be there. xD
    Very nice work.
    No problem with the Marowak evolution, if you can do it, I can wait, but if not, you've helped me so much with the others making it not very important. (but is always good to have it xD)

    I made some changes to your routines and merged them, now you can use one routine to do the 2 Evolution Methods (Stone + Map Name & Stone + Map Bank), well I'm not an ASMer but it's pure logical to do it like the Stone + Gender Evolution Method of Dawn Stone:

    Here's the routine:
    Spoiler:


    Assembled Version:
    Spoiler:


    To work, the order of stone evolutions at the evolution table must be:

    Map Name (XX / YY - BANK / MAP)
    Map Bank (XX - BANK)
    Default Stone Evolution
     
    Last edited:
    Back
    Top