• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • 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

239
Posts
8
Years
  • Age 31
  • Seen Apr 15, 2024
I would like someone to make an ASM Routine to have separate palletes for the OWs which appear on the World Map. (Fire Red)

Here are the offsets for the images
Male
Spoiler:


Female
Spoiler:

You actually probably don't need an assembly routine for this. I would use
Navenatox's dynamic overworld palettes patch
. You can just re-upload the female sprites and it will inherit a different palette number. And combined with JPAN's engine allows you to swap player overworld sprites, all with individual palettes.

Hope this helps :)
 

Delta231

A noob
681
Posts
7
Years
You actually probably don't need an assembly routine for this. I would use
Navenatox's dynamic overworld palettes patch
. You can just re-upload the female sprites and it will inherit a different palette number. And combined with JPAN's engine allows you to swap player overworld sprites, all with individual palettes.

Hope this helps :)

Does it really work? I kinda doubt that. :P
 
41
Posts
7
Years
  • Age 27
  • Seen Dec 16, 2018
here is the request of mine:

1. Other Forms
I am looking for a routine that allows 2 or more species to share similar dex number. By that, we can have a feature for Flabébé forms and other Pokémon
 
146
Posts
11
Years
  • CO
  • Seen Mar 16, 2023
XSE Special Command to delete pokemon

Hello,
After taking a tutorial from FBI we where able to come up with this.

Here is how it works:
Var 0x8004 value
0x0 = Players 1st Pokemon
0x1 = Players 2nd Pokemon
0x2 = Players 3rd Pokemon
0x3 = Players 4th Pokemon
0x4 = Players 5th Pokemon
0x5 = Players 6th Pokemon


So you could use Special 0x9F.
Which will let you choose the Pokemon you want deleted.
Then callasm 0x?????? +1(where "??????" is where you placed this routine).

C source:
Code:
[COLOR="Green"]
#include 

void delete_pokemon()
{
    u8 slot = var_8004; // get slot id from variable
    if (slot != 5) {
        memcpy(&party_player[slot], &party_player[slot + 1], 100 * (5 - slot));
    }
    memset(&party_player[5], 0x0, 100);
    return;
}
[/COLOR]

Pre-Compiled version:
Code:
[COLOR="Green"]
0C 4B 1B 78 10 B5 05 2B 0C D0 64 24 05 22 59 1C 
D2 1A 61 43 63 43 08 48 62 43 09 18 18 18 07 4B 
00 F0 12 F8 64 22 00 21 05 48 06 4B 00 F0 0C F8 
10 BD C0 46 C0 70 03 02 84 42 02 02 79 5E 1E 08 
78 44 02 02 D9 5E 1E 08 18 47 C0 46
[/COLOR]
Place in free aligned location.

Xse Test Script:
Code:
[COLOR="Green"]
#dynamic 0x810000

#org @start
lockall
faceplayer
msgbox @question 0x5
compare 0x800D 0x1
if 0x1 goto @yes
msgbox @no 0x6
releaseall
end

#org @yes
msgbox @delete 0x6
special 0x9F
waitstate
callasm 0x??????+1  //make sure to change this to pointer where you put routine
msgbox @done 0x6
release
end


#org @question
= Would you like me to delete a Pokemon?

#org @delete
=Alright then here we go!

#org @done
= There the deed has been done!

#org @no
= Maybe next time then.
Hope this helps and credit to FBI once again.
[/COLOR]

Hope this helps.
 
457
Posts
10
Years
  • Age 29
  • Seen Apr 9, 2024
This post motivated me to create an actual regional dex instead of just giving a national dex at the start, so thanks :D I've added some extra routines to do things like display the correct regional dex number in summary screens, displaying dex info on capture, and having the proper regional dex count. New hooks:
Code:
.thumb
.align

.equ number_of_mons_in_regional_dex,	300	//or however long you wanted your regional dex to be
.equ number_of_mons_in_national_dex,	721





data_on_capture_hook:	//0x08106B84 via r1
	bl species_to_regional_dex_number
	cmp r0, #0x0
	bne capture_display_return
	ldr r0, add_task_no_capture_display
	bx r0

capture_display_return:
	ldr r0, add_task_capture_display
	bx r0





habitat_dex_regional_limit_hook:	//0x08106810 via r1
	push {r4, lr}
	mov r4, r0
	bl haz_national_dex_bool
	cmp r0, #0x1
	beq habitat_dex_regional_limit_return	//valid
	mov r0, r4
	bl species_to_regional_dex_number
	cmp r0, #0x0
	beq habitat_dex_regional_limit_return	//not in regional dex, return 0
	mov r0, #0x1

habitat_dex_regional_limit_return:
	pop {r4}
	pop {r1}
	bx r1





dex_seeable_mon_hook:	//0x08043F90 via r1
	push {r4, lr}
	mov r4, r0
	bl haz_national_dex_bool
	cmp r0, #0x0
	beq only_regional_numbered
//national
	mov r0, r4
	bl species_to_national_dex_number_1
	b dex_seeable_mon_check_valid_species

only_regional_numbered:
	mov r0, r4
	bl species_to_regional_dex_number

dex_seeable_mon_check_valid_species:
	cmp r0, #0x0
	bne dex_seeable_mon_return
	ldr r0, full_halfword

dex_seeable_mon_return:
	pop {r4}
	pop {r1}
	bx r1
.align
full_halfword:	.word 0xFFFF





dex_evolution_fix_hook:	//0x080CE91A via r1
	bl species_to_regional_dex_number
	cmp r0, #0x0	//not in regional dex, invalid
	beq dex_evolution_failure
	ldr r0, dex_evolution_success_return
	bx r0

