• 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.

Code: ASM Resource Thread

Blah

Free supporter
1,924
Posts
11
Years
  • Scrolling Multi-choice boxes


    Multiple choice boxes have been a really cool, yet in my opinion, a very unmastered feature in ROM hacks. Most people use JPAN's patch to make multichoice boxes, others edit the existing ones in the ROM. However, it seems like there is no solution for when the multiple choice box needs to hold more than just 8 or so options. Most competent hackers seem to have the last option be something which opens another box. It seems clunky and quite troublesome, so I decided to hack it and make it support scrolling and customization :)

    Here are some things which are in some popular hacks which use a work around that can be avoided altogether with this hack:
    20.png
    7xjCAol.png
    CnolW43.png


    The hack in action:



    How to insert:

    Before getting started with the hack there is a little bit of setting up which is required.

    You need to set up a table of pointers somewhere in your ROM. This table will be a table of pointers to possible mulitchoice boxes in your ROM. Each pointer in that table will point to a location of another table. The second table will have pointers to 0xFF terminated strings which will appear in your multichoice box. Visually this is what it should look like:
    Spoiler:


    Once you've configured the above tables, take a look at the routine in the spoilers.
    Code:
    table:
    	.word 0x8[Location of your table, do not +1]
    Change this line according to wherever you put your first table.

    Once that's done compile and insert the routine into free word-aligned space!

    Spoiler:


    Now navigate to 080CB94C and insert the following byte changes:
    Code:
    00 49 08 47 XX XX XX 08
    Where XX XX XX is wherever you inserted this routine +1. Note that the trailing 08 may change depending on your ROM situation!


    Usage:

    So this is a hack of special 0x158. I've essentially fixed the hard coded table read, and removed limitters as well as recoded the size readings to read of a variable instead. So the script usage of this implementation is quite simple, yet there are some complications which arise along the way. I'll talk about those complications later and first describe usage!

    Code:
    Paramaters:
    var 0x8000 = which multichoice box should be shown from the table of multichoice boxes
    var 0x8001 = How many options are supposed to be shown
    var 0x8004 = leave as 0x0 for expected output. It does more, but don't play with it for now (I'll document it on a later day!).
    
    Return value:
    var 0x800D = Which option was selected, where 0x0 is the first option and 0x1 is the second options....ect.

    Sample script snipplet.
    Code:
    #dyn 0x740000
    #org @start
    lock
    faceplayer
    msgbox 0x874001B
    callstd MSG_NORMAL
    setvar 0x8000 0x0 'Use first multichoice box
    setvar 0x8001 0x12 ' First box has 18 options
    setvar 0x8004 0x0 ' standard
    special 0x158
    waitspecial
    release
    end
    
    #org 0x874001B
    = Hello here's some tough choices

    Note, after the waitspecial command finishes, variable 0x800D will have the selected option's index number inside it. From there you can do your own checks to verify which option the user had selected.

    Some usage requirements:

    - 0x8004 = 0. Keep it like this for now until I explain it more a later day. You can play with it too if you want, but it will likely cause a game crash.

    - The menu does not close unless the "B" button is pressed inplace of an option, OR the last option is selected. FR counters this by having an "EXIT" option as the last option of the multichoice box, and any scripts which use the multichoice box are looped as well. I have a fix for this:
    Code:
    @ 080CBB84 insert the following byte changes:
    @ 00 00 00 00
    So use this if you don't want to use the last option EXIT :)
     
    218
    Posts
    10
    Years
    • Seen Nov 12, 2021
    While clowning around in my game, I stumbled upon a bug with Protean. The Gale Wings ability (which Otachi has) trips Protean and changes the monster into a Flying type for some weird reason.



    Video is silly but it does demonstrate the bug.

    I think MrDS plans to rewrite the priority system, it should work correctly after he done that
     
    457
    Posts
    10
    Years
    • Seen Apr 9, 2024

    Scrolling Multi-choice boxes


    Multiple choice boxes have been a really cool, yet in my opinion, a very unmastered feature in ROM hacks. Most people use JPAN's patch to make multichoice boxes, others edit the existing ones in the ROM. However, it seems like there is no solution for when the multiple choice box needs to hold more than just 8 or so options. Most competent hackers seem to have the last option be something which opens another box. It seems clunky and quite troublesome, so I decided to hack it and make it support scrolling and customization :)

    Wow! This is kewl! Gonna test it out.

    What about for setting its x and y alignment? For an example, I would like to have the scrolling multichoice box on the center (or right). Just like the nature of multichoice boxes that can be aligned.
     

    BLAx501!

    Pokemon Flux
    80
    Posts
    10
    Years
  • I want to ask for something. Would it be possible to create a routine that doesn't changes the current music when changing maps?

    For expample, I start at Pallet Town with its lovely music, I activate that routine and when I move to Route 1 or enter Oak's Research Centre, it keeps playing the music, although there is specific music for each map I've mentioned.
     

    Blah

    Free supporter
    1,924
    Posts
    11
    Years
  • Wow! This is kewl! Gonna test it out.

    What about for setting its x and y alignment? For an example, I would like to have the scrolling multichoice box on the center (or right). Just like the nature of multichoice boxes that can be aligned.

    I don't think there are any multichoice boxes which can be aligned. Anyways, if you want information about the box X-Y please see the parameters passed to the function at
    ROM:08003CE4
     

    Blah

    Free supporter
    1,924
    Posts
    11
    Years
  • Music Overriding upon warp


    I want to ask for something. Would it be possible to create a routine that doesn't changes the current music when changing maps?

    For expample, I start at Pallet Town with its lovely music, I activate that routine and when I move to Route 1 or enter Oak's Research Centre, it keeps playing the music, although there is specific music for each map I've mentioned.

    Happy birthday, have an untested routine. If you experience problems, let me know.

    How to insert:

    Compile the following routine into free space:

    Spoiler:


    Then insert the following byte changes to 0x807198C:
    Code:
     00 48 00 47 XX XX XX 08
    Note that the trailing 08 may change. XX XX XX is as usual wherever you've inserted the routine +1 in reverse hex.

    Usage:
    Have flag 0x404 set and variable 0x8000 to be the music ID you'd want to play. Only works upon warp.
     
    218
    Posts
    10
    Years
    • Seen Nov 12, 2021
    Better to post it here :

    Here is a very simple routine that makes moves having 0 accuracy never miss. I found that more convenient than set the "always hit flag" in the battle scripts. It is for Emerald :

    Spoiler:


    Also, I saw few people asking for having new "-ate" abilities, which is understandable, so I post them here too if you want to make your custom ones :
    Spoiler:
     
    Last edited:

    BLAx501!

    Pokemon Flux
    80
    Posts
    10
    Years
  • Music Overriding upon warp




    Happy birthday, have an untested routine. If you experience problems, let me know.

    How to insert:

    Compile the following routine into free space:

    Spoiler:


    Then insert the following byte changes to 0x807198C:
    Code:
     00 48 00 47 XX XX XX 08
    Note that the trailing 08 may change. XX XX XX is as usual wherever you've inserted the routine +1 in reverse hex.

    Usage:
    Have flag 0x404 set and variable 0x8000 to be the music ID you'd want to play. Only works upon warp.

    I love you man!! I'm going to try it now to check if it works well and I'll edit this post with the results.

    Anyway, thanks a lot for the effort you are putting on this thread ;)
     

    Exodrake

    The Manliest Chick that Ever Manlied
    163
    Posts
    10
    Years
    • Seen Nov 30, 2016
    I'm unsure of the correct place to bring this up, but is there anybody researching expanding the move tutor yet (move reminder in later gens)? The problem is, if your Pokemon has a moveset with more than 20 moves, they won't all show up in the move tutor because that list can only show up to 20 moves. And expanded movesets with more than 20 moves are common with hacks that try to mimic later generations.
     
    417
    Posts
    9
    Years
    • Seen Nov 20, 2016
    I'm unsure of the correct place to bring this up, but is there anybody researching expanding the move tutor yet (move reminder in later gens)? The problem is, if your Pokemon has a moveset with more than 20 moves, they won't all show up in the move tutor because that list can only show up to 20 moves. And expanded movesets with more than 20 moves are common with hacks that try to mimic later generations.
    Had a (quick) look after reading your post. So this is how you can change the limit when the subroutine is reading the learnset entry:

    Code:
    main: @at 0x08043DA0:
    	cmp r5, #0x13 @CHANGE TO NEW LIMIT
    	bgt main + 0x14

    Actually you might be able to just change the first byte from 0x13 to the limit, but I'm not all that confident with compares and alignment with opcodes so I wrote it out.

    Sadly it isn't this simple. This subroutine (at 0x08043C84) is apparently writing the moves to an address contained at the offset 0x0203AAB4 + 0xE8. If anyone is familiar with with what's going on there and if there is space to add moves (a halfword at a time) that would be great. If it isn't possible to add more moves there without corruption, it may be necessary to use malloc and change all references to that address.

    As a side note, I had also wanted to rewrite the relearner to reteach egg moves. I didn't even know there was a limit of twenty until you brought it up.

    Edit:

    I went a level up, and word 0x0203AAB4 is just a temporary pointer to a malloc of size 0xA6C called at 0x080E47A6. It is necessary to understand each area used in that block, or at the very least how their size and offset relates to the maximum number of moves that can be listed. Following from the malloc call to the bl to 0x080E50CC, here's what I have so far on the block:

    Spoiler:
    The annoying thing is that the routines use actual numbers for the "bases", such as 0xE8 being used for move indices and 0x11A in a literal pool being used for names. I attempted changing the routines before all of the graphics comes into play and, as expected, it didn't work. This will be fun.
     
    Last edited:

    JPAN

    pokemon rom researcher
    104
    Posts
    15
    Years
    • Seen Jul 2, 2016
    I have something for you all. A number input box for Fire Red. Image in spoiler
    Spoiler:

    This box allows the player to insert numbers in a hack, allowing for many new features such as a banking system, password protected doors and the like.
    Included in the zip is the compiled code and the source. The source, however must be modified to be compiled in a normal compiler. It's included more as a study material to see how it was implemented.
    The "number box.out" file contains the compiled code, ready to use. All you need to do is insert the code at a free location, edit the pointer at code + 0x164 to (pointer to code + 0x0179) and then call it with the callASM command followed by a waitstate. You also need to be in a locked state, so use lockall or lock before callASM, and release/releaseall at the end of the script.
    To change the location of where the box is located change X at code+2 and Y at code+4 and to change the width of the box change the byte at code+6.
     
    Last edited:
    91
    Posts
    14
    Years
    • Seen Feb 22, 2023
    I have something for you all. A number input box for Fire Red. Image in spoiler
    Spoiler:

    This box allows the player to insert numbers in a hack, allowing for many new features such as a banking system, password protected doors and the like.
    Included in the zip is the compiled code and the source. The source, however must be modified to be compiled in a normal compiler. It's included more as a study material to see how it was implemented.
    The "number box.out" file contains the compiled code, ready to use. All you need to do is insert the code at a free location, edit the pointer at code + 0x164 to (pointer to code + 0x0179) and then call it with the callASM command followed by a waitstate.
    To change the location of where the box is located change X at code+2 and Y at code+4 and to change the width of the box change the byte at code+6.

    Hey, this is great! Yet I would be glad if you would provide us the actual source code. Somebody might want to edit your code and for my part I would like to add it to my build scripts. (I don't think your code is compiled with -c)

    Looking forward to combination lock like riddles :D

    ~SBird

    Edit: Okay screw me, I just found the "number_box.tmb" and did not consider it being a code file... thanks again for the project :)
     
    58
    Posts
    8
    Years
    • Seen Jan 7, 2017
    I have something for you all. A number input box for Fire Red. Image in spoiler

    This box allows the player to insert numbers in a hack, allowing for many new features such as a banking system, password protected doors and the like.
    Included in the zip is the compiled code and the source. The source, however must be modified to be compiled in a normal compiler. It's included more as a study material to see how it was implemented.
    The "number box.out" file contains the compiled code, ready to use. All you need to do is insert the code at a free location, edit the pointer at code + 0x164 to (pointer to code + 0x0179) and then call it with the callASM command followed by a waitstate.
    To change the location of where the box is located change X at code+2 and Y at code+4 and to change the width of the box change the byte at code+6.

    Your work amaze me! However I haven't passed the test in script.
    1. I changed the pointer you've mentioned.
    2. write a script like
    Code:
    #org @start
    setvar 0x8008 0xffff
    setvar 0x8009 0x2 //random number in my brain
    callasm 0x8[address+1]
    waitstate
    end

    But when I go to talk with the man who has the script, nothing happened.
    Please point out my mistake, thanks.
     

    JPAN

    pokemon rom researcher
    104
    Posts
    15
    Years
    • Seen Jul 2, 2016
    Your work amaze me! However I haven't passed the test in script.
    1. I changed the pointer you've mentioned.
    2. write a script like
    Code:
    #org @start
    setvar 0x8008 0xffff
    setvar 0x8009 0x2 //random number in my brain
    callasm 0x8[address+1]
    waitstate
    end
    But when I go to talk with the man who has the script, nothing happened.
    Please point out my mistake, thanks.

    I hadn't tested it without a lock/lockall command. Apparently, it is required, as the box does not appear without it. Instructions were edited to cover this fact.
     
    58
    Posts
    8
    Years
    • Seen Jan 7, 2017
    I hadn't tested it without a lock/lockall command. Apparently, it is required, as the box does not appear without it. Instructions were edited to cover this fact.

    Thank you very much! The box worked fine now. I will try to analyze your awesome routine then
     
    91
    Posts
    14
    Years
    • Seen Feb 22, 2023
    Another request (A real one this time I promise) : It is quite a neusance for (most) cases that you have to switch the number lets say from 0 to 456786 - For combination locks, codes, and generally stuff that requires LARGE numbers it would be way easier if you could edit digit by digit. Probably you could consider this. :)

    ~SBird
     
    58
    Posts
    8
    Years
    • Seen Jan 7, 2017
    I hadn't tested it without a lock/lockall command. Apparently, it is required, as the box does not appear without it. Instructions were edited to cover this fact.

    Sorry for bothering you again. I've looked at the routine and I found that maybe "func_10f7d8" is not needed to be called and after deleting it i've found nothing wrong though it's included in the original "multichoice" command for showing the triangle before the text. (number)

    Another thing is that could you make a detailed note about your functions? I know that it's a bit not realistic, but i really don't know many things in the source code.

    Thank you very much in advance!
     
    Last edited:
    277
    Posts
    9
    Years
  • I don't know where it is either. Perhaps you can ask daniilS via VM or something.




    1) For forced evolution, I don't know what you're really talking about. You mean just make a Pokemon evolve without giving the player time to hit the "b" button? I'll look into Pokemon evolution sure.

    2) I haven't seen it so VMing me it would be nice. Anyways this is rather easy, I've done it before. I'll post the results at the bottom of this post.

    3) Skipping the introduction was already done by Knizz. There's a post in the research and development section's quick research thread.


    Preventing TMs from being consumed on use


    Quick research:
    TMs are deleted in two places. The first place is in their own function. When called from the bag, after use the TM has it's own deletion mechanism. The second way is from the bag, after you use a TM the bag attempts to delete it as well. Well, the solution is quite simple. There's two ways to do this, either go to 0809A1D8 call your own function there which checks if the item is a TM, and if it is, just jump to the end. Or much more simply you just remove the parts from the bag and tm function that deletes the TM (Which is what I did). The former way is a way you can make another item you have unconsumable.

    To insert:
    Do the byte changes below
    0x124F78: 00 00 00 00
    0x125C80: 00 00 00 00

    Make it Ungivable:
    insert that at 0x1326B8: 00 00 17 E0

    Make it consumable after animation:
    Insert: 00 00 00 00 at 0x124F78

    To remove the quantities showing up in the bag:

    Compile and insert into free space:
    Spoiler:


    Here's a compiled version:
    Code:
    00 2D 01 D1 05 4B 18 47 38 1C 08 21 22 1C 04 4E 00 F0 02 F8 01 4B 18 47 30 47 C0 46 FF 1E 13 08 B1 35 13 08

    Now navigate to 0x131EF4 and insert:
    Code:
    00 48 00 47 XX XX XX 08
    Where XX XX XX is the pointer to where you assembled the routine +1

    Now navigate to 0x131EA5 and change the byte to E0

    Unsellable:
    Basically for the TMs, you can still sell them to vendors. To change this, you need to modify each TM individually. It's unfortunate, but the game checks if an item can be sold my comparing it's market price to zero. If it's strictly greater than zero, then you can sell it to a vendor, seems to be the rule. So to make TMs unsellable you need to set their market prices individually to zero.
    I can't use my own checks to disguise the TMs as unique because the sell routine in shops are used for ALL items including potions, berries, TMs, and other items like nuggets.


    Present :3
    3nina1p.png
    I've done this twice, and checked my hex editing, but it doesn't work. It still says there's 1 tm, and after I teach the tm to a pokemon the screen goes black, but the music still plays. Any idea why this happens?
     
    794
    Posts
    10
    Years
  • I've done this twice, and checked my hex editing, but it doesn't work. It still says there's 1 tm, and after I teach the tm to a pokemon the screen goes black, but the music still plays. Any idea why this happens?

    You probably messed up pointers. Try doing it again and make sure all your pointers are correct.

    Preventing TMs from being consumed on use


    Quick research:
    TMs are deleted in two places. The first place is in their own function. When called from the bag, after use the TM has it's own deletion mechanism. The second way is from the bag, after you use a TM the bag attempts to delete it as well. Well, the solution is quite simple. There's two ways to do this, either go to 0809A1D8 call your own function there which checks if the item is a TM, and if it is, just jump to the end. Or much more simply you just remove the parts from the bag and tm function that deletes the TM (Which is what I did). The former way is a way you can make another item you have unconsumable.

    To insert:
    Do the byte changes below
    0x124F78: 00 00 00 00
    0x125C80: 00 00 00 00

    Make it Ungivable:
    insert that at 0x1326B8: 00 00 17 E0

    Make it consumable after animation:
    Insert: 00 00 00 00 at 0x124F78

    To remove the quantities showing up in the bag:

    Compile and insert into free space:
    Spoiler:

    Here's a compiled version:
    Code:
    00 2D 01 D1 05 4B 18 47 38 1C 08 21 22 1C 04 4E 00 F0 02 F8 01 4B 18 47 30 47 C0 46 FF 1E 13 08 B1 35 13 08
    Now navigate to 0x131EF4 and insert:
    Code:
    00 48 00 47 XX XX XX 08
    Where XX XX XX is the pointer to where you assembled the routine +1

    Now navigate to 0x131EA5 and change the byte to E0

    Unsellable:
    Basically for the TMs, you can still sell them to vendors. To change this, you need to modify each TM individually. It's unfortunate, but the game checks if an item can be sold my comparing it's market price to zero. If it's strictly greater than zero, then you can sell it to a vendor, seems to be the rule. So to make TMs unsellable you need to set their market prices individually to zero.
    I can't use my own checks to disguise the TMs as unique because the sell routine in shops are used for ALL items including potions, berries, TMs, and other items like nuggets.


    Present :3
    3nina1p.png

    It seems that TMs are still consumable if taught to a pokemon without animation, i.e. if it only knows 2 moves.
     
    Back
    Top