• Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
  • Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
  • Our weekly protagonist poll is now up! Vote for your favorite Conquest protagonist in the poll by clicking here.
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Code: ASM Resource Thread

HP Regeneration per step


Intro:
Basically a routine to regenerate a Pokemon's HP every step. In this routine it's set to 3 per step. You may want to modify the exact amount to a percentage or something (see the commented line).

How to insert:

First compile and insert the following routine into free space.

Spoiler:


Now in a hex editor navigate to 0x6D5F6. There you will need to insert the following byte changes:
Code:
 01 4A 10 47 00 00 XX XX XX 08
Where XX XX XX is the pointer to where you inserted the above routine +1.

Usage:

There isn't any usage. It's automatically done. You can change the amount generated by reading the line in the code which I've commented.

For Emerald (Changes in Red):
Spoiler:

Insert at 0x9C8EA.
 

Battle Frontier routines (Generate a random trainer sprite)


Something to compliment my opponent party generation routine, it generates a random trainer sprite for the opponent from a table of possible sprite entries. Incase you haven't noticed, tables are awesome and tables make things customizable! Lets cut to the chase.

An important note about multi-use

You may or may not be familiar with the Rival and Champion trainer class functions so I will briefly explain that to explain this multi-use. In short, if you assign a trainer the trainer class "Rival" or "Champion" they will automatically be assigned the name of your Rival (the one you name in the Oak intro).

Some people have hacks in which there are more than 2 Rivals, and it may be important to you to have this said rival's sprite appear when battling them. I've removed the class dependency, and added that capability to the sprite generator.

How to insert:

Before compiling the routine in the spoiler below, there's a few things which you may want to customize.
1) The routine is flag toggled. By default I made this flag 0x205. See spoiler below about code to modify this
Spoiler:


2) This routine reads from a table of byte long entries, each of the entries correspond to a specific sprite. See spoiler for info
Spoiler:


3) This routine has an optional section described in the previous section.

To remove this section please see the spoiler below.
Spoiler:


To learn how to customize the optional section see the spoiler below.
Spoiler:


The routine:
Spoiler:


Once the changes have been made, compile and insert into free space. Then navigate to 0x37D30 and make the following byte changes:
Code:
00 4C 20 47 XX XX XX 08
Where XX XX XX is where you inserted the routine +1. Note the trailing 08 may change depending on where you've inserted the routine.


Usage:

Just set flag 0x205 and let the magic happen. Set variable 0x8000 to 0xFF for the optional part mentioned throughout the post.


Important:
Please direct questions in the ASM help thread and not to my poor PM box :(
 
Last edited:

Battle Frontier routines (Generate a random trainer name)


So I've done generating the sprite, generating the team, now it's time to give our random trainer their name. Naming is a little trickier because we can't assign a male name to a female sprite and vise versa. I decided to make a simple system to avoid that which I will now explain here. Skip to the next section if you're uninterested and want to risk making your female sprite be named Arnold.

Basically, without mentioning, in my previous post's routine I secretly stored the sprite's ID in variable 0x8001. This routine uses that information to generate a name which fits the sprite. Obviously, the only way to do that is to make a table whose entries are directly linked to the sprite table. How it works is, every sprite ID has a set amount of names which can be assigned to it, when a sprite is chosen at random, a name from the table which corresponds to the sprite is chosen at random.

Here is how the table is formatted"
Code:
[13 bytes (Possible name ID 1)] [13 bytes (Possible name ID 1)] [13 bytes (Possible name ID 1)] ....[13 bytes (Possible name ID 2)] ...
Names are 0xFF terminated of course.

An important note about multi-use

You may or may not be familiar with the Rival and Champion trainer class functions so I will briefly explain that to explain this multi-use. In short, if you assign a trainer the trainer class "Rival" or "Champion" they will automatically be assigned the name of your Rival (the one you name in the Oak intro).

Some people have hacks in which there are more than 2 Rivals, and if you use some of my naming routines, the player has the ability to name the second rival. This implies that the 2nd rival or important character's name will not be written into the ROM, but rather stored somewhere in the RAM. Which means you cannot just create a custom trainer and have it have the second Rival or important character's name (because like the rival's name, you don't know it to hard code it!). I've taken this into consideration and added some optional code to support this. I've removed the class dependency as well. Now you just need to set variable 0x8000 to 0xFF

How to insert:

Before compiling the routine in the spoiler below, there's a few things which you may want to customize.
1) The routine is flag toggled. By default I made this flag 0x205. See spoiler below about code to modify this
Spoiler:


