PDA

View Full Version : Development: Set Disobedience


metapod23
August 5th, 2010, 07:02 AM
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:

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

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

.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? :cool:

All credit to this one goest to Jambo51:

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

.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

Darthatron
August 6th, 2010, 03:37 PM
Might I ask as to what game you are hacking?

metapod23
August 6th, 2010, 03:40 PM
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.

Darthatron
August 6th, 2010, 03:50 PM
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...

metapod23
August 6th, 2010, 03:59 PM
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.

Samike360
August 6th, 2010, 05:01 PM
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.

metapod23
August 6th, 2010, 08:16 PM
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:

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

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

colcolstyles
August 6th, 2010, 09:02 PM
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.

Darthatron
August 7th, 2010, 12:54 AM
Pro tip: Before you start making a routine, you need to observe the data.

metapod23
August 7th, 2010, 05:18 AM
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.

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.

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?

Iacobus
August 7th, 2010, 08:02 AM
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.

metapod23
August 7th, 2010, 08:34 AM
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?

Iacobus
August 7th, 2010, 09:20 AM
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:
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.

metapod23
August 7th, 2010, 09:45 AM
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.

colcolstyles
August 7th, 2010, 09:57 AM
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):
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.

metapod23
August 7th, 2010, 10:14 AM
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):
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? :embarrass

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.

