View Single Post
  #1    
Old February 3rd, 2009, 11:42 AM
thethethethe
Gym Leader
 
Join Date: Jun 2007
Location: Melbourne, Australia
Gender: Male
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
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.
__________________
Gone.
Reply With Quote