- 1,103
- Posts
- 17
- Years
- Melbourne, Australia
- Seen Oct 12, 2010
ASM Take and Return Pokémon
NOTE:This is currently only for Fire Red. I'll add support for other ROM's when I find time.
To do this all you'll need is a little knowledge about command #23 (callasm) and the ability to use a hex editor very basically. You don't need to be an expert, because I'll even give you an example script.
Okay here's the code for those who know what to do with it. Its also is partly commented for those you have trouble understanding. Don't ask what to do with this if you don't already know. For those who don't know what to do with this, I'll give the other way to get the ASM code into the ROM. The code may not be the best but it works.
Spoiler:
Take Pokemon
Return Pokemon
Code:
.text
.align 2
.thumb
.thumb_func
.global main
main:
push {r0-r4, lr}
ldr r0, .var1 @var for Pokemon to take
ldrh r0, [r0] @store Pokemon's number in party
ldr r1, .var2 @+2, var for total Pokemon(use command #43)
ldrh r1, [r1] @store max Pokemon in current party
cmp r0, r1 @If number to store is greater than number in party
bgt error
b taken
error:
mov r0, #1
ldr r1, .var3
strh r0, [r1] @+4, For error it will return 1 to var.
pop {r0-r4, pc}
taken:
ldr r3, .pokedata @loads Pokemon party data to reg
cmp r0, #0 @if Pokemon to take is first, jump further ahead
beq take
mov r2, #0 @loop counter
multiply:
add r3, #100 @For each Pokemon in party has 100 bytes
add r2, #1 @r2+=1
cmp r2, r0 @if counter equals Pokemon to copy
bne multiply
take:
mov r0, r3
ldr r1, =0x02010000 @Destination to place data until Pokemon is given back.
mov r2, #25 @or 50, I can't remember off the top of my head.
swi 0xC @Either 0xC or oxB I can't remember which one is 4 byte write and which is two byte write.
mov r0, #0 @loop counter
ldr r1, =0x00000000 @to overwrite old data with nothing.
remove:
str r1, [r3] @pverwrite Pokemon data with 0
add r3, #4 @add 4 to location for next spot
add r0, #1 @r0+=1 for loop
cmp r0, #25 @If all data is overwritten
blt remove
fix:
@to fix up party if needed
mov r1, #100
sub r2, r3, r1 @original calculated party spot
ldr r1, .pokedata
sub r1, r2, r1 @difference between data and Pokemon taken
ldr r4, =500
cmp r1, r4 @If last Pokemon
beq finish
cmp r1, #0
beq finish
mov r0, r1
mov r1, #4 @calculate length (Maybe two I need to check
swi 0x06 @divide interrupt result returned at r0
mov r1, r2 @r2 = Where to move party MOVE TO: r1
mov r2, r0 @r0 = Length MOVE TO: r2
mov r0, r3 @r3 = Rest of party MOVE TO: r0
swi 0xC
finish:
mov r0, #0 @If work correctly, returns 0 to var number 3.
ldr r1, .var3
strh r0, [r1]
pop {r0-r4, pc}
.align 2
.pokedata:
.word 0x02024284
.var1:
.word 0x020370b8
.var2:
.word 0x020370ba
.var3:
.word 0x020370b8
Return Pokemon
Code:
.text
.align 2
.thumb
.thumb_func
.global main
main:
push {r0-r2, lr}
ldr r0, .var1
ldrh r0, [r0] @Load amount of Pokemon in party
cmp r0, #5
beq error
b given
error:
mov r0, #1
ldr r1, .var3
str r0, [r1]
pop {r0-r2, pc}
given:
ldr r1, .pokedata
cmp r0, #0
beq ahead
mov r2, #0
loop1:
add r1, #100
add r2, #1
cmp r2, r0
bne loop1
ahead:
ldr r0, .space
mov r2, #25
swi 0xC
mov r2, #0
mov r1, #0
remove:
str r1, [r0]
add r0, #4
add r2, #1
cmp r2, #25
blt remove
finish:
mov r0, #0
ldr r1, .var3
strh r0, [r1]
pop {r0-r2, pc}
.align 2
.pokedata:
.word 0x02024284
.var1:
.word 0x020370B8
.var3:
.word 0x020370BC
.space:
.word 0x02010000
Here's the ASM code for those who don't know how to compile it. This isn't an ASM tutorial so I won't cover anything other than what's needed to get this working.
Input this data into your ROM through a hex editor at an address of your choice. Write the address down, because you'll need them for the script.
Take Pokemon
Code:
1FB5 1A48 0088 1A49 0988 8842 00DC 03E0
0120 1849 0880 1FBD 134B 0028 04D0 0022
6433 0132 8242 FBD1 181C 1349 1922 0CDF
0020 0021 1960 0433 0130 1928 FADB 6421
5A1A 0949 511A 0D4C A142 08D0 0029 06D0
081C 0421 06DF 111C 021C 181C 0CDF 0020
0449 0880 1FBD 0000 8442 0202 B870 0302
BA70 0302 B870 0302 00F0 0202 F401 0000
Then you'll also need to input this code into your Hex editor as well.
Return Pokemon
Code:
07B5 1048 0088 0528 00D0 03E0 0120 0E49
0860 07BD 0A49 0028 04D0 0022 6431 0132
8242 FBD1 0948 1922 0CDF 0022 0021 0160
0430 0132 1928 FADB 0020 0349 0880 07BD
8442 0202 B870 0302 BC70 0302 00F0 0202
Now that you have the ASM part done. This part should be easy. All we need to do now is script it. Most people are most comfortable with XSE nowadays so I'll put my example script to use the code in XSE.
But now we're still not ready to code. We need to know some things about your ASM code.
The first code uses 3 variables 0x8000, 0x8001, and 0x8002. The second code uses only two variables 0x8000 and 0x8002.
In the first code, 0x8000 is used to store the number of the Pokemon in your party. For example, if it's the first Pokemon, you would store zero, if it were the sixth Pokemon, you would store 5 into the variable.
0x8001 is used to store the total amount of Pokemon in your party. This can be obtained by just using countpokemon and then a copyvar from 0x800D to 0x8001.
0x8002 is used as an error check. For example if the Pokemon's number in your party that you wanted to take, was less than the total Pokemon in your party designated by the above two variables. This is just originating from a normal C/C++ and the fact that a returned 0 means no problems, and a return of anything else means an error occurred.
In the second script, 0x8000 is used for the total Pokemon you have.
0x8002 is used in the same way as in the first code and is an error check.
So here's an example script using the ASM code. I'll comment any important areas out so you should know what's going on even if you don't script very well.
Code:
#alias @ $
#dynamic 0x800000
#org $start 'Code to take a Pokemon
lock
faceplayer
checkflag 0x200
if 0x1 goto $return
setvar 0x8000 0x0 'Pokemon to take is first in Party.
countpokemon 'Total Pokemon in party.
copyvar 0x8001 0x800D
callasm 0x800001 'callasm 0x(address + 1) Of course then I inserted this code at 0x800001
compare 0x800D 0x1 'If error occurred.
if 0x1 goto $error
msgbox $1 0x6
setflag 0x200
release
end
#org $error
msgbox $2 0x6
release
end
#org $return
countpokemon
compare 0x800D 0x5
if 0x1 goto $error 'If there's no room for the return.
copyvar 0x8000 0x800D
callasm 0x800101 'Callasm 0x(address +1) Mine was 0x800100
compare 0x8002 0x1 'Error Check
if 0x1 goto $error
msgbox $3 0x6
clearflag 0x200
release
end
#org $1
= Pokemon taken.
#org $2
= Error occurred.
#org $3
= Pokemon returned
Note this will only allow you to take one Pokemon at a time. If you try to take a second it will overwrite the first Pokemon and you'll lose the first Pokemon.
Please let me know if there are any bugs. I haven't extensively tested it out, I only checked whether it worked with the first Pokemon being taken and returned or not. The quicker people let me know, the quicker I can fix it.
Don't take without Permission.
Tutorial and code by thethethethe.
Tutorial and code by thethethethe.