dex_evolution_failure:
	mov r0, #0x11
	strh r0, [r5, #0x8]
	mov r2, #0x1
	ldr r1, dex_evolution_failure_return
	bx r1





dex_display_counts_hook:	//0x08104BBC via r2
	//r0: mode
	push {lr}
	cmp r1, #0x0
	beq call_regional_count
	bl national_pokedex_count
	b dex_display_counts_return

call_regional_count:
	bl dex_regional_count_hook

dex_display_counts_return:
	pop {pc}





dex_regional_count_hook:	//0x08088EDC via r1
	push {r4-r6, lr}
	mov r6, r0	//mode
	mov r4, #0x1	//loop
	mov r5, #0x0	//counter

dex_regional_count_loop:
	lsl r0, r4, #0x1	//loop times 2
	adr r1, regional_dex_order
	ldrh r0, [r1, r0]	//req species
	mov r1, r6	//mode
	mov r2, #0x1	//input is SPECIES
	bl dex_flag_check
	add r5, r5, r0
	add r4, #0x1
	ldr r0, regional_dex_limit
	cmp r4, r0
	blo dex_regional_count_loop
	mov r0, r5
	pop {r4-r6, pc}





dex_display_hook:	//0x0810352C via r1
	ldr r1, regional_dex_limit
	cmp r0, #0x0
	beq store_dex_limit_and_return
	ldr r1, national_dex_limit

store_dex_limit_and_return:
	str r1, [sp, #0x0]
	ldr r0, regional_dex_limit_return
	bx r0





regional_dex_hook:	//0x0810356C via r0
	mov r4, r8
	add r4, #0x1
	lsl r0, r4, #0x1	//index times 2
	adr r1, regional_dex_order
	ldrh r0, [r1, r0]
	bl species_to_national_dex_number_1
	mov r5, r0
	mov r1, #0x0
	ldr r2, regional_dex_hook_return
	bx r2





store_last_dex_seen_hook:	//0x081035B4 via r1
	str r0, [r2]
	mov r10, r4
	mov r4, r3
	ldr r0, def_store_string_dex_number
	bx r0





lazy_regional_dex_end_hook:	//0x081035F4 via r0
	mov r0, r8
	ldr r1, regional_dex_limit
	cmp r0, r1
	blo regional_dex_hook
	ldr r0, end_dex_display_return
	bx r0





display_regional_num_hook:	//0x08104A66 via r1
	mov r5, r0	//save species
	bl haz_national_dex_bool
	cmp r0, #0x0
	beq use_regional_dex_ordering
	ldr r1, dex_malloc_ptr
	ldr r1, [r1]
	add r1, #0x42
	ldrb r1, [r1]
	cmp r1, #0x0	//check if looking at regional dex
	beq use_regional_dex_ordering
	mov r0, r5
	bl species_to_national_dex_number_1
	b display_dex_number_return

use_regional_dex_ordering:
	mov r0, r5
	bl species_to_regional_dex_number	

display_dex_number_return:
	mov r5, r0
	ldr r0, dex_number_display_return
	bx r0





species_to_regional_dex_number:
	adr r3, regional_dex_order
	mov r2, r0	//req species
	mov r0, #0x0	//loop counter
find_regional_number_loop:
	lsl r1, r0, #0x1
	ldrh r1, [r3, r1]
	cmp r1, r2
	beq species_to_regional_dex_return
	add r0, #0x1
	ldr r1, regional_dex_limit
	cmp r0, r1
	bls find_regional_number_loop
	mov r0, #0x0	//not in dex: set number to 0
species_to_regional_dex_return:
	bx lr



species_to_national_dex_number_1:
	ldr r1, f_species_to_nat_dex
	bx r1
.align
f_species_to_nat_dex:	.word 0x08043298 + 1

haz_national_dex_bool:
	ldr r0, f_haz_national_check
	bx r0
.align
f_haz_national_check:	.word 0x0806E25C + 1

dex_flag_check:
	ldr r3, f_dex_flag_check
	bx r3
.align
f_dex_flag_check:	.word 0x08104AB0 + 1

national_pokedex_count:
	ldr r1, f_national_pokedex_count
	bx r1
.align
f_national_pokedex_count:	.word 0x08088E8C + 1



.align
add_task_no_capture_display:	.word 0x08106B90 + 1
add_task_capture_display:	.word 0x08106BA4 + 1
dex_evolution_success_return:	.word 0x080CE948 + 1
dex_evolution_failure_return:	.word 0x080CE924 + 1
regional_dex_limit:	.word number_of_mons_in_regional_dex
national_dex_limit:	.word number_of_mons_in_national_dex
regional_dex_limit_return:	.word 0x0810353a + 1
regional_dex_hook_return:	.word 0x08103578 + 1
def_store_string_dex_number:	.word 0x081035D6 + 1
end_dex_display_return:	.word 0x08103906 + 1
dex_malloc_ptr:			.word 0x0203ACF0
dex_number_display_return:	.word 0x08104A70 + 1

regional_dex_order:
.short 0x0000
.short CHIKORITA
.short BAYLEEF
.short MEGANIUM
etc
For anyone using Touched's scripts/ASMAGIX:
Code:
data_on_capture_hook		08106B84	1
dex_seeable_mon_hook		08043F90	1
dex_evolution_fix_hook		080CE91A	1
dex_display_counts_hook		08104BBC	2
dex_regional_count_hook		08088EDC	1
dex_display_hook		0810352C	1
regional_dex_hook		0810356C	0
store_last_dex_seen_hook	081035B4	1
lazy_regional_dex_end_hook	081035F4	0
display_regional_num_hook	08104A66	1
habitat_dex_regional_limit_hook	08106810	1

I have modified and enhanced azurile13's (credits and kudos to him) routine to make this supported on the Compiler's THUMB.bat. These are the things I modified:
  • Added routines creating the hooks that are to be copy-pasted on their respective locations. There are 11 hooks.
  • Added the master location of the routine in which the hooks will create locations for those routines. Insert your free space on .equ MyLoc. Format: 0x###### (Hexadecimal Number)
  • Created and added a new index list of Pokémon up to Generation VI including the formes in style of KDS/Chacha Dinosaur from the filenames of MrDollSteak's sprites in his Sugimori and Gen VI threads. I think there is no master index list for Generation VII. If there is, please PM me and I will add those.
  • With the list created as stated above, you will just have to create your own Regional Pokédex by copy-pasting from your Excel and Notepad file to below "regional_dex_order" and .hword 0x0000 should be first in the list. Make sure the names are all CAPS-LOCKED. In case of Nidorans, Farfetch'd, Mr. Mime, Ho-Oh, Mime Jr., Porygon-Z, and Flabébé, their characters are changed so you'll have to look for them in the master list. NOTE: Cofagrigus have been filtered out and changed into asterisks (*). Remember to correct its name before generating the binary file otherwise the .asm file won't work.

Custom Regional Pokédex for FireRed:
Spoiler:
 
Last edited:
5,256
Posts
16
Years

Deposit entire team but one


Just going to publish this combination of two routines and a script excerpt that you can use to let the player select one Pokémon from their team, and then deposit the rest of their team.

Spoiler: Script
Code:
...
countpokemon
callasm ROUTINE_ONE+1
compare LASTRESULT 0x1
if B_<> goto @snippet1
msgbox @string1 MSG_NORMAL
call @snippet2
callasm ROUTINE_TWO+1
textcolor 0x2 // black
bufferpartypokemon 0x0 0x0
bufferboxname 0x1 0x4035
checkflag 0x834
if 0x1 goto @snippet3
msgbox @string2 MSG_NORMAL
goto @snippet4

//---------------
#org @snippet1
msgbox @string3 MSG_NORMAL
release
end

//---------------
#org @snippet2
special 0x9F
waitstate
special2 LASTRESULT 0x147
compare LASTRESULT 0x19C
if 0x1 goto @egg
compare 0x8004 0x5
if 0x2 goto @exited_out
return

//---------------
#org @snippet3
msgbox @string4 MSG_NORMAL
goto @snippet4

//---------------
#org @snippet4
...

//---------
// Strings
//---------
#org @string1
= You are only allowed to bring one\nPOKéMON.\pPlease select which one you would\nlike to bring.

#org @string2
= [buffer1] will join you.\pThe rest of your team was\ntransferred to SOMEONE's PC.\pThey were placed starting\nin BOX ["][buffer2]."

#org @string3
= You are only allowed to bring one\nPOKéMON.\pNormally, we would offer to deposit\nthe rest of your team into a BOX.\pHowever, it seems like all of your\nBOXES are full.\pPlease make room and return later.

#org @string4
= [buffer1] will join you.\pThe rest of your team was\ntransferred to BILL's PC.\pThey were placed starting\nin BOX ["][buffer2]."

Spoiler: ROUTINE_ONE
Code:
.thumb

@ This routine loops through the player's boxes to make sure there is room in a given box to deposit the entire team

main:
    push {r4-r7, lr}
    ldr r0, =(0x020370D0) @ var_800D
    ldrh r0, [r0]
    sub r0, #2 @ party size - 1
    mov r4, r0
    mov r5, #0
    
box_loop:
    mov r6, #0 @ box_id
    mov r7, #0 @ pos_in_box
    
pokemon_in_box_loop:
    mov r0, r6
    mov r1, r7
    ldr r3, =(0x0808BD30+1) @ pokemon_by_box_and_position
    bl call_via_r3
    mov r1, #0xB @ req_species
    ldr r3, =(0x0803FD44+1) @ pokemon_getattr_encrypted
    bl call_via_r3
    cmp r0, #0
    beq empty_space_found

next_loop:
    add r7, #1
    cmp r7, #30
    bls pokemon_in_box_loop

completed_current_box:
    add r6, #1
    cmp r6, #14
    bge not_enough_space
    mov r7, #0
    b pokemon_in_box_loop

empty_space_found:
    add r5, #1
    cmp r5, r4
    bls next_loop

enough_space:
    mov r0, #1
    b end
    
not_enough_space:
    mov r0, #0
    
end:
    ldr r1, =(0x020370D0) @ var_800D
    str r0, [r1]
    pop {r4-r7}
    pop {r3}

call_via_r3:
    bx r3

.pool

Spoiler: ROUTINE_TWO
Code:
.thumb

@ This routine loops through the player's party, depositing every slot (slot 0 to 5) except for the slot number in var 8004
@ It then copies the Pokémon in the remaining slot to slot 0, and then erases each Pokémon from slots 1 to 5

main:
    push {r4-r6,lr}
    ldr r4, =(0x020370C0) @ var_8004
    ldrh r4, [r4]
    ldr r5, =(0x02024284) @ party_player
    mov r6, #0

loop:
    cmp r6, #6
    beq continue
    cmp r6, r4
    beq skip
    mov r1, #0x64
    mul r1, r6
    add r0, r1, r5
    ldr r3, =(0x08040B90|1) @ pokemon_add_to_pc
    bl call_via_r3

skip:
    add r6, #1
    b loop

continue:
    mov r1, #0x64
    mul r1, r4
    add r1, r5
    mov r0, r5
    mov r2, #0x64
    ldr r3, =(0x081E5E78|1) @ memcpy
    bl call_via_r3
    ldr r0, =(0x02024284+0x64) @ second Pokémon party address
    ldr r1, =(0x081F42A0) @ just a random 500 (dec) 00 bytes in the ROM
    ldrh r2, =(0x1F4)
    ldr r3, =(0x081E5E78|1) @ memcpy
    bl call_via_r3
    pop {r4-r6}
    pop {r3}

call_via_r3:
    bx r3

.pool
 
Last edited:

Lunos

Random Uruguayan User
3,114
Posts
15
Years
Exp. All / Gen. 6 Exp. Share [Emerald]
This routine was created by Samu from Wahack and it was posted right here. All the credits belong to him.

I'm afraid that I'll have to leave the comments in Spanish because I don't know how to properly translate them to English due to my lack of knowledge on the ASM programming language. Sorry :(

ASM Routine:
Code:
.thumb
.align 2

/****** NEW GEN EXP SHARE + EGG EXP FIX *******
************************************************
************************************************
************************************************
Créditos a BluRose & Lunos *********************
************************************************
************************************************/

no_crash:
	ldr r0, [r5]
	mov r1, r0
	add r1, #0x53
	ldrb r0, [r1]
	
flag_check:				@Se encarga de comprobar si hemos activado el flag
	push {r0-r2}
	ldr r0, flag_number
	ldr r2, flag_routine
	push {r1-r3}
	bl linker
	pop {r1-r3}
	cmp r0, #0x1		@Compara el flag con 0x1 (activado)
	bne routine_off
	pop {r0-r2}	
	
main:
	@Comprobar el slot y guardarlo en una variable.
	push {r3-r6}
	ldr r6, slot_var		@Carga en r3 el slot del pokemon
	ldrb r3, [r6]
	ldr r4, is_egg_party	
	mov r5, #0x64			
	mul r5, r5, r3			@Calcula las posiciones a avanzar
	ldrb r4, [r4, r5]		@Carga en r4 el byte egg/not
	cmp r4, #0x6
	beq pokemonIsEgg
	mov r2, #0x1
	b update_slot
	
pokemonIsEgg:
	mov r2, #0x0			@Establece r2 en 0 (no ganará exp)
	
update_slot:				@Actualiza y resetea el valor del slot
	add r3, #0x1
	cmp r3, #0x6
	bne end
	mov r3, #0x0
	
end:
	strh r3, [r6]
	pop {r3-r6}
	
return:
	push {r2}
	ldr r2, return_dir
	bx r2
	
routine_off:				@Ejecuta las instrucciones "originales"
	pop {r0-r2}
	mov r2, #0x1
	and r2, r0
	b return

linker:
	bx r2
	
.align 2
flag_number:
	.word 0x00000XXX 					@Elige el numero del flag
flag_routine:
	.word 0x0809D790 +1				@Rutina que checkea el flag
slot_var: 								@Escoge una variable temporal (no uses la 0x8000,
	.word 0x020275D6 + (0x800Y * 2)	@el juego la utiliza al inicializar combates dobles
is_egg_party:
	.word 0x020244EC + 0x13				@Byte que comprueba si es un huevo
return_dir:
	.word 0x0804A592 + 1				@Dirección de retorno a la rutina

Note: In order to use this routine, you must set a flag and a temp var in the Lines 72 and 76 respectively.

After inserting the routine in your ROM, open your Pokémon Emerald ROM in a hex editor and make the following changes:
-04A4BE: 02 21
-04A634: 01 20
-04A58A: C0 46 00 4A 10 47 XX XX XX 08 04 BC
Note: XX XX XX = Pointer to the ASM Routine, +1.
Example: If I were to put it in E3CF80, I'd have to replace XX XX XX with 81 CF E3.


Relevant information:
The flag handles the effect itself. If the flag you gave to the routine is OFF (0x0) the Exp. Share will work just like in Gen. 3. If it's ON (0x1), it'll work like in Gen. 1/6/7.

Result:

I'm sure there's ways to make this better, so if anyone could give that a try, that'd be awesome :)
 

Skeli

Lord of the Rings
300
Posts
10
Years
Custom Victory Music [FR]:
Everyone knows of the code that allows you have custom trainer battle music, but as far as I'm aware, no one has ever written code that allows you have custom victory music (that jingle that plays when you win a battle).
This code is very similar to the custom trainer battle music in which it loads the data from a table structured [Byte - Trainer Class] 00 [HWord - Song ID]. The table is ended with a 0xFFFF.
But before you do anything though, you need to decide how many jingles you want. If you don't need more than 7, just compile the code as it is. If you don't modify the code, the table is at 0x15740 (there's enough space there for 7 jingles, just make sure you put the end 0xFFFF). Otherwise change the last line in the code to your table's pointer.
In order to get this working all you need to do is compile the ASM and copy whatever's at the offset 0x156F4 in the bin into your Rom. Due to the way the original code was written, the new code can be completely pasted over.
Enjoy!
Code:
.text
.align 2
.thumb
.thumb_func
.global victorymusic

@TableFormat: [Byte - Trainer Class] 00 [HWord - Song ID]
.org 0x156F4
Main:
	bl 0x35314
	ldr r1, .ScriptLoc
	ldr r0, =0x81D87EF
	str r0, [r1]
	ldr r2, .TrainerSomething
	ldr r0, .TrainerBattleFlagID

GetTrainerType:
	ldrh    r1, [r0]
	lsl    	r0, r1, #0x2
	add    	r0, r1
	lsl    	r0, #0x3
	add    	r0, r2
	ldrb    r0, [r0, #1]

CheckTable:
	ldr r1, .Table
	ldrh r3, =0xFFFF

Loop:
	ldrb r2, [r1]
	cmp r0, r2
	beq LoadSpecialSong
	add r1, #0x4
	ldrh r2, [r1]
	cmp r2, r3
	beq 0x1575E @Regular Victory Song
	b Loop

LoadSpecialSong:
	add r1, #0x2
	ldrh r0, [r1]
	b 0x15762

.align 2
.ScriptLoc: 		.word 0x2023D74
.TrainerSomething: 	.word 0x823EAC8
.TrainerBattleFlagID: 	.word 0x20386AE
.Table: 		.word 0x8015740
 

Delta231

A noob
681
Posts
7
Years
I want to make a request. As Dizzy's Various features added Expansion for Hall of Frame fix. Is there any way to port to Fire Red?
 

Delta231

A noob
681
Posts
7
Years
Exp. All / Gen. 6 Exp. Share [Emerald]
This routine was created by Samu from Wahack and it was posted right here. All the credits belong to him.

I'm afraid that I'll have to leave the comments in Spanish because I don't know how to properly translate them to English due to my lack of knowledge on the ASM programming language. Sorry :(

ASM Routine:
Code:
.thumb
.align 2

/****** NEW GEN EXP SHARE + EGG EXP FIX *******
************************************************
************************************************
************************************************
Créditos a BluRose & Lunos *********************
************************************************
************************************************/

no_crash:
	ldr r0, [r5]
	mov r1, r0
	add r1, #0x53
	ldrb r0, [r1]
	
flag_check:				@Se encarga de comprobar si hemos activado el flag
	push {r0-r2}
	ldr r0, flag_number
	ldr r2, flag_routine
	push {r1-r3}
	bl linker
	pop {r1-r3}
	cmp r0, #0x1		@Compara el flag con 0x1 (activado)
	bne routine_off
	pop {r0-r2}	
	
main:
	@Comprobar el slot y guardarlo en una variable.
	push {r3-r6}
	ldr r6, slot_var		@Carga en r3 el slot del pokemon
	ldrb r3, [r6]
	ldr r4, is_egg_party	
	mov r5, #0x64			
	mul r5, r5, r3			@Calcula las posiciones a avanzar
	ldrb r4, [r4, r5]		@Carga en r4 el byte egg/not
	cmp r4, #0x6
	beq pokemonIsEgg
	mov r2, #0x1
	b update_slot
	
pokemonIsEgg:
	mov r2, #0x0			@Establece r2 en 0 (no ganará exp)
	
update_slot:				@Actualiza y resetea el valor del slot
	add r3, #0x1
	cmp r3, #0x6
	bne end
	mov r3, #0x0
	
end:
	strh r3, [r6]
	pop {r3-r6}
	
return:
	push {r2}
	ldr r2, return_dir
	bx r2
	
routine_off:				@Ejecuta las instrucciones "originales"
	pop {r0-r2}
	mov r2, #0x1
	and r2, r0
	b return

linker:
	bx r2
	
.align 2
flag_number:
	.word 0x00000XXX 					@Elige el numero del flag
flag_routine:
	.word 0x0809D790 +1				@Rutina que checkea el flag
slot_var: 								@Escoge una variable temporal (no uses la 0x8000,
	.word 0x020275D6 + (0x800Y * 2)	@el juego la utiliza al inicializar combates dobles
is_egg_party:
	.word 0x020244EC + 0x13				@Byte que comprueba si es un huevo
return_dir:
	.word 0x0804A592 + 1				@Dirección de retorno a la rutina

Note: In order to use this routine, you must set a flag and a temp var in the Lines 72 and 76 respectively.

After inserting the routine in your ROM, open your Pokémon Emerald ROM in a hex editor and make the following changes:
-04A4BE: 02 21
-04A634: 01 20
-04A58A: C0 46 00 4A 10 47 XX XX XX 08 04 BC
Note: XX XX XX = Pointer to the ASM Routine, +1.
Example: If I were to put it in E3CF80, I'd have to replace XX XX XX with 81 CF E3.


Relevant information:
The flag handles the effect itself. If the flag you gave to the routine is OFF (0x0) the Exp. Share will work just like in Gen. 3. If it's ON (0x1), it'll work like in Gen. 1/6/7.

Result:

I'm sure there's ways to make this better, so if anyone could give that a try, that'd be awesome :)


Fire Red Port done by Samu from Whack a hack Foro.
Original Link to the post


Code:
.align 2
.thumb

/****** NEW GEN EXP SHARE + EGG EXP FIX  *******
************** FIRE RED VERSION ********************
************************************************
It Is important to note that you HAVE Tto choose the flag you
wanna use to toggle on/off the routine.
In the same way, you also have to choose a temp variable
for this routine to store a control value. (it will actually count
the current pokemon slot from it's checking)
************************************************
************************************************
************************************************
Credits to BluRose & Lunos          *********************
& Samu (lmao almost forgot myself)  ******************
************************************************
************************************************/

no_crash:
	ldr r0, [r5]
	mov r1, r0
	add r1, #0x53
	ldrb r0, [r1]
	
flag_check:			   
@will
 check the flag value, return it to r0 and compare it
	push {r0-r2}
	ldr r0, flag_number
	ldr r2, flag_routine
	push {r1-r3}
	bl linker
	pop {r1-r3}
	cmp r0, #0x1		        @If flag is set (0x1) routine is "on", otherwise is "off"
	bne routine_off
	pop {r0-r2}	
	
main:
   
@Che
cks the team slot to check and stores it into a temp variable
	push {r3-r6}
	ldr r6, slot_var		        @Loads the slot in r3
	ldrb r3, [r6]
	ldr r4, is_egg_party	
	mov r5, #0x64			
	mul r5, r5, r3			  
	ldrb r4, [r4, r5]		        @Loads in r4 the pointer to the team_slot "egg_byte"
	cmp r4, #0x6                    @if byte value is 0x6 -> pokemon is an egg
	beq pokemonIsEgg
	mov r2, #0x1                    @otherwise set r0 to 0x1 (will gain exp)
	b update_slot
	
pokemonIsEgg:
	mov r2, #0x0			@sets r2 to 0x0 (will not gain exp)
	
update_slot:				@updates and reset slot value.
	add r3, #0x1
	cmp r3, #0x6
	bne end
	mov r3, #0x0
	
end:
	strh r3, [r6]
	pop {r3-r6}
	
return:
	push {r2}
	ldr r2, return_dir
	bx r2
	
routine_off:				@"original instructions"
	pop {r0-r2}
	mov r2, #0x1
	and r2, r0
	b return

linker:
	bx r2
	
.align 2
flag_number:
	.word 0x00000[XXX] 					@Choose the flag number
flag_routine:
	.word 0x0806E6D0 +1				@Routine that returns flag value to r0
slot_var: 								@choose a temp variable
	.word 0x020270B8 + (0x800[X] * 2)	
is_egg_party:
	.word 0x02024284 + 0x13				@"eggByte" of first pokemon slot
return_dir:
	.word 0x08021CD0 + 1	               @routine return direction


The following changes in the rom are needed:
- Go to 0x08021C3A and overwrite with "02 21".
- Go to 0x08021D70 and write "01 20".
- Go to 0x08021CC6 and write the following:
"C0 46 00 4A 10 47 [XX+1 XX XX 08] 04 BC"
where [XX+1 XX XX 08] is the reverse pointer +1 to the offset of this routine.


Example: If I were to put it in 130F40, I'd have to replace XX XX XX with 41 0F 13.
 
Last edited:
51
Posts
9
Years
  • Age 33
  • Seen Nov 18, 2023
Fire Red Port done by Samu from Whack a hack Foro.
Original Link to the post


Code:
.align 2
.thumb

/****** NEW GEN EXP SHARE + EGG EXP FIX  *******
************** FIRE RED VERSION ********************
************************************************
It Is important to note that you HAVE Tto choose the flag you
wanna use to toggle on/off the routine.
In the same way, you also have to choose a temp variable
for this routine to store a control value. (it will actually count
the current pokemon slot from it's checking)
************************************************
************************************************
************************************************
Credits to BluRose & Lunos          *********************
& Samu (lmao almost forgot myself)  ******************
************************************************
************************************************/

no_crash:
	ldr r0, [r5]
	mov r1, r0
	add r1, #0x53
	ldrb r0, [r1]
	
flag_check:			   
@will
 check the flag value, return it to r0 and compare it
	push {r0-r2}
	ldr r0, flag_number
	ldr r2, flag_routine
	push {r1-r3}
	bl linker
	pop {r1-r3}
	cmp r0, #0x1		        @If flag is set (0x1) routine is "on", otherwise is "off"
	bne routine_off
	pop {r0-r2}	
	
main:
   
@Che
cks the team slot to check and stores it into a temp variable
	push {r3-r6}
	ldr r6, slot_var		        @Loads the slot in r3
	ldrb r3, [r6]
	ldr r4, is_egg_party	
	mov r5, #0x64			
	mul r5, r5, r3			  
	ldrb r4, [r4, r5]		        @Loads in r4 the pointer to the team_slot "egg_byte"
	cmp r4, #0x6                    @if byte value is 0x6 -> pokemon is an egg
	beq pokemonIsEgg
	mov r2, #0x1                    @otherwise set r0 to 0x1 (will gain exp)
	b update_slot
	
pokemonIsEgg:
	mov r2, #0x0			@sets r2 to 0x0 (will not gain exp)
	
update_slot:				@updates and reset slot value.
	add r3, #0x1
	cmp r3, #0x6
	bne end
	mov r3, #0x0
	
end:
	strh r3, [r6]
	pop {r3-r6}
	
return:
	push {r2}
	ldr r2, return_dir
	bx r2
	
routine_off:				@"original instructions"
	pop {r0-r2}
	mov r2, #0x1
	and r2, r0
	b return

linker:
	bx r2
	
.align 2
flag_number:
	.word 0x00000[XXX] 					@Choose the flag number
flag_routine:
	.word 0x0806E6D0 +1				@Routine that returns flag value to r0
slot_var: 								@choose a temp variable
	.word 0x020270B8 + (0x800[X] * 2)	
is_egg_party:
	.word 0x02024284 + 0x13				@"eggByte" of first pokemon slot
return_dir:
	.word 0x08021CD0 + 1	               @routine return direction


The following changes in the rom are needed:
- Go to 0x08021C3A and overwrite with "02 21".
- Go to 0x08021D70 and write "01 20".
- Go to 0x08021CC6 and write the following:
"C0 46 00 4A 10 47 [XX+1 XX XX 08] 04 BC"
where [XX+1 XX XX 08] is the reverse pointer +1 to the offset of this routine.


Example: If I were to put it in 130F40, I'd have to replace XX XX XX with 41 0F 13.

It doesn't work correctly.

Without asm:
pidgey level 3 - 24 exp point
with exp share - 12 + 12 exp point

With this routine:
pidgey level 3 - 12 exp point
with exp share flag off - 12 + 24 exp point
with exp share flag on - 12 + 12 + 12 + ... exp point
 

Skeli

Lord of the Rings
300
Posts
10
Years
Auto Run [FR]
Compile this ASM, copy everything past offset 0x5BA30 in the bin file, and paste in at 0x5BA30 in your rom. This checks if a flag is set to allow you to run automatically. The default is the original running shoes flag in Fire Red. This also removes the need for a flag to be set in order for the player to run. If you want a flag, you'll have to hook to a new routine altogether.
Code:
.thumb
.global AutoRun

.org 0x5BA30
CheckAutoRunFlag:
ldr r0, .Flag
bl 0x6E6D0 @Flag Check
lsl r0, #0x18
cmp r0, #0x0
bne CheckRunTile

CheckBButton:
mov r0, #0x2
and r5, r0
cmp r5, #0x0
beq 0x5BA8C @Walk

CheckRunTile:
ldr r2, .NPC_States
ldrb r1, [r6, #0x5]
lsl r0, r1, #0x3
add r0, r1
lsl r0, #0x2
add r0, r2
ldrb r0, [r0, #0x1E]
bl 0xBD488 @Runnable Tile
cmp r0, #0x0
bne 0x5BA8C @Walk

Run:
mov r0, r4
bl 0x5BAAC
cmp r0, #0x0
beq 0x5BA74
mov r0, r4
bl 0x5C194
b 0x5BA7A

.align 2
.Flag: .word 0x82F
.NPC_States: .word 0x2036E38

This next piece of code allows you to toggle auto run through the use of the L or R buttons. Just make sure you disable the help menu (put 1D E0 at 0x13B8C2), and flashbacks (somewhere on PC). The bottom area of the code is where the customizable stuff is. If you don't know much about Ram locations leave the helper byte location alone (it's probably fine for you). Also, this code only allows you to change the toggle every second of playtime (so no spamming).
Note:
-The toggling rarely works when the game is in Turbo Mode.
-This code will only work if you've inserted the above code.
-This code must have the same flag as above to work.


Code:
.thumb
.global AutoRunToggle

@Hook at 0x8056458 with r0
@00 48 00 47 XX+1 XX XX 0x8 at 0x8056458

Main:
lsr r1, #0x10
mov r4, r1

CheckButtonPress:
ldrb r2, .Key
ldr r0, .KeyInput
ldrb r0, [r0, #0x1]
mov r1, #0x3
and r0, r1
cmp r0, r2
bne Return

CheckSecondPass:
ldr r0, .HelperByte
ldrb r0, [r0]
ldr r1, .SaveBlock2
ldr r1, [r1]
ldrb r1, [r1, #0x11]
cmp r0, r1
beq Return

ChangeFlag:
ldrh r2, .Flag
mov r0, r2
ldr r1, .Flag_Decrypt
bl Linker
cmp r0, #0x0
bne ClearFlag

SetFlag:
mov r0, r2
ldr r1, .SetFlag
bl Linker
b UpdateHelper

ClearFlag:
mov r0, r2
ldr r1, .ClearFlag
bl Linker

UpdateHelper:
ldr r1, .SaveBlock2
ldr r1, [r1]
ldrb r1, [r1, #0x11]
ldr r0, .HelperByte
strb r1, [r0]

Return:
ldr r1, =0x8112B3D
bl Linker
ldr r1, =0x8056461

Linker:
bx r1

.align 2
.SaveBlock2: .word 0x300500C
.Flag_Decrypt: .word 0x806E6D1
.SetFlag: .word 0x806E681
.ClearFlag: .word 0x806E6A9
.KeyInput: .word 0x04000130
[B].HelperByte: .word 0x203D800 @Replace with custom loc
.Key: .word 0x1 @0x0 = L+R, 0x1 = L, 0x2 = R @Choose key
.Flag: .word 0x82F @Change to Custom Flag[/B]
 
Last edited:

Lunos

Random Uruguayan User
3,114
Posts
15
Years
Auto Run [FR]
Compile this ASM, copy everything past offset 0x5BA30 in the bin file, and paste in at 0x5BA30 in your rom. This checks if a flag is set to allow you to run automatically. The default is the original running shoes flag in Fire Red. This also removes the need for a flag to be set in order for the player to run. If you want a flag, you'll have to hook to a new routine altogether.
Code:
.thumb
.global AutoRun

.org 0x5BA30
CheckAutoRunFlag:
ldr r0, .Flag
bl 0x6E6D0 @Flag Check
lsl r0, #0x18
cmp r0, #0x0
bne CheckRunTile

CheckBButton:
mov r0, #0x2
and r5, r0
cmp r5, #0x0
beq 0x5BA8C @Walk

CheckRunTile:
ldr r2, .NPC_States
ldrb r1, [r6, #0x5]
lsl r0, r1, #0x3
add r0, r1
lsl r0, #0x2
add r0, r2
ldrb r0, [r0, #0x1E]
bl 0xBD488 @Runnable Tile
cmp r0, #0x0
bne 0x5BA8C @Walk

Run:
mov r0, r4
bl 0x5BAAC
cmp r0, #0x0
beq 0x5BA74
mov r0, r4
bl 0x5C194
b 0x5BA7A

.align 2
.Flag: .word 0x82F
.NPC_States: .word 0x2036E38

Would it be possible to modify it a little bit so when pressing a button like say.. the GBA's R Button, the flag is enabled or disabled? Then it would work just like in Pokémon Procyon/Deneb, a pair of Japanese ROM Hacks in which by pressing the R Button you can toggle ON or OFF the Running Shoes.
 
Last edited:

Skeli

Lord of the Rings
300
Posts
10
Years
Would it be possible to modify it a little bit so when pressing a button like say.. the GBA's R Button, the flag is enabled or disabled? Then it would work just like in Pokémon Procyon/Deneb, a pair of Japanese ROM Hacks in which by pressing the R Button you can toggle ON or OFF the Running Shoes.
They should really learn to share more often.

(Scroll up)
 
Last edited:

Lunos

Random Uruguayan User
3,114
Posts
15
Years
This next piece of code allows you to toggle auto run through the use of the L or R buttons. Just make sure you disable the help menu first (put 1D E0 at 0x13B8C2). The bottom of the code is where the customizable stuff is. If you don't know much about Ram locations leave the helper byte location alone (it's probably fine for you). Also, this code only allows you to change the toggle every second of playtime (so no spamming). Note that the the toggling rarely works when the game is in Turbo Mode.

Code:
.thumb
.global AutoRunToggle

@Hook at 0x8056458 with r0
@00 48 00 47 XX+1 XX XX 0x8 at 0x8056458

Main:
lsr r1, #0x10
mov r4, r1

CheckButtonPress:
ldrb r2, .Key
ldr r0, .KeyInput
ldrb r0, [r0, #0x1]
mov r1, #0x3
and r0, r1
cmp r0, r2
bne Return

CheckSecondPass:
ldr r0, .HelperByte
ldrb r0, [r0]
ldr r1, .SaveBlock2
ldr r1, [r1]
ldrb r1, [r1, #0x11]
cmp r0, r1
beq Return

ChangeFlag:
ldrh r2, .Flag
mov r0, r2
ldr r1, .Flag_Decrypt
bl Linker
cmp r0, #0x0
bne ClearFlag

SetFlag:
mov r0, r2
ldr r1, .SetFlag
bl Linker
b UpdateHelper

ClearFlag:
mov r0, r2
ldr r1, .ClearFlag
bl Linker

UpdateHelper:
ldr r1, .SaveBlock2
ldr r1, [r1]
ldrb r1, [r1, #0x11]
ldr r0, .HelperByte
strb r1, [r0]

Return:
ldr r1, =0x8112B3D
bl Linker
ldr r1, =0x8056461

Linker:
bx r1

.align 2
.SaveBlock2: .word 0x300500C
.Flag_Decrypt: .word 0x806E6D1
.SetFlag: .word 0x806E681
.ClearFlag: .word 0x806E6A9
.KeyInput: .word 0x04000130
[B].HelperByte: .word 0x203D800 @Replace with custom loc
.Key: .word 0x1 @0x0 = L+R, 0x1 = L, 0x2 = R @Choose key
.Flag: .word 0x82F @Change to Custom Flag[/B]

The first routine is working perfectly fine on my end, but this one's not.
1) I went to the offset 13B8C2 and wrote "1D E0".
2) I compiled the ASM Routine, the only changes I did to it were:
-Line 70: .Key: .word 0x2
-Line 71: .Flag: .word 0x200
3) I inserted the compiled routine in the offset 71A250.
4) I went to the offset 056458 and wrote: 00 48 00 47 51 A2 71 08
And then when I start the game, enable the Flag 0x200 and press the R Button, my character still walks and I still have to run by holding the B Button :/

EDIT: Fixed. I didn't get at first that I had to use both ASM Routines at the same time.
 
Last edited:
146
Posts
11
Years
  • CO
  • Seen Mar 16, 2023
Pokemon LoathingFriendship Evolution:
Code:
.text
.align 2
.thumb
.thumb_func
.global loathFriendship

main:
push {r0-r7}
add r0, r6, r7
lsl r0, r0, #0x3
add r0, r2, r0
add r3, r0, r3
ldrb r2, [r3, #0x2]
mov r0, r8
bl decrypt
mov r11, r0
pop {r0-r7}
mov r1, r11
cmp r1, #0x10
blo max_lowhappy
b exit

max_lowhappy:
mov r10, r3
pop {r0-r7}
mov r1, r10
ldr r0, evolution_loc
bx r0

exit:
pop {r0-r7}
ldr r0, no_evo
bx r0

decrypt: 
push {r0-r7}
mov r1, #0x20
ldr r2, decryptpoke
bx r2

.align 2
no_evo: .word 0x08043111
evolution_loc: .word 0x0804310D
decryptpoke: .word 0x0803FBE9

The Pokemons happiness must be between 0-10 to trigger the evolution.
To insert follow instructions in this thread.

I hope some find this useful.
I thought about trade evolution basically being just this.
A Pokemon so depressed it evolves...
 

Miko-chan

Haruka Fanboy
3
Posts
6
Years
Is there a port of the Disable Bag to Emerald?

Trying on my own, I was trying to convert this "Prevent Items" routine by JPAN here:
Spoiler:

The only problem I have now is finding the address of the routine that shows the "Items can't be used now." message.

Here's the original FR Version:
Spoiler:
Here's mine (omitted stuff for clarity):
Spoiler:
 
Back
Top