2) This routine reads from a table of 13 byte long entries, each of the entries correspond to a specific name for a sprite. See spoiler for info.
Spoiler:


3) This routine has an optional section described in the previous section.

To remove this section please see the spoiler below.
Spoiler:


To learn how to customize the optional section see the spoiler below.
Spoiler:


The routine:
Spoiler:


Once the changes have been made, compile and insert into free space. Then navigate to 0xD8134 and make the following byte changes:
Code:
00 4C 20 47 XX XX XX 08
Where XX XX XX is where you inserted the routine +1. Note the trailing 08 may change depending on where you've inserted the routine.


Usage:

Just set flag 0x205 and let the magic happen. Set variable 0x8000 to 0xFF for the optional part mentioned throughout the post.


Important:
Please direct questions in the ASM help thread and not to my poor PM box :(
 
Excuse my triple post, but I have an update about the third routine which deals with actually making the trainer temporary. The whole idea of generating a randomized trainer using ASM routines, rather than using a script to pick a random battle from 50 or so, efficiency and time saving aside, is to save the Hacker 50 or so trainer slots which they would have used to make the trainers.

However, it became apparent to me while working on this that there was no need to make a custom trainerID or temporary trainer ID. In any frontier routine, the battle style would be
Code:
trainerbattle 0x1 0xID 0x0 @stuff @stuff
so the hacker can just clear the trainerflag after the battle, and use one trainer flag for a large selection of custom trainers. As such, I will not be making a routine for this.

I think this concludes the biggest problem about implementing a battle frontier in Fire Red. Some of the competitions, atleast the interesting ones, can be done with smart usage of the Pokemon storage system routines, and small edits of game code. I encourage people to post their solutions to said problems.

I'm currently working on making minigames in FR. Let me know some of your ideas :)
 
Not sure if you're still taking these, but I have a small request: a way to force set mode that can be toggled on/off. Would be very useful for battle frontier type places.

Just going to repost this because I believe it's relevant to the other battle frontier routines, for people that don't want to permanently enable set mode.
 

My condition for using this hack

Unlike most hacks, this is a little different. It's open source, and you're free to use it. However, I require you post the script you use for any of your moves. This is because I want people to keep anything regarding this hack public.
Just post the script you use in your own thread, and that'll be it (like the Sunny Day script I used).

Here's my Rock Climb script, just posting here for convenience. It's worth noting this script was made for FireRed, and uses JPAN's special 0x7F; of course, you can just compile the routine and replace special 0x7F with callasm instead.

For Emerald, I believe you need to change the pointer to evaluator to be 0x081A8D95, as well as changing the movement bytes and the animation (?). Special 0x8F isn't in Emerald afaik, so just replace instances of it with getplayerpos 0x8004 0x8005 (EDIT: it seems to not work if it isnt a special, so it's still easiest to replace one of the specials which point to a nop to point to the routine instead).

All instances of 0xA5 should be replaced with the Rock Climb behaviour byte, and all instances of 0x1AF with your attack ID for Rock Climb.

This works for any height of Rock Climb wall, provided each Rock Climb wall tile has the behaviour byte specified in this script. You should also assign this script to the behaviour byte, as well as for the field move, so it's multipurpose in that sense. The script could probably be far more efficient, the movement isn't ideal, the "Rock Climb can't be used here" isn't consistent with how trying to Surf where you cannot works, and (due to horizontal Rock Climbing being impossible / ugly with the Gen 3's 2D engine) horizontal movement doesn't work, but for all intents and purposes it's functional.

Code:
#dynamic 0x800000

'---------------
#org @start
lock
special 0x8F
comparefarbytetobyte 0x2036E50 0x11
if 0x1 call @snippet1
comparefarbytetobyte 0x2036E50 0x22
if 0x1 call @snippet2
special 0x7F
compare 0x8005 0xA5
if 0x1 goto @snippet3
goto @snippet4

'---------------
#org @snippet1
addvar 0x8005 0x1
return

'---------------
#org @snippet2
subvar 0x8005 0x1
return

