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

[Script] Fixing the Toxic catch rate bug in Ruby & Sapphire

  • 12
    Posts
    3
    Years
    • Seen Jul 19, 2022
    Hello everyone 👌,

    after successfully fixing the bug with the clerk in Oldale Town, I set my eyes on a rather unknown phenomenon.
    When using Toxic on a Pokemon, the catch rate will not be enhanced, just like it would be with normal poisoning (link).
    According to the article, this has even been fixed for FireRed and LeafGreen (and Emerald?), which should make it easier to understand what is going wrong.

    I know that the status condition of a Pokemon is stored in a DWORD (link), seems like a waste since only the first 8 Bits are used anyway, but OK.
    Edit: Hmm... now that I think of it, probably the other Bits are used for stuff like Curse and Leech Seed.

    Toxic is Bit #7, while sleep uses #0 to #2 and the other conditions use #3 to #6.
    My best guess is, that the routine which computes the catch rate does two ANDs:
    * the first uses a mask to check if it has to multiply by 2 if sleep or freeze != 0
    * the second uses another mask to check if it has to multiply by 1.5 if the other conditions != 0
    and somehow the Bit-Mask for checking the second part does not include the Bit for Toxic... like I said just an assumption.

    My big question is now, how do I find out where I even have to start to look at?
    How do I determine the starting point of the script - can I found out about that with any of the common binary hacking tools?
    I wouldn't have an issue crawling through some ASM, I just have to know where stuff begins and where it ends - even going so far as using the features provided in the emulator (using VBA-M atm) to see where the execution leads me.

    Cheers
     
    Last edited:
    My big question is now, how do I find out where I even have to start to look at?
    How do I determine the starting point of the script - can I found out about that with any of the common binary hacking tools?
    I wouldn't have an issue crawling through some ASM, I just have to know where stuff begins and where it ends - even going so far as using the features provided in the emulator (using VBA-M atm) to see where the execution leads me.

    Cheers

    By far the easiest way to make modifications like this to the game's code is to build your hack using the decomps as that allows you to directly access the game's code.
    In this case I believe you would just modify this line by uncommenting STATUS1_TOXIC_POISON.

    If you absolutely want to modify code with binary hacking, you could find the code you want to modify in the decomp and then look up the function's address in the symbol map to find the code.
     
    Wow, this is a super useful hint, thanks!
    I wasn't even too far off with my theory about the ANDs haha

    Yes, I would like to fix it using the binary hacking tools... taking advantage of the decomps to seek the addresses is OK with me.
    It's not only about fixing the issue, but also understanding what exactly went wrong in the ROM - just changing a line in a decomp and compiling again hasn't the same effect for me ^^

    OK, so I am not super deep into C/C++, but the symbols are just the translation between the names (variables, functions, etc.) and the offsets, right?
    The function this particular problem is in, is called "atkEF_handleballthrow".

    Big question is which symbol file I have to use... I am using the english european Ruby Revision 1 ... should be this, right?
    If correct, this tells me the following:
    0802b5b8 g 000003a8 atkEF_handleballthrow
    I have no clue what the columns are exactly, since there is no header, but I guess the first one is the address and the third is the length in bytes (probably?).
    The second column always changes between "g" and "l"... probably a declaration if it is a local or global function I would assume.

    So, given that I didn't get it wrong, this should mean that the code in the ROM (whose address offset is 0x08000000 per se) starts at 0x02b5b8 inside the ROM and is 0x3a8 (= 936 dec) bytes long - wouldn't seem to be completely off the table.

    Now, how do I look at the code behind that?
    What exactly is behind this address... ASM instructions or THUMB instructions... how do I know?

    XSE doesn't show anything with that offset at all - am I off with my detective work?

    Kind regards
     
    I forgot to mention another way to find the code in the rom: make your change in the decomp and compare the produced file to an unmodified rom to see what changed. This approach is useful for small changes that don't add or remove bytes, like changing the value of some constant (the bitmask in this situation).


    I have no clue what the columns are exactly, since there is no header, but I guess the first one is the address...
    It is and that's all you need to know.

    Now, how do I look at the code behind that?
    With any disassembler that supports the instruction set, like the one built into most emulators.

    What exactly is behind this address... ASM instructions or THUMB instructions... how do I know?
    THUMB instructions are assembly. Assuming you meant ARM/THUMB, you can disassemble the code as both and see which one looks like code and which one is utter nonsense. Practically all code in the gen 3 games is THUMB code.

    XSE doesn't show anything with that offset at all
    XSE is a tool for editing gamefreak's event scripts. It won't do much with anything else.
     
    Heyo everyone... here comes a blast from the past 😂
    After half a year I finally managed to complete the fix and also make a detailled video about it.
    Maybe some people here are interested in such technical stuff ^^

     
    Last edited:
    Back
    Top