Counterbug
August 7th, 2010, 11:17 AM
I think you could find out more if you use the vba-sdl-h to set breakpoints, when the disobedience thing triggers.
(http://www.pokecommunity.com/showthread.php?p=6046141#post6046141)

metapod23
August 7th, 2010, 11:22 AM
I think you could find out more if you use the vba-sdl-h to set breakpoints, when the disobedience thing triggers.
(http://www.pokecommunity.com/showthread.php?p=6046141#post6046141)

What should I define as the breakpoints, though?

colcolstyles
August 7th, 2010, 11:24 AM
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.

metapod23
August 7th, 2010, 11:37 AM
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. :)

colcolstyles
August 7th, 2010, 12:42 PM
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 (http://bulbapedia.bulbagarden.net/wiki/Pokémon_data_substructures_in_the_GBA). 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'.

metapod23
August 7th, 2010, 01:24 PM
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 (http://bulbapedia.bulbagarden.net/wiki/Pokémon_data_substructures_in_the_GBA). 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?

colcolstyles
August 7th, 2010, 01:48 PM
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:
http://homepage.mac.com/loristyles/.Pictures/disobey.png

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:
http://homepage.mac.com/loristyles/.Pictures/obey.png

Because I'm a nice guy, here's the 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:

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

Pia Carrot
August 7th, 2010, 03:00 PM
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.

metapod23
August 7th, 2010, 04:33 PM
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:
http://homepage.mac.com/loristyles/.Pictures/disobey.png

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:
http://homepage.mac.com/loristyles/.Pictures/obey.png

Because I'm a nice guy, here's the 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:

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

JPAN
August 7th, 2010, 06:08 PM
The disobedience check is part of the BattleScript commands, namely command 0, that checks what the pokemon will do. The actual obedience check is at 0801D438, covering all types of disobedience. The code checks for the obedience flag first, then proceeds to check for badges and levels. I'll post here the relevant piece of code for this matter:
ROM:0801D460 BL Disobey_byte_check ;decompiled below, the code that was talked about earlier
ROM:0801D464 CMP R0, #0
ROM:0801D466 BEQ loc_801D4BE
ROM:0801D468 LDR R2, =0x2023BE4
ROM:0801D46A LDRB R1, [R4]
ROM:0801D46C MOVS R0, #0x58
ROM:0801D46E MULS R1, R0
ROM:0801D470 MOVS R0, R2
ROM:0801D472 ADDS R0, #0x54
ROM:0801D474 ADDS R0, R1, R0
ROM:0801D476 LDR R0, [R0]
ROM:0801D478 ADDS R2, #0x3C
ROM:0801D47A ADDS R1, R1, R2

ROM:0801D47C BL Compare_trainer_values ;compares your trainer IDS with the pokemon trainer IDS
ROM:0801D480 LSLS R0, R0, #0x18
ROM:0801D482 CMP R0, #0
ROM:0801D484 BEQ loc_801D4F4 ;the same, is obedient
;from here on it's the badge checks. R6 is the maximum level the pokemon may have
ROM:0801D486 LDR R0, =0x827
ROM:0801D488 BL Check_active_flag
ROM:0801D48C LSLS R0, R0, #0x18
ROM:0801D48E CMP R0, #0
ROM:0801D490 BNE loc_801D4F4 ;earthbadge on = obedience

ROM:0801D492 MOVS R6, #0xA
ROM:0801D494 LDR R0, =0x821
ROM:0801D496 BL Check_active_flag
ROM:0801D49A LSLS R0, R0, #0x18
ROM:0801D49C CMP R0, #0
ROM:0801D49E BEQ loc_801D4A2

ROM:0801D4A0 MOVS R6, #0x1E
ROM:0801D4A2
ROM:0801D4A2 loc_801D4A2 ; CODE XREF: Disobedience_check+66j
ROM:0801D4A2 LDR R0, =0x823
ROM:0801D4A4 BL Check_active_flag
ROM:0801D4A8 LSLS R0, R0, #0x18
ROM:0801D4AA CMP R0, #0
ROM:0801D4AC BEQ loc_801D4B0

ROM:0801D4AE MOVS R6, #0x32
ROM:0801D4B0
ROM:0801D4B0 loc_801D4B0 ; CODE XREF: Disobedience_check+74j
ROM:0801D4B0 LDR R0, =0x825
ROM:0801D4B2 BL Check_active_flag
ROM:0801D4B6 LSLS R0, R0, #0x18
ROM:0801D4B8 CMP R0, #0
ROM:0801D4BA BEQ loc_801D4BE

ROM:0801D4BC MOVS R6, #0x46
ROM:0801D4BE
ROM:0801D4BE loc_801D4BE ; CODE XREF: Disobedience_check+2Ej
ROM:0801D4BE ; Disobedience_check+82j
ROM:0801D4BE LDR R5, =0x2023BE4
ROM:0801D4C0 LDR R0, =0x2023D6B
ROM:0801D4C2 MOV R8, R0
ROM:0801D4C4 LDRB R0, [R0]
ROM:0801D4C6 MOVS R7, #0x58
ROM:0801D4C8 MULS R0, R7
ROM:0801D4CA ADDS R0, R0, R5
ROM:0801D4CC ADDS R0, #0x2A
ROM:0801D4CE LDRB R0, [R0] ;gets pokemon current level
ROM:0801D4D0 CMP R0, R6
ROM:0801D4D2 BLS loc_801D4F4 ;if current level <= max level, is obedient

ROM:0801D4D4 BL RNG_halfword
ROM:0801D4D8 MOVS R1, #0xFF
ROM:0801D4DA ANDS R1, R0
ROM:0801D4DC MOV R2, R8
ROM:0801D4DE LDRB R0, [R2]
ROM:0801D4E0 MOVS R2, R0
ROM:0801D4E2 MULS R2, R7
ROM:0801D4E4 ADDS R0, R2, R5
ROM:0801D4E6 ADDS R0, #0x2A
ROM:0801D4E8 LDRB R0, [R0]
ROM:0801D4EA ADDS R0, R0, R6
ROM:0801D4EC MULS R0, R1
ROM:0801D4EE ASRS R4, R0, #8
ROM:0801D4F0 CMP R4, R6
ROM:0801D4F2 BGE loc_801D518
ROM:0801D4F4
ROM:0801D4F4 loc_801D4F4 ; CODE XREF: Disobedience_check+14j
ROM:0801D4F4 ; Disobedience_check+24j ...
ROM:0801D4F4 MOVS R0, #0
ROM:0801D4F6 B loc_801D738

Disobey_byte_check ; CODE XREF: Disobedience_check+28p
ROM:0801D3C0 PUSH {R4-R7,LR}
ROM:0801D3C2 LSLS R0, R0, #0x18
ROM:0801D3C4 LSRS R4, R0, #0x18
ROM:0801D3C6 MOVS R0, R4
ROM:0801D3C8 BL sub_80751C4
ROM:0801D3CC LSLS R0, R0, #0x18
ROM:0801D3CE LSRS R0, R0, #0x18
ROM:0801D3D0 CMP R0, #1
ROM:0801D3D2 BEQ loc_801D406
ROM:0801D3D4 LDR R0, =0x2023BCE
ROM:0801D3D6 LSLS R4, R4, #1
ROM:0801D3D8 ADDS R5, R4, R0
ROM:0801D3DA LDRH R0, [R5]
ROM:0801D3DC MOVS R7, #0x64
ROM:0801D3DE MULS R0, R7
ROM:0801D3E0 LDR R6, =0x2024284
ROM:0801D3E2 ADDS R0, R0, R6
ROM:0801D3E4 MOVS R1, #0xB
ROM:0801D3E6 MOVS R2, #0
ROM:0801D3E8 BL get_party_status ;get pokemon species
ROM:0801D3EC MOVS R1, 0x19A ;compares with deoxys
ROM:0801D3F0 CMP R0, R1
ROM:0801D3F2 BEQ loc_801D414 ; if so, check obedience flag

ROM:0801D3F4 LDRH R0, [R5]
ROM:0801D3F6 MULS R0, R7
ROM:0801D3F8 ADDS R0, R0, R6
ROM:0801D3FA MOVS R1, #0xB
ROM:0801D3FC MOVS R2, #0
ROM:0801D3FE BL get_party_status ; redundant, checks your pokemon again for its species
ROM:0801D402 CMP R0, #0x97
ROM:0801D404 BEQ loc_801D414 ;if mew, check for obedience
ROM:0801D406
ROM:0801D406 loc_801D406 ; CODE XREF: Disobey_byte_check+12j
ROM:0801D406 MOVS R0, #1
ROM:0801D408 B loc_801D42A ; is obedient, end
ROM:0801D408 ; ---------------------------------------------------------------------------
ROM:0801D40A DCB 0
ROM:0801D40B DCB 0
ROM:0801D40C dword_801D40C DCD 0x2023BCE ; DATA XREF: Disobey_byte_check+14r
ROM:0801D410 dword_801D410 DCD 0x2024284 ; DATA XREF: Disobey_byte_check+20r
ROM:0801D414 ; ---------------------------------------------------------------------------
ROM:0801D414
ROM:0801D414 loc_801D414 ; CODE XREF: Disobey_byte_check+32j
ROM:0801D414 ; Disobey_byte_check+44j
ROM:0801D414 LDR R0, =0x2023BCE
ROM:0801D416 ADDS R0, R4, R0
ROM:0801D418 LDRH R1, [R0]
ROM:0801D41A MOVS R0, #0x64
ROM:0801D41C MULS R0, R1
ROM:0801D41E LDR R1, =0x2024284
ROM:0801D420 ADDS R0, R0, R1
ROM:0801D422 MOVS R1, #0x50
ROM:0801D424 MOVS R2, #0
ROM:0801D426 BL get_party_status ;checks last ribbon, that is the obedience flag, and returns it
ROM:0801D42A
ROM:0801D42A loc_801D42A ; CODE XREF: Disobey_byte_check+48j
ROM:0801D42A POP {R4-R7}
ROM:0801D42C POP {R1}
ROM:0801D42E BX R1


0801D4D4 checks one last time if, by chance, the attack will go trough. If not it will proceed to 0x0801d518, where what will the pokemon actually do\say is calculated.
So, several modifications can be made here to change the level a pokemon will become disobedient and in what conditions will it become disobedient.
The location of the obedience flag is actually in the last part of the Ribbon data in the Misc block, the topmost flag (bit 31 of the Ribbon word), but it's only useful for the species listed on the disobedience byte. And as for why Mew\Deoxys only disobey, it's because the chance of attack is determined by a random number (from 0-ff) to be smaller than the max level (that in the byte case is 0).

Edit: If I understood correctly, the code needed here is one that, if a pokemon doesn't have the flag, the pokemon has some chances of attacking, instead of just laying around all the time. With that in mind, I made a code for the occasion
.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
The trick in that code is that the pokemon will act as if it was obedient every once in a while thanks to the random number stored at 0x03005000.

metapod23
August 7th, 2010, 07:49 PM
^ That's an interesting code, JPAN. I might have to try it out. I think it might be useful to have the disobedient Pokemon attack every once in a while. I'll add it to the main page, too.

Oh, and colcolstyles, I'm so pleased with routine you made that I added you to the credits of my hack. I just want you to know that it's appreciated. Thanks again! :)

The disobedience check is part of the BattleScript commands, namely command 0, that checks what the pokemon will do. The actual obedience check is at 0801D438, covering all types of disobedience. The code checks for the obedience flag first, then proceeds to check for badges and levels. I'll post here the relevant piece of code for this matter:
ROM:0801D460 BL Disobey_byte_check ;decompiled below, the code that was talked about earlier
ROM:0801D464 CMP R0, #0
ROM:0801D466 BEQ loc_801D4BE
ROM:0801D468 LDR R2, =0x2023BE4
ROM:0801D46A LDRB R1, [R4]
ROM:0801D46C MOVS R0, #0x58
ROM:0801D46E MULS R1, R0
ROM:0801D470 MOVS R0, R2
ROM:0801D472 ADDS R0, #0x54
ROM:0801D474 ADDS R0, R1, R0
ROM:0801D476 LDR R0, [R0]
ROM:0801D478 ADDS R2, #0x3C
ROM:0801D47A ADDS R1, R1, R2

ROM:0801D47C BL Compare_trainer_values ;compares your trainer IDS with the pokemon trainer IDS
ROM:0801D480 LSLS R0, R0, #0x18
ROM:0801D482 CMP R0, #0
ROM:0801D484 BEQ loc_801D4F4 ;the same, is obedient
;from here on it's the badge checks. R6 is the maximum level the pokemon may have
ROM:0801D486 LDR R0, =0x827
ROM:0801D488 BL Check_active_flag
ROM:0801D48C LSLS R0, R0, #0x18
ROM:0801D48E CMP R0, #0
ROM:0801D490 BNE loc_801D4F4 ;earthbadge on = obedience

ROM:0801D492 MOVS R6, #0xA
ROM:0801D494 LDR R0, =0x821
ROM:0801D496 BL Check_active_flag
ROM:0801D49A LSLS R0, R0, #0x18
ROM:0801D49C CMP R0, #0
ROM:0801D49E BEQ loc_801D4A2

ROM:0801D4A0 MOVS R6, #0x1E
ROM:0801D4A2
ROM:0801D4A2 loc_801D4A2 ; CODE XREF: Disobedience_check+66j
ROM:0801D4A2 LDR R0, =0x823
ROM:0801D4A4 BL Check_active_flag
ROM:0801D4A8 LSLS R0, R0, #0x18
ROM:0801D4AA CMP R0, #0
ROM:0801D4AC BEQ loc_801D4B0

ROM:0801D4AE MOVS R6, #0x32
ROM:0801D4B0
ROM:0801D4B0 loc_801D4B0 ; CODE XREF: Disobedience_check+74j
ROM:0801D4B0 LDR R0, =0x825
ROM:0801D4B2 BL Check_active_flag
ROM:0801D4B6 LSLS R0, R0, #0x18
ROM:0801D4B8 CMP R0, #0
ROM:0801D4BA BEQ loc_801D4BE

ROM:0801D4BC MOVS R6, #0x46
ROM:0801D4BE
ROM:0801D4BE loc_801D4BE ; CODE XREF: Disobedience_check+2Ej
ROM:0801D4BE ; Disobedience_check+82j
ROM:0801D4BE LDR R5, =0x2023BE4
ROM:0801D4C0 LDR R0, =0x2023D6B
ROM:0801D4C2 MOV R8, R0
ROM:0801D4C4 LDRB R0, [R0]
ROM:0801D4C6 MOVS R7, #0x58
ROM:0801D4C8 MULS R0, R7
ROM:0801D4CA ADDS R0, R0, R5
ROM:0801D4CC ADDS R0, #0x2A
ROM:0801D4CE LDRB R0, [R0] ;gets pokemon current level
ROM:0801D4D0 CMP R0, R6
ROM:0801D4D2 BLS loc_801D4F4 ;if current level <= max level, is obedient

ROM:0801D4D4 BL RNG_halfword
ROM:0801D4D8 MOVS R1, #0xFF
ROM:0801D4DA ANDS R1, R0
ROM:0801D4DC MOV R2, R8
ROM:0801D4DE LDRB R0, [R2]
ROM:0801D4E0 MOVS R2, R0
ROM:0801D4E2 MULS R2, R7
ROM:0801D4E4 ADDS R0, R2, R5
ROM:0801D4E6 ADDS R0, #0x2A
ROM:0801D4E8 LDRB R0, [R0]
ROM:0801D4EA ADDS R0, R0, R6
ROM:0801D4EC MULS R0, R1
ROM:0801D4EE ASRS R4, R0, #8
ROM:0801D4F0 CMP R4, R6
ROM:0801D4F2 BGE loc_801D518
ROM:0801D4F4
ROM:0801D4F4 loc_801D4F4 ; CODE XREF: Disobedience_check+14j
ROM:0801D4F4 ; Disobedience_check+24j ...
ROM:0801D4F4 MOVS R0, #0
ROM:0801D4F6 B loc_801D738

Disobey_byte_check ; CODE XREF: Disobedience_check+28p
ROM:0801D3C0 PUSH {R4-R7,LR}
ROM:0801D3C2 LSLS R0, R0, #0x18
ROM:0801D3C4 LSRS R4, R0, #0x18
ROM:0801D3C6 MOVS R0, R4
ROM:0801D3C8 BL sub_80751C4
ROM:0801D3CC LSLS R0, R0, #0x18
ROM:0801D3CE LSRS R0, R0, #0x18
ROM:0801D3D0 CMP R0, #1
ROM:0801D3D2 BEQ loc_801D406
ROM:0801D3D4 LDR R0, =0x2023BCE
ROM:0801D3D6 LSLS R4, R4, #1
ROM:0801D3D8 ADDS R5, R4, R0
ROM:0801D3DA LDRH R0, [R5]
ROM:0801D3DC MOVS R7, #0x64
ROM:0801D3DE MULS R0, R7
ROM:0801D3E0 LDR R6, =0x2024284
ROM:0801D3E2 ADDS R0, R0, R6
ROM:0801D3E4 MOVS R1, #0xB
ROM:0801D3E6 MOVS R2, #0
ROM:0801D3E8 BL get_party_status ;get pokemon species
ROM:0801D3EC MOVS R1, 0x19A ;compares with deoxys
ROM:0801D3F0 CMP R0, R1
ROM:0801D3F2 BEQ loc_801D414 ; if so, check obedience flag

ROM:0801D3F4 LDRH R0, [R5]
ROM:0801D3F6 MULS R0, R7
ROM:0801D3F8 ADDS R0, R0, R6
ROM:0801D3FA MOVS R1, #0xB
ROM:0801D3FC MOVS R2, #0
ROM:0801D3FE BL get_party_status ; redundant, checks your pokemon again for its species
ROM:0801D402 CMP R0, #0x97
ROM:0801D404 BEQ loc_801D414 ;if mew, check for obedience
ROM:0801D406
ROM:0801D406 loc_801D406 ; CODE XREF: Disobey_byte_check+12j
ROM:0801D406 MOVS R0, #1
ROM:0801D408 B loc_801D42A ; is obedient, end
ROM:0801D408 ; ---------------------------------------------------------------------------
ROM:0801D40A DCB 0
ROM:0801D40B DCB 0
ROM:0801D40C dword_801D40C DCD 0x2023BCE ; DATA XREF: Disobey_byte_check+14r
ROM:0801D410 dword_801D410 DCD 0x2024284 ; DATA XREF: Disobey_byte_check+20r
ROM:0801D414 ; ---------------------------------------------------------------------------
ROM:0801D414
ROM:0801D414 loc_801D414 ; CODE XREF: Disobey_byte_check+32j
ROM:0801D414 ; Disobey_byte_check+44j
ROM:0801D414 LDR R0, =0x2023BCE
ROM:0801D416 ADDS R0, R4, R0
ROM:0801D418 LDRH R1, [R0]
ROM:0801D41A MOVS R0, #0x64
ROM:0801D41C MULS R0, R1
ROM:0801D41E LDR R1, =0x2024284
ROM:0801D420 ADDS R0, R0, R1
ROM:0801D422 MOVS R1, #0x50
ROM:0801D424 MOVS R2, #0
ROM:0801D426 BL get_party_status ;checks last ribbon, that is the obedience flag, and returns it
ROM:0801D42A
ROM:0801D42A loc_801D42A ; CODE XREF: Disobey_byte_check+48j
ROM:0801D42A POP {R4-R7}
ROM:0801D42C POP {R1}
ROM:0801D42E BX R1


0801D4D4 checks one last time if, by chance, the attack will go trough. If not it will proceed to 0x0801d518, where what will the pokemon actually do\say is calculated.
So, several modifications can be made here to change the level a pokemon will become disobedient and in what conditions will it become disobedient.
The location of the obedience flag is actually in the last part of the Ribbon data in the Misc block, the topmost flag (bit 31 of the Ribbon word), but it's only useful for the species listed on the disobedience byte. And as for why Mew\Deoxys only disobey, it's because the chance of attack is determined by a random number (from 0-ff) to be smaller than the max level (that in the byte case is 0).

Edit: If I understood correctly, the code needed here is one that, if a pokemon doesn't have the flag, the pokemon has some chances of attacking, instead of just laying around all the time. With that in mind, I made a code for the occasion
.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
The trick in that code is that the pokemon will act as if it was obedient every once in a while thanks to the random number stored at 0x03005000.

JPAN, I tried to assemble this code I got some error messages: invalid offset, target not word aligned; invalid offset, value too big.

I couldn't get it to assemble.

NarutoActor
August 9th, 2010, 08:21 AM
Yup. Also, You can edit the asm routine to compare with a var. For an example if var 0x8000 is 0x1 then it will be a bulbasaur. That would make the asm routine more universal for other hackers. All you need to do is set the var before the asm routine, copy the var value into a registry, and compare.

metapod23
August 9th, 2010, 12:44 PM
Yup. Also, You can edit the asm routine to compare with a var. For an example if var 0x8000 is 0x1 then it will be a bulbasaur. That would make the asm routine more universal for other hackers. All you need to do is set the var before the asm routine, copy the var value into a registry, and compare.

So could I create a routine that only has Charmeleon or Charizard obey or disobey if a certain variable (or flag) was set? That would be the best thing, imho. Then I could just set the variable (say, to 0x1) when I want them to obey, and unset it when I want them to disobey.

If that's possible, any chance you can enlighten me on to how that routine might be written?

(And I still can't get JPAN's routine to assemble. :()

metapod23
January 2nd, 2011, 12:20 PM
Yup. Also, You can edit the asm routine to compare with a var. For an example if var 0x8000 is 0x1 then it will be a bulbasaur. That would make the asm routine more universal for other hackers. All you need to do is set the var before the asm routine, copy the var value into a registry, and compare.

So I spent a good part of my day trying to get this to work with this code. I've tried various things, but here's what I tried recently:

.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 r1, .VAR
cmp r1, #0x00
beq disobey2

mov r0, #0x01
ldr r1, .RESUME
bx r1

disobey2:
ldr r1, .DISOBEY
bx r1

resume:
ldr r1, .RESUME
bx r1

branchlink:
bx r3

.align 2
.RESUME:
.word 0x0801D42B
.DISOBEY:
.word 0x0801D415
.VAR:
.word 0x020370d2

I bolded what I was attempting to do, which is to set a variable to a register, compare it to a number (in this case, 0) and if it's set to 0, have the Poké disobey; if not, have it obey.

I want to use variable 6187, just because I haven't used that one yet, but I'm just trying to experiment with 0x800d to see if I can get it to work. So far with my attempts, Charizard has either obeyed the entire time, whether 0x800d was set to 0x0 or 0x1, or has disobeyed in either event.

Any input would be appreciated. :)

colcolstyles
January 2nd, 2011, 04:16 PM
You need a 'ldrh r1, [r1]' instruction after 'ldr r1, .VAR'.

Also, you can get rid of the "branchlink" section. That must have been left in from a previous project. It's unnecessary here.

metapod23
January 3rd, 2011, 08:53 AM
You need a 'ldrh r1, [r1]' instruction after 'ldr r1, .VAR'.

Also, you can get rid of the "branchlink" section. That must have been left in from a previous project. It's unnecessary here.

It worked! Thanks! :)

Now I'm just trying to find the right register for variable 0x6200. I tried debugging with VBA-SLD-H, but when I try to use the breakpoint command for the script I'm testing, it kind of freezes, and I haven't had any luck comparing registers when I hit F11 right after I activate the script and after/before I activate a different script. At least none of the ones I have tried have worked.

Anybody have any advice?

colcolstyles
January 3rd, 2011, 02:27 PM
I'm not really sure what you're asking but if you want to retrieve the value of a non-0x8000 variable, you should call the THUMB routine at '0x0806E454' and pass the variable number as a parameter through r0.

metapod23
January 3rd, 2011, 07:18 PM
I'm not really sure what you're asking but if you want to retrieve the value of a non-0x8000 variable, you should call the THUMB routine at '0x0806E454' and pass the variable number as a parameter through r0.

Unfortunately, I have no idea how to do that. :\

I'll keep searching the forums/google to see if I can scrounge up something. None of the tutorials or topics I've found have made it very clear to me.

TheDarkShark
January 4th, 2011, 02:13 AM
My ASM isn't very good, but I think the code would be something like this:

ldrh r0, <whatever variable you want to use>
bal 0x0806E454

EDIT: Here's the full code. I'm not shure if this will work, but here it is (changes in bold) :
.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:
ldrh r0, 0x6187 @The number of the variable is stored
bal 0x0806E454 @The Routine is called
cmp r0, #0x00 @Maybe, you have to compare another Register, as I don't know, where the value of the variable is stored
beq disobey2[/B]

mov r0, #0x01
ldr r1, .RESUME
bx r1

disobey2:
ldr r1, .DISOBEY
bx r1

resume:
ldr r1, .RESUME
bx r1

branchlink:
bx r3

.align 2
.RESUME:
.word 0x0801D42B
.DISOBEY:
.word 0x0801D415

metapod23
January 4th, 2011, 07:18 AM
My ASM isn't very good, but I think the code would be something like this:

ldrh r0, <whatever variable you want to use>
bal 0x0806E454

.........

Thanks for responding. It didn't work, but it got me trying some different things. Taking word for word what colcol instructed, I tried this:

.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:
bl =0x0806E454
ldr r0, =0x00006200
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

.align 2
.RESUME:
.word 0x0801D42B
.DISOBEY:
.word 0x0801D415

It doesn't work, though, so obviously I'm doing something wrong. I was trying to use this tut - http://pkmnhackersonline.com/zodiacdagreat/ASM/Lesson3.htm - as reference.

It doesn't crash/freeze the game like some of my attempts (like using labels for the variable/routine), but the Pokemon obeys no matter what the variable is set to.

Maybe someone could help me figure out my mistakes?

Jambo51
January 4th, 2011, 12:11 PM
...Maybe someone could help me figure out my mistakes?

The Line of code I left in bold is the problem here. The bl thumb command has a VERY short range (0xFFFF bytes I think), so instead of trying to directly link to it, try this instead. Unless you are inserting this code within that range. First of all, what you're doing here, because the code is written the wrong way around, is running the variable decrypting routine, then overwriting the result with "garbage".

Try this instead. Essentially the same, but should work better:

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


For the record, you should ALWAYS precede a bl command with a push {lr} command and follow it with a combo of pop {whatever}, mov lr, whatever; as you don't know if the calling routine needs the value held in lr for the rest of the routine. Better safe than sorry!

Incidentally, I'd assume that this is the same routine which runs the checks on Mew and Deoxys for disobedience? If so, could we rewrite it to exclude those rather frustrating checks?

metapod23
January 4th, 2011, 01:24 PM
The Line of code I left in bold is the problem here. The bl thumb command has a VERY short range (0xFFFF bytes I think), so instead of trying to directly link to it, try this instead. Unless you are inserting this code within that range. First of all, what you're doing here, because the code is written the wrong way around, is running the variable decrypting routine, then overwriting the result with "garbage".

Try this instead. Essentially the same, but should work better:

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


For the record, you should ALWAYS precede a bl command with a push {lr} command and follow it with a combo of pop {whatever}, mov lr, whatever; as you don't know if the calling routine needs the value held in lr for the rest of the routine. Better safe than sorry!

Thanks for the response, but it's still not working for me. :(
Charizard obeys whether the variable is set to 0x0 or 0x1 ...

Incidentally, I'd assume that this is the same routine which runs the checks on Mew and Deoxys for disobedience? If so, could we rewrite it to exclude those rather frustrating checks?

That's correct, it's the same routine. I would guess that you could just alter the routine at 0x0801D404, which I think was the original location of the routine to check for disobedience? I would guess you could just write a new routine that doesn't really do anything and insert it there?

I'm sure there's a routine before this that goes to the routine at 0x0801D404 if an attack is selected, though, and it would be best to edit that routine to not have it go to the routine at 0x0801D404 at all, but I don't know what the offset of that one would be ...

Jambo51
January 4th, 2011, 03:17 PM
Thanks for the response, but it's still not working for me. :(
Charizard obeys whether the variable is set to 0x0 or 0x1 ...



That's correct, it's the same routine. I would guess that you could just alter the routine at 0x0801D404, which I think was the original location of the routine to check for disobedience? I would guess you could just write a new routine that doesn't really do anything and insert it there?

I'm sure there's a routine before this that goes to the routine at 0x0801D404 if an attack is selected, though, and it would be best to edit that routine to not have it go to the routine at 0x0801D404 at all, but I don't know what the offset of that one would be ...

This might sound a bit iffy, but let me insert this routine and i'll see if I can find why it isn't working for you. If you say yes, you'll need to tell me the insertion location so I can do it. Also, 2 seconds after posting this, I found and removed the Mew and Deoxys checks. Hooray! Now we can all catch and actually use Mew. Simply replace the cmp r1, #0x97 line with lsl r0, r0, #0x0 (97 29 with 00 00) and the check won't run.

metapod23
January 4th, 2011, 04:09 PM
This might sound a bit iffy, but let me insert this routine and i'll see if I can find why it isn't working for you. If you say yes, you'll need to tell me the insertion location so I can do it. Also, 2 seconds after posting this, I found and removed the Mew and Deoxys checks. Hooray! Now we can all catch and actually use Mew. Simply replace the cmp r1, #0x97 line with lsl r0, r0, #0x0 (97 29 with 00 00) and the check won't run.

Sure, go ahead. I've been placing the routine at 0x859000.

EDIT

Actually, now I realize that it does work. Thanks!! :D

For some reason variable 0x6200 wasn't already set to 0, even though I hadn't used it in my game yet - I was assuming that it was. :embarrass

I switched it to 0x6199 and it works perfectly. Thanks again, Jambo51! I really appreciate it. :)

Also, I put the code in the first post, and I'll add you and others that helped on this code to the credits for my hack. :)

metapod23
August 10th, 2011, 01:12 PM
I'm just reviving this thread to post that I figured out how to combine JPAN's routine of having a Pokemon obey once in a while and Jambo51's routine of having it only do so when a certain variable is or isn't set. Again, I want 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).

.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

Wynchester
December 30th, 2012, 02:07 PM
My question is this... Does this then affect every Poke of a species (i.e. all Charmeleon and Charizard) or only one specific pokemon you have? My instinct says all of the Species, but if that's the case, I need help making it so it only affects a very specific Poke.

tinix
December 31st, 2012, 12:34 AM
It affects all of species. I think you could make a specific poke disobey by storing its personality value(it is unique as it is randomly generated) from its data in some variable and then comparing the variable to the personality value of active pokemon. If I am wrong feel free to correct me.