'---------------
#org @snippet3
lock
special 0x8F
comparefarbytetobyte 0x2036E50 0x33
if 0x1 goto @snippet5
comparefarbytetobyte 0x2036E50 0x44
if 0x1 goto @snippet5
checkattack 0x1AF
compare LASTRESULT 0x6
if 0x1 goto @snippet5
setanimation 0x0 LASTRESULT
bufferpartypokemon 0x0 LASTRESULT
bufferattack 0x1 0x1AF
msgbox @string1 MSG_YESNO '"The wall is very rocky[.]\nWould y..."
compare LASTRESULT 0x0
if 0x1 goto @snippet6
msgbox @string2 MSG_KEEPOPEN '"[buffer1] used [buffer2]!"
closeonkeypress
doanimation 0x2
waitstate
special 0x8F
setvar 0x8006 0x0
copyvar 0x4001 0x8004
copyvar 0x4002 0x8005
comparefarbytetobyte 0x2036E50 0x11
if 0x1 goto @snippet7
comparefarbytetobyte 0x2036E50 0x22
if 0x1 goto @snippet8
goto @snippet4

'---------------
#org @snippet4
msgbox @string3 MSG_NORMAL '"Rock Climb can't be used here!"
release
end

'---------------
#org @snippet5
msgbox @string4 MSG_SIGN '"The wall is very rocky[.]\nWill a ..."
release
end

'---------------
#org @snippet6
closeonkeypress
release
end

'---------------
#org @snippet7
copyvar 0x8004 0x4001
addvar 0x4002 0x1
copyvar 0x8005 0x4002
addvar 0x8006 0x1
special 0x7F
compare 0x8005 0xA5
if 0x1 goto @snippet7
goto @snippet9

'---------------
#org @snippet8
copyvar 0x8004 0x4001
subvar 0x4002 0x1
copyvar 0x8005 0x4002
addvar 0x8006 0x1
special 0x7F
compare 0x8005 0xA5
if 0x1 goto @snippet8
goto @snippet9

'---------------
#org @snippet9
compare 0x8006 0x0
if 0x1 goto @snippet10
comparefarbytetobyte 0x2036E50 0x11
if 0x1 call @snippet11
comparefarbytetobyte 0x2036E50 0x22
if 0x1 call @snippet12
subvar 0x8006 0x1
goto @snippet9

'---------------
#org @snippet10
release
end

'---------------
#org @snippet11
applymovement MOVE_PLAYER @move1
waitmovement 0x0
return

'---------------
#org @snippet12
applymovement MOVE_PLAYER @move2
waitmovement 0x0
return


'---------
' Strings
'---------
#org @string1
= The wall is very rocky[.]\nWould you like to use [buffer2]?

#org @string2
= [buffer1] used [buffer2]!

#org @string3
= Rock Climb can't be used here!

#org @string4
= The wall is very rocky[.]\nWill a Pokémon's move scale it?


'-----------
' Movements
'-----------
#org @move1
#raw 0x35 'Slide Down (Normal)
#raw 0xFE 'End of Movements

#org @move2
#raw 0x36 'Slide Up (Normal)
#raw 0xFE 'End of Movements

Give credit, of course, to JPAN and FBI agent.
 
Last edited:
Here are some of Jpans routines ported to Emerald.
All of which will be included in DSLN.

Check D-Pad
Spoiler:

Delete Pokemon From party(special 62)
Spoiler:

Check pokemon Status (Special 63)
Spoiler:
 
If anybody ever wants the Wally thingy to use your rival's backsprite in Emerald for whatever reason, here's a routine that does just that:
Code:
.thumb

reloadpal:
	and r0, r1
	beq abort
	cmp r4, #0
	beq genderbend
abort:
	ldr r3, =0x080A96B2
	mov pc, r3

reloadsprite:
	mov r1, r0
	add r3, #1
	mov lr, r3
	ldr r3, =0x0806A12C
	b genderbend

enterfield:
	ldr r4, =0x02024064
	ldrb r1, [r4]
