Research & Development Got a well-founded knack with ROM hacking? Love reverse-engineering the Pokémon games? Or perhaps you love your assembly language. This is the spot for polling and gathering your ideas, and then implementing them! Share your hypothesis, get ideas from others, and collaborate to create!

Reply
 
Thread Tools
  #1    
Old August 5th, 2010 (7:02 AM). Edited August 10th, 2011 by metapod23.
metapod23's Avatar
metapod23 metapod23 is offline
Hardened Trainer
     
    Join Date: Mar 2009
    Gender: Male
    Nature: Timid
    Posts: 673
    For a while I was hoping to figure out a way to make a Pokemon disobedient, a sort of reverse of the setobedience command. I tried experimenting with Mew to see if there was anything in his code that would make him disobedient, but couldn't find anything, and I'm looking for more of the trade disobedience (occasionally sleeping, using other attacks, etc.).

    Can anyone tell me if there was a way to create a custom ASM routine to set a specific Pokemon in your party as disobedient? Could you find the setobedience command and just change a few things, and create your own routine for setting a Pokemon to disobedient no matter what its level and what badges you've obtained? Any insight would be appreciated. I know I don't understand much about ASM, but I'm willing to do whatever possible to get this in, and I'm hoping it won't be too difficult, considering there's a command already in the game that does almost the same thing, but the opposite.

    And now a solution to this problem. This code was made by colcolstyles, all credit goes to him:

    Quote:
    Originally Posted by colcolstyles View Post
    Code:
    .text
    .align 2
    .thumb
    .thumb_func
    .global hijack
    
    	@ put at 0x0801D404
    	@ also put 0x0000 at 0x081D402
    
    main:
    	ldr r1, .ADDRESS
    	bx r1
    
    .align 2
    .ADDRESS:
    	.word	0x08720001
    That branches off to the new routine at '0x720000' (that address can be changed) which is:

    Code:
    .text
    .align 2
    .thumb
    .thumb_func
    .global obedience
    
    main:
    	cmp r0, #0x97		@ if current attacker == Mew
    	beq disobey
    	cmp r0, #0x07		@ if current attacker == Squirtle
    	beq disobey
    	
    	mov r0, #0x01
    	ldr r1, .RESUME
    	bx r1
    	
    disobey:
    	ldr r1, .DISOBEY
    	bx r1
    	
    branchlink:
    	bx r3
    
    .align 2
    .RESUME:
    	.word	0x0801D42B
    .DISOBEY:
    	.word	0x0801D415	@ goes on to check obedient byte
    ^ Of course, you need to remove anything that says @ and whatever follows that - that's just explanation. With this you can make and Pokemon you want to be disobedient. It's really quite nifty.


    Here's another code you can apply. This one was designed by JPAN, all credit to him. This is a code causes certain Pokemon to be disobedient, but instead of being completely disobedient, they are also occasionally obedient. It actually gives you some incentive to train a disobedient Pokemon, which can add to the depth of the game.

    Code:
    .align 2
    .thumb
    /*to use this code, place 00 49 08 47 at 0x0801d3f4, and the reversed pointer to  where
    you put this code at 0x0801d3f8*/
        cmp r0, #0x5
        beq disobey_or_not
        cmp r0, #0x6 
        beq disobey_or_not    /*add more checks here for other pokemon*/
        ldr r1, mew_check
        bx r1
    mew_check:   .word 0x0801D403
    disobey_or_not: ldr r1, random_addr 
        ldrb r1, [r1]
        mov r0, #0xb4 /*change here the "perform attack" chance. percentage  is r0 divided by 256 times 100 */
        cmp r1, r0 /*aprox 70% chance of not performing an attack*/
        bgt is_obedient
        ldr r0, disobedient_ret_addr
        bx r0
    is_obedient:   mov r0, #0x1
        pop {r4-r7,pc}
    .hword 0x0000    
    random_addr: .word 0x03005000
    disobedient_ret_addr: .word 0x0801d415
    And now here's a code that allows you to choose when a Pokemon is and isn't obedient. With this code, you can set a Pokemon's obedience to a variable, and have it only obey when that variable is set. Pretty cool, right?

    All credit to this one goest to Jambo51:

    Code:
    .text
    .align 2
    .thumb
    .thumb_func
    .global obedience
     
    main:
        cmp r0, #0x97
        beq disobey
        cmp r0, #0x05
        beq disobey
        cmp r0, #0x06
        beq disobey
     
        mov r0, #0x01
        ldr r1, .RESUME
        bx r1
     
    disobey:
        ldr r0, =0x00006200 @the variable you want to use
        push {lr}
        bl vardecrypt
        pop {r1}
        mov lr, r1
        ldrh r0, [r0]
        cmp r0, #0x00
        beq disobey2
     
        mov r0, #0x01
        ldr r1, .RESUME
        bx r1
     
    disobey2:
        ldr r1, .DISOBEY
        bx r1
     
    resume:
        ldr r1, .RESUME
        bx r1
     
    vardecrypt:
        ldr r1, .VARDEC
        bx r1
     
    .align 2
    .RESUME:
        .word    0x0801D42B
    .DISOBEY:
        .word    0x0801D415
    .VARDEC:
        .word    0x0806E455
    Lastly, a code to make a Pokemon only sometimes disobey unless a certain variable is set:

    Special thanks to thank colcolstyles, Jambo51, and JPAN for working on this for me! Thanks!

    So here's the routine:

    First place 00 49 08 47 at 0x0801D3F4, and the reversed pointer to the code below at 0x0801D3F8 (per JPAN's routine).

    Code:
    .text
    .align 2
    .thumb
    .thumb_func
    .global obedience
     
    main:
        cmp r0, #0x97    @Mew's number, if you want it to disobey still
        beq disobey
        cmp r0, #0x05    @Pokemon you want to disobey only sometimes 
        beq disobey        (Charmeleon)
        cmp r0, #0x06    @Pokemon you want to disobey only sometimes         
        beq disobey        (Charizard)
        ldr r1, mew_check
        bx r1
    
    mew_check:
       .word 0x0801D403
     
    disobey:
        ldr r0, =0x00006199    @Variable you want to use
        push {lr}
        bl vardecrypt
        pop {r1}
        mov lr, r1
        ldrh r0, [r0]
        cmp r0, #0x00    @the value of the variable you want to cause the
        beq disobey2       Pokemon to sometimes disobey
         mov r0, #0x01
        ldr r1, .RESUME
        bx r1
    
    disobey2:
        ldr r1, random_addr 
        ldrb r1, [r1]
        mov r0, #0xcd    the number, divided by 256, that will be the
        cmp r1, r0          percentage of how often the Pokemon disobeys
        bgt is_obedient    (in this case, cd (205)/256 = 80% disobey)
        ldr r0, disobedient_ret_addr
        bx r0
     
    resume:
        ldr r1, .RESUME
        bx r1
     
    vardecrypt:
        ldr r1, .VARDEC
        bx r1
    
    is_obedient:   mov r0, #0x1
        pop {r4-r7,pc}
    .hword 0x0000
    
    .align 2
    .RESUME:
        .word    0x0801D42B
    .DISOBEY:
        .word    0x0801D415
    .VARDEC:
        .word    0x0806E455
    random_addr:
    	.word 0x03005000
    
    disobedient_ret_addr:
    	.word 0x0801d415
    __________________
    Reply With Quote

    Relevant Advertising!

      #2    
    Old August 6th, 2010 (3:37 PM).
    Darthatron's Avatar
    Darthatron Darthatron is offline
    巨大なトロール。
    • Silver Tier
     
    Join Date: Jan 2006
    Location: Melbourne, Australia
    Age: 25
    Gender: Male
    Nature: Modest
    Posts: 1,152
    Might I ask as to what game you are hacking?
    __________________
    あなた は しきしゃ です
    わたし は ばか です
    Reply With Quote
      #3    
    Old August 6th, 2010 (3:40 PM).
    metapod23's Avatar
    metapod23 metapod23 is offline
    Hardened Trainer
       
      Join Date: Mar 2009
      Gender: Male
      Nature: Timid
      Posts: 673
      Quote:
      Originally Posted by Darthatron View Post
      Might I ask as to what game you are hacking?
      Fire Red. It's for my AshGray hack. I want to my the player's Charmeleon/Charizard disobedient.
      __________________
      Reply With Quote
        #4    
      Old August 6th, 2010 (3:50 PM).
      Darthatron's Avatar
      Darthatron Darthatron is offline
      巨大なトロール。
      • Silver Tier
       
      Join Date: Jan 2006
      Location: Melbourne, Australia
      Age: 25
      Gender: Male
      Nature: Modest
      Posts: 1,152
      I can be bothered writing a routine... but... 0x02024284 contains Party Pokemon data. I'm 90% sure the Sanity byte controls the obedience...

      http://bulbapedia.bulbagarden.net/wiki/Pok%C3%A9mon_data_structure_in_Generation_III

      I'm not on a computer with anything on it right now, so I can't do anything...
      __________________
      あなた は しきしゃ です
      わたし は ばか です
      Reply With Quote
        #5    
      Old August 6th, 2010 (3:59 PM).
      metapod23's Avatar
      metapod23 metapod23 is offline
      Hardened Trainer
         
        Join Date: Mar 2009
        Gender: Male
        Nature: Timid
        Posts: 673
        Quote:
        Originally Posted by Darthatron View Post
        I can be bothered writing a routine... but... 0x02024284 contains Party Pokemon data. I'm 90% sure the Sanity byte controls the obedience...

        http://bulbapedia.bulbagarden.net/wiki/Pok%C3%A9mon_data_structure_in_Generation_III

        I'm not on a computer with anything on it right now, so I can't do anything...
        Okay, thank you, that should be helpful. It might be time for me to learn some basics about ASM. I know I can't expect anybody to do the work for me. Again, thanks.
        __________________
        Reply With Quote
          #6    
        Old August 6th, 2010 (5:01 PM).
        Samike360's Avatar
        Samike360 Samike360 is offline
        Lover of May
           
          Join Date: Mar 2009
          Location: ATL
          Gender:
          Nature: Bold
          Posts: 396
          Try this tutorial I found: http://sfc.pokefans.net/lesson.php?id=14

          I'm not sure if that's exactly what you're looking for, but it seems to be related to the issue.
          __________________





          Please warm my eggs...I'll be sure to return the favor

          From now one, if you haven't contacted me yet....I will not accept hacks unless they are at least in progressing hacks. So if you want my help, get some screenshots first.
          Reply With Quote
            #7    
          Old August 6th, 2010 (8:16 PM).
          metapod23's Avatar
          metapod23 metapod23 is offline
          Hardened Trainer
             
            Join Date: Mar 2009
            Gender: Male
            Nature: Timid
            Posts: 673
            Well, I know this isn't right, because it didn't work, and I'm still an ASM-newb, but my thinking was that you would load the "sanity byte" of, say, the first Pokemon in your party, and either subtract 1 or add 1 to it. I kind of figured the sanity byte would start at 0x0 or 0x1 and need to have a byte removed or added to make the Pokemon disobey. So I tried a very basic routine, going off of HackMew's Secret ID example in his tutorial:

            Code:
            .text
            .align 2
            .thumb
            .thumb_func
            .global lesson1
            
            main:
            	push {r0, lr}
            	ldr r0, .POKE_DATA
            	ldr r0, [r0]
            	ldrb r0, [r0, #0x13]
            	sub r0, #0x1
            	pop {r0, pc}
            
            
            .align 2
            .POKE_DATA:
            	.word 0x02024284
            And then I tried this:

            Code:
            .text
            .align 2
            .thumb
            .thumb_func
            .global lesson1
            
            main:
            	push {r0-r1, lr}
            	ldr r0, .POKE_DATA
            	ldr r0, [r0]
            	ldrb r0, [r0, #0x13]
            	mov r1, #0x1
            	strb r1, [r0]
            	pop {r0-r1, pc}
            
            
            .align 2
            .POKE_DATA:
            	.word 0x02024284
            In an attempt to simply change the byte itself to 0x0 or 0x1, but that didn't work either.

            I know it's not correct, but any advice on where to go from this, or if I should be going in a completely different direction. I might have to do something a lot more complicated that I'm not capable of yet ...
            __________________
            Reply With Quote
              #8    
            Old August 6th, 2010 (9:02 PM).
            colcolstyles's Avatar
            colcolstyles colcolstyles is offline
            Yours truly
            • Crystal Tier
             
            Join Date: May 2008
            Location: The Bay Area
            Gender: Male
            Nature: Lonely
            Posts: 1,584
            The data at '0x02024284' is not a pointer. Because of this, the "ldr r0, [r0]" on the third line of each routine is unnecessary. It was needed in the Secret ID case because the trainer's data is moved around in-game and so in order to find it, you needed to load the pointer at an address and then subsequently load the data at that second pointer. It's kind of confusing and difficult to explain but if you remove the line that I told you to, you should hopefully have a little more success.
            __________________

            Brother of Vrai
            Reply With Quote
              #9    
            Old August 7th, 2010 (12:54 AM).
            Darthatron's Avatar
            Darthatron Darthatron is offline
            巨大なトロール。
            • Silver Tier
             
            Join Date: Jan 2006
            Location: Melbourne, Australia
            Age: 25
            Gender: Male
            Nature: Modest
            Posts: 1,152
            Pro tip: Before you start making a routine, you need to observe the data.
            __________________
            あなた は しきしゃ です
            わたし は ばか です
            Reply With Quote
              #10    
            Old August 7th, 2010 (5:18 AM). Edited August 7th, 2010 by metapod23.
            metapod23's Avatar
            metapod23 metapod23 is offline
            Hardened Trainer
               
              Join Date: Mar 2009
              Gender: Male
              Nature: Timid
              Posts: 673
              Quote:
              Originally Posted by colcolstyles View Post
              The data at '0x02024284' is not a pointer. Because of this, the "ldr r0, [r0]" on the third line of each routine is unnecessary. It was needed in the Secret ID case because the trainer's data is moved around in-game and so in order to find it, you needed to load the pointer at an address and then subsequently load the data at that second pointer. It's kind of confusing and difficult to explain but if you remove the line that I told you to, you should hopefully have a little more success.
              I removed it and tried it again for both routines, but the Pokemon still seems to obey. Thanks for the help, though.

              Quote:
              Originally Posted by Darthatron View Post
              Pro tip: Before you start making a routine, you need to observe the data.
              Do you mean like the debugging part of HackMew's tutorial?


              EDIT: According to this:

              http://bulbapedia.bulbagarden.net/wiki/User:Kyoufu_Kawa#Font_and_Sanity

              The sanity byte has to do with whether the Pokemon is an egg or not.

              Quote:
              The sanity byte determines if the individual is an egg. Zero and 2 are a regular monster, 1, 3-5 are Bad EGGs but can be changed back, 6 makes the game write "EGG" instead of the monster's nickname but doesn't actually make it an egg and 7 is the actual Bad EGG. When you break the checksum, the sanity byte is set to 7. This persists! Several actions in the game (see below) make it check for Bad EGGs and keep resetting the byte to 7, for example stepping into tall grass and opening the party screen. Good luck turning the Bad EGG back into a real monster. Note that only the first few bits matter so the pattern repeats after 7.
              I did a test with a new routine and was able to determine that in my game, with Pikachu as my only Pokemon, Pikachu's sanity byte was 2 - which according to this makes it a regular monster.

              So does this mean that the sanity byte doesn't control obedience?



              EDIT 2: I was trying out the debugger thing and I thought of something. Since you can view what's going on with custom routines, if I had the offset for the setobedience routine that's in the game, could I theoretically view that and see what it's dealing with? If I could see that, then I could use the same things for my custom routine, right? So if that's the case, how could I go about figuring out what the offset for the setobedience command is?
              __________________
              Reply With Quote
                #11    
              Old August 7th, 2010 (8:02 AM).
              Iacobus's Avatar
              Iacobus Iacobus is offline
              sǝɯɐɾ
                 
                Join Date: Dec 2003
                Location: Belgium
                Age: 25
                Gender: Male
                Posts: 62
                As you said yourself, the fact that your Pokémon obeys you is related to it's level and the number of badges you have. So, one could say that, before you attack, the game does a little calculation which takes the highest 'badge-flag' and the Pokémon level into account.
                What one should do is find the routine that checks if the Pokémon obeys or not and eventually add another check. For example: One could use an unused bit in the Pokémon data and use this as a flag.
                Reply With Quote
                  #12    
                Old August 7th, 2010 (8:34 AM).
                metapod23's Avatar
                metapod23 metapod23 is offline
                Hardened Trainer
                   
                  Join Date: Mar 2009
                  Gender: Male
                  Nature: Timid
                  Posts: 673
                  Quote:
                  Originally Posted by Iacobus View Post
                  What one should do is find the routine that checks if the Pokémon obeys or not and eventually add another check. For example: One could use an unused bit in the Pokémon data and use this as a flag.
                  It's something I'm willing to do, but how? How would I find that original routine? Is it in the party Pokemon data? And if it's not the "Sanity Byte," what is it?
                  __________________
                  Reply With Quote
                    #13    
                  Old August 7th, 2010 (9:20 AM).
                  Iacobus's Avatar
                  Iacobus Iacobus is offline
                  sǝɯɐɾ
                     
                    Join Date: Dec 2003
                    Location: Belgium
                    Age: 25
                    Gender: Male
                    Posts: 62
                    Quote:
                    Originally Posted by metapod23 View Post
                    It's something I'm willing to do, but how? How would I find that original routine? Is it in the party Pokemon data? And if it's not the "Sanity Byte," what is it?
                    Well, I surely trust Kawa's research. Which means that the "Sanity Byte" means exactly this:
                    Quote:
                    The sanity byte determines if the individual is an egg. Zero and 2 are a regular monster, 1, 3-5 are Bad EGGs but can be changed back, 6 makes the game write "EGG" instead of the monster's nickname but doesn't actually make it an egg and 7 is the actual Bad EGG. When you break the checksum, the sanity byte is set to 7. This persists! Several actions in the game (see below) make it check for Bad EGGs and keep resetting the byte to 7, for example stepping into tall grass and opening the party screen. Good luck turning the Bad EGG back into a real monster. Note that only the first few bits matter so the pattern repeats after 7.
                    (Sure there is the possibility he made a mistake.)

                    Anyway, how I would try to find this routine you need to expand is, well..
                    The game displays a message when the Pokémon isn't willing to obey you, right?
                    I would try to find out when that message is loaded and like so work my way back and find the actual routine that does the 'check'.
                    Also, if indeed the "Sanity Byte's" pattern repeats after 7, you could easily use a bit from that byte for the new 'flag'. At least I think you could.
                    __________________
                    Reply With Quote
                      #14    
                    Old August 7th, 2010 (9:45 AM). Edited August 7th, 2010 by metapod23.
                    metapod23's Avatar
                    metapod23 metapod23 is offline
                    Hardened Trainer
                       
                      Join Date: Mar 2009
                      Gender: Male
                      Nature: Timid
                      Posts: 673
                      Quote:
                      Originally Posted by Iacobus View Post
                      Well, I surely trust Kawa's research. Which means that the "Sanity Byte" means exactly this:
                      (Sure there is the possibility he made a mistake.)

                      Anyway, how I would try to find this routine you need to expand is, well..
                      The game displays a message when the Pokémon isn't willing to obey you, right?
                      I would try to find out when that message is loaded and like so work my way back and find the actual routine that does the 'check'.
                      Also, if indeed the "Sanity Byte's" pattern repeats after 7, you could easily use a bit from that byte for the new 'flag'. At least I think you could.
                      Okay, that's a start. I'll see what I can do ...

                      EDIT: The following messages should be located at these offsets:

                      (Pokemon) ignored orders while asleep! - 0x3FD0F1
                      - The pointer to this message is at 0x3FE358

                      (Pokemon) ignored orders! - 0x3FD111
                      - The pointer to this message is at 0x3FE35C

                      (Pokemon) pretended not to notice! - 0x3FD16A
                      - The pointer to this message is at 0x3FE370

                      That's the end of the pointers. Not sure what I could do from here.
                      __________________
                      Reply With Quote
                        #15    
                      Old August 7th, 2010 (9:57 AM).
                      colcolstyles's Avatar
                      colcolstyles colcolstyles is offline
                      Yours truly
                      • Crystal Tier
                       
                      Join Date: May 2008
                      Location: The Bay Area
                      Gender: Male
                      Nature: Lonely
                      Posts: 1,584
                      Oh wow. When I looked at your routines earlier, I just skimmed over them real briefly and then pointed out the first error that I saw. There are a bunch more too.

                      First of all, the first routine does absolutely nothing. It loads a byte from some address, subtracts one from it... and then restores the previous condition without changing anything. As for the second routine, if all you're trying to do is store '0x01' at '0x02024284', then all you need is the following (excluding push and pop):
                      Code:
                      ldr r0, .POKE_DATA
                      mov r1, #0x01
                      strb r1, [r0, #0x00]
                      Before, you weren't actually writing to the POKE_DATA. That's why you didn't notice any change.

                      Also, it was my understanding that a Pokémon was deemed an egg by setting one of the top two bits in the IV word. I could be mistaken, though.
                      __________________

                      Brother of Vrai
                      Reply With Quote
                        #16    
                      Old August 7th, 2010 (10:14 AM).
                      metapod23's Avatar
                      metapod23 metapod23 is offline
                      Hardened Trainer
                         
                        Join Date: Mar 2009
                        Gender: Male
                        Nature: Timid
                        Posts: 673
                        Quote:
                        Originally Posted by colcolstyles View Post
                        Oh wow. When I looked at your routines earlier, I just skimmed over them real briefly and then pointed out the first error that I saw. There are a bunch more too.

                        First of all, the first routine does absolutely nothing. It loads a byte from some address, subtracts one from it... and then restores the previous condition without changing anything. As for the second routine, if all you're trying to do is store '0x01' at '0x02024284', then all you need is the following (excluding push and pop):
                        Code:
                        ldr r0, .POKE_DATA
                        mov r1, #0x01
                        strb r1, [r0, #0x00]
                        Before, you weren't actually writing to the POKE_DATA. That's why you didn't notice any change.

                        Also, it was my understanding that a Pokémon was deemed an egg by setting one of the top two bits in the IV word. I could be mistaken, though.
                        Well, yeah, I did mention that I'm an ASM-newb, right?

                        But no, I'm not storing 0x0 at that offset. That's only the beginning of the offset for the first Pokemon's data. I need to store it where the sanity byte is, which is (if I'm understanding correctly) 19 bytes (13 in hex) after that, which is why I had "ldrb r0, [r0, #0x13]" there.
                        __________________
                        Reply With Quote
                          #17    
                        Old August 7th, 2010 (11:17 AM).
                        Counterbug Counterbug is offline
                           
                          Join Date: Jun 2010
                          Gender: Male
                          Posts: 1
                          I think you could find out more if you use the vba-sdl-h to set breakpoints, when the disobedience thing triggers.
                          Reply With Quote
                            #18    
                          Old August 7th, 2010 (11:22 AM).
                          metapod23's Avatar
                          metapod23 metapod23 is offline
                          Hardened Trainer
                             
                            Join Date: Mar 2009
                            Gender: Male
                            Nature: Timid
                            Posts: 673
                            Quote:
                            Originally Posted by Counterbug View Post
                            I think you could find out more if you use the vba-sdl-h to set breakpoints, when the disobedience thing triggers.
                            What should I define as the breakpoints, though?
                            __________________
                            Reply With Quote
                              #19    
                            Old August 7th, 2010 (11:24 AM).
                            colcolstyles's Avatar
                            colcolstyles colcolstyles is offline
                            Yours truly
                            • Crystal Tier
                             
                            Join Date: May 2008
                            Location: The Bay Area
                            Gender: Male
                            Nature: Lonely
                            Posts: 1,584
                            One step ahead of you. :)

                            Well I've been slowly making my way through the assembly code for the 'setobedience' command and though I haven't figured it out yet, I've been following some values through the system and it looks like the game is trying to access the "Data" substructure of my Squirtle's data. I'll update this post once I figure out which block gets accessed and, from there, what piece of data exactly gets modified.
                            __________________

                            Brother of Vrai
                            Reply With Quote
                              #20    
                            Old August 7th, 2010 (11:37 AM).
                            metapod23's Avatar
                            metapod23 metapod23 is offline
                            Hardened Trainer
                               
                              Join Date: Mar 2009
                              Gender: Male
                              Nature: Timid
                              Posts: 673
                              Quote:
                              Originally Posted by colcolstyles View Post
                              One step ahead of you.

                              Well I've been slowly making my way through the assembly code for the 'setobedience' command and though I haven't figured it out yet, I've been following some values through the system and it looks like the game is trying to access the "Data" substructure of my Squirtle's data. I'll update this post once I figure out which block gets accessed and, from there, what piece of data exactly gets modified.
                              Oh, wow! Thank you so much! I really do appreciate the help.
                              __________________
                              Reply With Quote
                                #21    
                              Old August 7th, 2010 (12:42 PM).
                              colcolstyles's Avatar
                              colcolstyles colcolstyles is offline
                              Yours truly
                              • Crystal Tier
                               
                              Join Date: May 2008
                              Location: The Bay Area
                              Gender: Male
                              Nature: Lonely
                              Posts: 1,584
                              Sorry for the delay. The game uses a very long and inefficient way to perform the modulo operation and it does it about 6 times before it actually starts to edit anything. D:

                              Well from what I can tell, the game is editing the last byte of the Growth substructure. There is no documentation on that piece of data which means that is possible that it controls obedience. The guy who wrote that article seems to think that it's a halfword (16-bit) but the game reads from it using ldrb so I'm guessing that it is actually two bytes. The 'setobedience' command takes whatever value is stored there, 'and's it with '0x7F' (i.e., clears the most significant bit), 'orr's that with some other value (it was '0x80' for me) and then stores the final result back in the Growth substructure. I'll look more into it later but right now I have to go run a few errands. If anyone's interested, the routine that does what I mentioned above is located at '0x08040A82'.
                              __________________

                              Brother of Vrai
                              Reply With Quote
                                #22    
                              Old August 7th, 2010 (1:24 PM). Edited August 7th, 2010 by metapod23.
                              metapod23's Avatar
                              metapod23 metapod23 is offline
                              Hardened Trainer
                                 
                                Join Date: Mar 2009
                                Gender: Male
                                Nature: Timid
                                Posts: 673
                                Quote:
                                Originally Posted by colcolstyles View Post
                                Sorry for the delay. The game uses a very long and inefficient way to perform the modulo operation and it does it about 6 times before it actually starts to edit anything. D:

                                Well from what I can tell, the game is editing the last byte of the Growth substructure. There is no documentation on that piece of data which means that is possible that it controls obedience. The guy who wrote that article seems to think that it's a halfword (16-bit) but the game reads from it using ldrb so I'm guessing that it is actually two bytes. The 'setobedience' command takes whatever value is stored there, 'and's it with '0x7F' (i.e., clears the most significant bit), 'orr's that with some other value (it was '0x80' for me) and then stores the final result back in the Growth substructure. I'll look more into it later but right now I have to go run a few errands. If anyone's interested, the routine that does what I mentioned above is located at '0x08040A82'.
                                That's interesting, thanks. Don't worry about delays, take your time. I appreciate the effort.

                                Oh, and I thought that ldrb was for reading one byte, and that two bytes = 16 bits. So if the game uses ldrb, it's only loading one byte?
                                __________________
                                Reply With Quote
                                  #23    
                                Old August 7th, 2010 (1:48 PM). Edited August 7th, 2010 by colcolstyles.
                                colcolstyles's Avatar
                                colcolstyles colcolstyles is offline
                                Yours truly
                                • Crystal Tier
                                 
                                Join Date: May 2008
                                Location: The Bay Area
                                Gender: Male
                                Nature: Lonely
                                Posts: 1,584
                                Quote:
                                Originally Posted by metapod23 View Post
                                Oh, and I thought that ldrb was for reading one byte, and that two bytes = 16 bits. So if the game uses ldrb, it's only loading one byte?
                                I'm sorry, I should have been more clear. The Bulbapedia article says that the last two bytes of the Growth substructure are unknown. It groups them together as one halfword. However, because the game reads from that data in bytes, I'm guessing that instead the "unknown halfword" is actually two unknown bytes (though it might be safe to say that the second byte is no longer unknown).

                                I'm going to go do a little more research on that byte. Perhaps by looking at Mew's data (who I've heard is disobedient unless obtained legally or something like that) I can figure out if there's a certain value which makes a pokémon disobedient.


                                edit: At '0x0801D402' the game checks if the player's pokémon is Mew. I expanded the routine to add a check for Squirtle (which was the only other pokémon I had in my party at the time). And look what I got:
                                Spoiler:


                                In an unedited ROM, all pokémon except Mew will always obey the player unless they don't have enough badges (but I didn't look up those routines). If the player is using a Mew, it checks the top bit of the last byte in the Growth Structure. If it is set, then Mew will obey. If not, then Mew won't obey. By default, all pokémon don't have that bit set but because it isn't checked, it doesn't matter. However, in order to get Mew to obey, you need to use the 'setobedience' command to set that bit, unless you want to do the work of decrypting the Pokémon data and then recalculating the checksum. Once you use 'setobedience', Mew/Squirtle will start to obey again:
                                Spoiler:


                                Because I'm a nice guy, here's the code:

                                Code:
                                .text
                                .align 2
                                .thumb
                                .thumb_func
                                .global hijack
                                
                                	@ put at 0x0801D404
                                	@ also put 0x0000 at 0x081D402
                                
                                main:
                                	ldr r1, .ADDRESS
                                	bx r1
                                
                                .align 2
                                .ADDRESS:
                                	.word	0x08720001
                                That branches off to the new routine at '0x720000' (that address can be changed) which is:

                                Code:
                                .text
                                .align 2
                                .thumb
                                .thumb_func
                                .global obedience
                                
                                main:
                                	cmp r0, #0x97		@ if current attacker == Mew
                                	beq disobey
                                	cmp r0, #0x07		@ if current attacker == Squirtle
                                	beq disobey
                                	
                                	mov r0, #0x01
                                	ldr r1, .RESUME
                                	bx r1
                                	
                                disobey:
                                	ldr r1, .DISOBEY
                                	bx r1
                                	
                                branchlink:
                                	bx r3
                                
                                .align 2
                                .RESUME:
                                	.word	0x0801D42B
                                .DISOBEY:
                                	.word	0x0801D415	@ goes on to check obedient byte
                                Obviously, you should change #0x07 to #0x06 for Charizard. That should do the trick.
                                __________________

                                Brother of Vrai
                                Reply With Quote
                                  #24    
                                Old August 7th, 2010 (3:00 PM).
                                Pia Carrot's Avatar
                                Pia Carrot Pia Carrot is offline
                                Kick it
                                • Silver Tier
                                 
                                Join Date: Aug 2010
                                Age: 21
                                Gender: Male
                                Nature: Adamant
                                Posts: 712
                                Perhaps researching what makes herbs/roots make your pokemon happiness go down may help? or maybe gym badges (pokemon up to lvl 30 can obey you)

                                hope it helps.
                                Reply With Quote
                                  #25    
                                Old August 7th, 2010 (4:33 PM). Edited August 7th, 2010 by metapod23.
                                metapod23's Avatar
                                metapod23 metapod23 is offline
                                Hardened Trainer
                                   
                                  Join Date: Mar 2009
                                  Gender: Male
                                  Nature: Timid
                                  Posts: 673
                                  Quote:
                                  Originally Posted by colcolstyles View Post
                                  I'm sorry, I should have been more clear. The Bulbapedia article says that the last two bytes of the Growth substructure are unknown. It groups them together as one halfword. However, because the game reads from that data in bytes, I'm guessing that instead the "unknown halfword" is actually two unknown bytes (though it might be safe to say that the second byte is no longer unknown).

                                  I'm going to go do a little more research on that byte. Perhaps by looking at Mew's data (who I've heard is disobedient unless obtained legally or something like that) I can figure out if there's a certain value which makes a pokémon disobedient.


                                  edit: At '0x0801D402' the game checks if the player's pokémon is Mew. I expanded the routine to add a check for Squirtle (which was the only other pokémon I had in my party at the time). And look what I got:
                                  Spoiler:


                                  In an unedited ROM, all pokémon except Mew will always obey the player unless they don't have enough badges (but I didn't look up those routines). If the player is using a Mew, it checks the top bit of the last byte in the Growth Structure. If it is set, then Mew will obey. If not, then Mew won't obey. By default, all pokémon don't have that bit set but because it isn't checked, it doesn't matter. However, in order to get Mew to obey, you need to use the 'setobedience' command to set that bit, unless you want to do the work of decrypting the Pokémon data and then recalculating the checksum. Once you use 'setobedience', Mew/Squirtle will start to obey again:
                                  Spoiler:


                                  Because I'm a nice guy, here's the code:

                                  Code:
                                  .text
                                  .align 2
                                  .thumb
                                  .thumb_func
                                  .global hijack
                                  
                                  	@ put at 0x0801D404
                                  	@ also put 0x0000 at 0x081D402
                                  
                                  main:
                                  	ldr r1, .ADDRESS
                                  	bx r1
                                  
                                  .align 2
                                  .ADDRESS:
                                  	.word	0x08720001
                                  That branches off to the new routine at '0x720000' (that address can be changed) which is:

                                  Code:
                                  .text
                                  .align 2
                                  .thumb
                                  .thumb_func
                                  .global obedience
                                  
                                  main:
                                  	cmp r0, #0x97		@ if current attacker == Mew
                                  	beq disobey
                                  	cmp r0, #0x07		@ if current attacker == Squirtle
                                  	beq disobey
                                  	
                                  	mov r0, #0x01
                                  	ldr r1, .RESUME
                                  	bx r1
                                  	
                                  disobey:
                                  	ldr r1, .DISOBEY
                                  	bx r1
                                  	
                                  branchlink:
                                  	bx r3
                                  
                                  .align 2
                                  .RESUME:
                                  	.word	0x0801D42B
                                  .DISOBEY:
                                  	.word	0x0801D415	@ goes on to check obedient byte
                                  Obviously, you should change #0x07 to #0x06 for Charizard. That should do the trick.
                                  You're a saint! lol!

                                  Thank you very much. I really do appreciate it. I'm gonna test it out and then post the code with credit in the first post of the thread.

                                  EDIT: Might I ask something?

                                  In your post you said that 0x0801D415 goes on to check the obedience byte? What I'd really like to do is have a code to change an individual Pokemon obedience byte. So presumably an obedient byte does exist then? While having the Mew type of disobedience would work, I'd prefer it to be more like the traded-overtrained disobedience, where the Pokemon falls asleep, and refused to attack. With the Mew disobedience, Mew simply doesn't do anything, I believe. Maybe if I do checkobedience and use 0x0801D415 as a breakpoint I could figure it out?

                                  Oh, and I'm dumb, so I don't know how to insert the first code into the game properly. Do I copy the code to a specific offset once it's assembled? Or maybe there's a way to assemble it I don't know, since there's a command to tell it where to put it in the code itself. Right now, all I really know is the "thumb" command to create the hex script to be inserted ...

                                  EDIT2: Never mind - got it to work. Had to copy the code 0x1d415. And as HackMew said in the post after this one, only Mew and Deoxys do the complete disobedience thing. I just tried it with Charizard and it worked perfectly.

                                  The last thing I'd like to know is I can undo the setobedience command? See, I kind of want to make Charizard obedient for a bit, then make it disobedient again, then make it obedient once more later. Possible?
                                  __________________
                                  Reply With Quote
                                  Reply
                                  Quick Reply

                                  Sponsored Links
                                  Thread Tools

                                  Posting Rules
                                  You may not post new threads
                                  You may not post replies
                                  You may not post attachments
                                  You may not edit your posts

                                  BB code is On
                                  Smilies are On
                                  [IMG] code is On
                                  HTML code is Off

                                  Forum Jump


                                  All times are GMT -8. The time now is 7:46 PM.