genderbend:
	ldr r0, =0x03005D90
	ldr r0, [r0]
	ldrb r5, [r0, #8]
	mov r0, #1
	eor r0, r5
	mov r5, r0
	mov pc, r3

loadpal:
	ldr r0, =0x03005D90
	ldr r0, [r0]
	ldrb r0, [r0, #8]
	ldr r1, =0x08305D8C
	cmp r0, #0
	bne next
	add r1, #8
next:
	ldr r0, [r1]
	ldr r3, =0x0816A9B8
	mov pc, r3
	
/*01 4A 01 A3 97 46 XX XX XX XX C0 46 at 0x0A969E and 0x0A98E6(+C), 00 A3 A7 46 at 0x169ECC and 0x169F98, XX XX XX XX(+16) at 0x169F70 and 0x16A03C, 28 1C at 0x169EE0 and 0x169FAC, 87 46 at 0x16A9B6, and XX XX XX XX(+28) at 0x16AA60*/
Insertion instructions are found at the bottom. (+number) means you'll need to add that number to the XX XX XX XX (pointer to the routine) when you make the byte changes at that address (so if I inserted it at 0x08123456, I'd put 01 4A 01 A3 97 46 62 34 12 08 C0 46 at 0x0A98E6).
 
For Emerald, I believe you need to change the pointer to evaluator to be 0x081A8D95, as well as changing the movement bytes and the animation (?). Special 0x8F isn't in Emerald afaik, so just replace instances of it with getplayerpos 0x8004 0x8005.

That special is 0x92 in Emerald. List here will be updated in the future: https://www.pokecommunity.com/posts/8881985
 

Warp redirection


This is something similar to FR's elevator scripts in Celadon dept store. What it does is it redirects all warps to a specific one assigned by two variables (one for map bank and second for map number, I know you can make one variable to hold both of these, but I think the reverse hexing and math calculations might confuse people so 2 variables).

I think this will be useful for a single warp or multiple warps which warps you to a different map depending on what's happening. It's better than FR's elevator script because you can have a default warp position, and the redirection only takes 2 setvar instructions (could've been one, but you know) :D

How to insert:

Code:
MBank:
	.word 0x4012

MNumb:
	.word 0x4013

Change these two to the variables you want to use for map bank and map number (should be two non-temp vars). Then compile and insert the following routine into free space:

Spoiler:


Insert the following byte changes at 0x6DC78:
Code:
00 48 00 47 XX XX XX 08
Where XX XX XX is where you inserted this routine +1. Note that 08 may change depending on where you insert it.

Usage

Unlike other similar routines I made, this one reads the variables to determine if it should execute. Have the Mbank var not equal to 0 to toggle execution. Of course, Mbank = map bank var and Mnumb = Map number var.
 

HP Removal per step


Intro:
Basically a routine to remove a Pokemon's HP every step. In this routine it's set to 3 per step. You may want to modify the exact amount to a percentage or something (see the commented lines).

How to insert:

First compile and insert the following routine into free space.

Fire Red:
Spoiler:


Emerald:
Spoiler:


Usage:

Set flag 0x270 (or the flag you customized in the routine), then the HP automatically decreases based on the amount you set in the routine every step. You can change the amount removed by reading the lines in the code which I've commented.

Note: I did not test any of these; they should work in theory even though I didn't try it personally. This routine is a modification of FBI's, and is requested by Danny. Not sure why you'd want all Pokémon to constantly lose HP per step, so I added a flag check so it's toggle-able. This also doesn't work with the previous regeneration per step routine, if you thought it would for some reason.
 
Last edited:

HP Removal per step


Intro:
Basically a routine to remove a Pokemon's HP every step. In this routine it's set to 3 per step. You may want to modify the exact amount to a percentage or something (see the commented lines).

How to insert:

First compile and insert the following routine into free space.

Fire Red:
Spoiler:


Emerald:
Spoiler:


Usage:

Set flag 0x270 (or the flag you customized in the routine), then the HP automatically decreases based on the amount you set in the routine every step. You can change the amount removed by reading the lines in the code which I've commented.

Note: I did not test any of these; they should work in theory even though I didn't try it personally. This routine is a modification of FBI's, and is requested by Danny. Not sure why you'd want all Pokémon to constantly lose HP per step, so I added a flag check so it's toggle-able. This also doesn't work with the previous regeneration per step routine, if you thought it would for some reason.

Uhh, the FR routine is incorrect, so I guess that means the EM routine is not working either.

To explain the gain routine a little more in detail, lets look at the parts which require changing.

Code:
	mov r1, #0x39
	ldr r3, =(0x803FBE8 +1)
	bl linker
	mov r4, r0
	cmp r4, #0x0
	beq next
OK, here we're checking if current HP of this Pokemon is 0x0. If it is, it's fainted so move on to the next Pokemon. So far, so good. But it's important to note that in r4 right now the Pokemon's current HP is held.


Code:
	mov r0, r5
	mov r1, #0x3A
	ldr r3, =(0x803FBE8 +1)
	bl linker
	add r6, r6, #0x1
	cmp r4, r0
	beq loop
Here we have the total HP the Pokemon has being stored in R0. Note that Total HP is not Current HP. They are very distinct. What's happening here is a check to see if Total HP == Current HP. If it is, we'll move on to the next Pokemon. This is good if the routine was to increment HP, as we can't increment the HP of a full HP Pokemon. But if you're taking away HP, the total HP doesn't matter. Instead you should check that if you take away HP, it's current HP would be negative.

Code:
removeHP:
	sub r1, r4 #0x3 @amount to remove per step. Customize it
	cmp r1, #0x0
	bgt cont
	mov r4, #0x0
Uh, the compare should not be comparing to zero. Try this:

Code:
cmp r4, #0x3 @assuming you're taking away 3 HP
bge cont
mov r4, #0x0


I thought I'd just help you out by pointing out some of the inconsistencies and the changes you'd need to make to make this work. I know you're just editing my gain HP routine, and trying to help. Good luck GoGo. :)
 
Uhh, the FR routine is incorrect, so I guess that means the EM routine is not working either.

To explain the gain routine a little more in detail, lets look at the parts which require changing.

Code:
	mov r1, #0x39
	ldr r3, =(0x803FBE8 +1)
	bl linker
	mov r4, r0
	cmp r4, #0x0
	beq next
OK, here we're checking if current HP of this Pokemon is 0x0. If it is, it's fainted so move on to the next Pokemon. So far, so good. But it's important to note that in r4 right now the Pokemon's current HP is held.


Code:
	mov r0, r5
	mov r1, #0x3A
	ldr r3, =(0x803FBE8 +1)
	bl linker
	add r6, r6, #0x1
	cmp r4, r0
	beq loop
Here we have the total HP the Pokemon has being stored in R0. Note that Total HP is not Current HP. They are very distinct. What's happening here is a check to see if Total HP == Current HP. If it is, we'll move on to the next Pokemon. This is good if the routine was to increment HP, as we can't increment the HP of a full HP Pokemon. But if you're taking away HP, the total HP doesn't matter. Instead you should check that if you take away HP, it's current HP would be negative.

Code:
removeHP:
	sub r1, r4 #0x3 @amount to remove per step. Customize it
	cmp r1, #0x0
	bgt cont
	mov r4, #0x0
Uh, the compare should not be comparing to zero. Try this:

Code:
cmp r4, #0x3 @assuming you're taking away 3 HP
bge cont
mov r4, #0x0


I thought I'd just help you out by pointing out some of the inconsistencies and the changes you'd need to make to make this work. I know you're just editing my gain HP routine, and trying to help. Good luck GoGo. :)

This is what I get for not testing :P
Changes added to the post
 
It would be great, if i could warp via ASM in a script to a warp of my choice / to a location of my choice. I do not understand really function of this ASM snippet, because you don't say, which warp will be changed.

This particular routine changes every warp to a specific warp given by the variables. For the type of warping you describe, there are script commands which do that.
 
Update to Egg Check routine:
Now uses var 0x8004 for party slot instead of the user manually using the species.
Good idea to use with a special 0x9F(FR)

FR
Spoiler:

EM (untested but idk why it wouldnt work)
Spoiler:

I would recommend using this version of the routine over the old one as its more efficient and works better.
Thanks to Touched Senpai for telling me something I shouldve known!, but was too stupid to remember.
 

HP Regeneration per step


Intro:
Basically a routine to regenerate a Pokemon's HP every step. In this routine it's set to 3 per step. You may want to modify the exact amount to a percentage or something (see the commented line).

How to insert:

First compile and insert the following routine into free space.

Spoiler:


Now in a hex editor navigate to 0x6D5F6. There you will need to insert the following byte changes:
Code:
 01 4A 10 47 00 00 XX XX XX 08
Where XX XX XX is the pointer to where you inserted the above routine +1.

Usage:

There isn't any usage. It's automatically done. You can change the amount generated by reading the line in the code which I've commented.

This is nice, but, it will be better if it is toggleable by flag
 
While clowning around in my game, I stumbled upon a bug with Protean. The Gale Wings ability (which Otachi has) trips Protean and changes the monster into a Flying type for some weird reason.



Video is silly but it does demonstrate the bug.
 
It would be great, if i could warp via ASM in a script to a warp of my choice / to a location of my choice. I do not understand really function of this ASM snippet, because you don't say, which warp will be changed.

I don't understand what you are saying here. The routine currently changes the destination of all warps until untoggled.

This is nice, but, it will be better if it is toggleable by flag
Pretty simple change. I think it's like the second ASM tutorial I made which covers this. The thing with flag toggling is that everyone wants to use a different flag, and some people prefer variables. Better to do it yourself if you want toggling imo.
 
Back
Top