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

Quick Research & Development Thread

Faster Game Saving [FR]

Starting with Gen II, attempting to update the save on your current file would tell you that "There is already a save file. Is it OK to overwrite?" This needless extra step remained until Gen V, when it reverted the process back to one step.

To skip this step and save after just one prompt, change the byte at 0x6F874 from 0A to 56. This only applies to saving over your current profile. If you start a new game and try to save over the old profile, you'll still receive the extended overwrite warning.

Explanation: The subroutine at 0x6F86C gets loaded if the game detects there's already a save file. First it checks if the profile is different from the current one. If it's the same profile, it branches to 0x6F88C. This is indicated in hex by 0A D1. After branching, it'll load the "There is already a saved file" text string and corresponding subroutine.

What this change does is make the game branch instead to 0x6F924, which bypasses the already-present save subroutine and skips straight to saving the game.

I'm still not that good at ASM. If anything needs correcting, feel free to do so!
 
I made a script with the help of some asm made by FBI, he had a custom wild battle asm that helped me create a very cool and desirable event where I give away a pokemon and in return I would get a perfect iv pokemon right back. I made this for FIRE RED obviously and here is the script I made and I need some help with one thing for perfection's sake.

Spoiler:


Now, what I need help with is that I used special 0xbb. It is supposed to store the pokemon I selected into daycare, how I do I delete the daycare stored pokemon so there is no choice of getting it back, the whole point I made this was to get rid of the imperfect pokemon to fight a perfect version of it to re-raise. Thanks guys!
 
Pointer to expand object effect tables and limiter:

For Ruby:

Table:

AXVE- 0x1FCDE4

Limiters:

0x0803E2F8: 00 00 00 00

For Fire Red:

Table:

BPRE- 0x2528BC

Limiters:

0x08042508: 00 00 00 00

0x0804152C: 00 00 00 00

Credits to: JPAN

Spoiler:
 
Update the AI Priority move effects table [FR]
If you open a trainer editor and you edit aany trainer, you'll notice there's an option for "Trainer AI". By default, most of trainers are set in 0, and important trainers like Gym Leaders have this set to 7. There's a good explanation about how to setup the trainer AI in this post made by Samu from Whack a Hack forums (In spanish). Well, the point of this post is not that research.

If you set the trainer AI to 7, any trainer with that AI will start the battle giving priority to some moves that set the battle, like poisoning your Pokémon, increasing their speed, attack stats, etc. There is a table of move effects located at 0x81DBAA7 with a set of 0x37 move effects that have priority over other move effects during the beggining of the battle. The table has the following entries.

Code:
        .byte EFFECT_ATTACK_UP
	.byte EFFECT_DEFENSE_UP
	.byte EFFECT_SPEED_UP
	.byte EFFECT_SPECIAL_ATTACK_UP
	.byte EFFECT_SPECIAL_DEFENSE_UP
	.byte EFFECT_ACCURACY_UP
	.byte EFFECT_EVASION_UP
	.byte EFFECT_ATTACK_DOWN
	.byte EFFECT_DEFENSE_DOWN
	.byte EFFECT_SPEED_DOWN
	.byte EFFECT_SPECIAL_ATTACK_DOWN
	.byte EFFECT_SPECIAL_DEFENSE_DOWN
	.byte EFFECT_ACCURACY_DOWN
	.byte EFFECT_EVASION_DOWN
	.byte EFFECT_CONVERSION
	.byte EFFECT_LIGHT_SCREEN
	.byte EFFECT_SPECIAL_DEFENSE_UP_2
	.byte EFFECT_FOCUS_ENERGY
	.byte EFFECT_CONFUSE
	.byte EFFECT_ATTACK_UP_2
	.byte EFFECT_DEFENSE_UP_2
	.byte EFFECT_SPEED_UP_2
	.byte EFFECT_SPECIAL_ATTACK_UP_2
	.byte EFFECT_SPECIAL_DEFENSE_UP_2
	.byte EFFECT_ACCURACY_UP_2
	.byte EFFECT_EVASION_UP_2
	.byte EFFECT_ATTACK_DOWN_2
	.byte EFFECT_DEFENSE_DOWN_2
	.byte EFFECT_SPEED_DOWN_2
	.byte EFFECT_SPECIAL_ATTACK_DOWN_2
	.byte EFFECT_SPECIAL_DEFENSE_DOWN_2
	.byte EFFECT_ACCURACY_DOWN_2
	.byte EFFECT_EVASION_DOWN_2
	.byte EFFECT_REFLECT
	.byte EFFECT_POISON
	.byte EFFECT_PARALYZE
	.byte EFFECT_SUBSTITUTE
	.byte EFFECT_LEECH_SEED
	.byte EFFECT_MINIMIZE
	.byte EFFECT_CURSE
	.byte EFFECT_SWAGGER
	.byte EFFECT_CAMOUFLAGE
	.byte EFFECT_YAWN
	.byte EFFECT_DEFENSE_CURL
	.byte EFFECT_TORMENT
	.byte EFFECT_FLATTER
	.byte EFFECT_WILL_O_WISP
	.byte EFFECT_INGRAIN
	.byte EFFECT_IMPRISON
	.byte EFFECT_TEETER_DANCE
	.byte EFFECT_TICKLE
	.byte EFFECT_COSMIC_POWER
	.byte EFFECT_BULK_UP
	.byte EFFECT_CALM_MIND
	.byte EFFECT_CAMOUFLAGE

The pointer of this table is located at 0x81DBA96 so you can repoint the table and add new entries to the table so trainers with a high Ai might use moves on this table firstly.
 
I combined my work with the one from Doesnt. As a result, there are less bytes to write into freespace.
So, here's what to do to give exp points when you catch a pokemon:
1-The bytes to put into freespace: 2E E0 3F 02 02 00 2E 0C 3C 02 02 00 2E 0D 3C 02 02 00 23 00 F1 63 9A 1D 08 28 58 9A 1D 08

2-The bytes to replace at 1D9A53: 41 XX XX XX 08 (XX = pointer to the code above).

3-Just like Doesnt wrote earlier, replace the bytes at 15A68 with A1 5A 01 08.

It should work without problems, as I tested it before posting.

Thanks to Doesnt for telling me how to fix a music issue.
Is there a way to get around Rattata appearing as the captured Pokémon if you have an extended Dex?
 
[FR] Suppress Pokédex screen on new Pokémon capture
To prevent the Pokédex screen/animation from showing after catching a new Pokémon, nop the 22 bytes at 0x106B7A (that is, up to and including 0x106B8F). This will jump straight to the nickname prompt after a new Pokémon is caught (but will still show the "Pokémon X was added to the Pokédex" text if left unedited).
 
Last edited:
Change Vs Seeker Step Requirement (FR)
Change 0x0810C50E to your number in hex
 
Last edited:
Is there a way to get around Rattata appearing as the captured Pokémon if you have an extended Dex?

To prevent Rattata from appearing in the Pokedex and appearing the new captured Pokémon, you must expand the Habitats Table using a Hexadecimal editor and add each new Pokémon in the Habitats ... You can use PGE to add each new Pokémon to the habitats.

To find out where the Habitats table is located, and to learn more about it, go to the Froosty The_learner post.
FIRE RED habitat editing: https://www.pokecommunity.com/threads/379667
 
Last edited:
Making the EVs more "RBY/GSC-like" on FireRed

RBY and GSC are known for supporting "full EV spread", as the 510 EV limit didn't existed at the time. Bringing back the old Stat Exp system would be a very hard task, but I found a way to simulate the full EVs from past gens by limitting the max EV to 63 and reducing the EV divider from 4 to 1 (of course, removing the 510 EV limit would be a better solution, but I haven't found a way to do that with binary hacking).

This solution works on FireRed.

Step 1) Limit the EV cap to 63

From Touched's tutorial:
Address 0x0439FC = 0x3F (63)
Address 0x043A02 = 0x3F (63)

Step 2) Change EV divider to 1

I owe this one to Mr.Pkmn posting the hex addresses to do that. In that case, he shows how to change the EV divider from 4 to 2.

To make it 1, I have made some tests to find a value that A) stats would be correctly divided by 1 and B) would not screw up the stats (this one is dedicated to the HP EV divider).

The values I found are completely empirical, I have no idea of why they have worked and I haven't found any glitches until now (I have not tested link battles on my hack yet).

Here are the changes:

Address 0x03E582 = 0x02 (HP)
Address 0x03E5CE = 0x0F (ATK)
Address 0x03E614 = 0x0F (DEF)
Address 0x03E65A = 0x0F (SPD)
Address 0x03E6A0 = 0x0F (SAT)
Address 0x03E6E6 = 0x0F (SDE)


Credits:
- Touched
- Mr.Pkmn
________________

KNOWN PROBLEMS:

About that 63 limit... well, a Pokémon won't get past it by gaining EV by battle. However, Vitamins (HP Up, Protein, etc.) will completely ignore that, so your HP can reach 100 EV with HP Up (and the same for other stats).
For now, the best solution I have is to remove the access to every vitamin from the game with AdvanceMap, so you'll get EVs only by battle. I really don't know how to change the max EV you can get with vitamins (default = 100).
 
Last edited:
Static Levels For In-Game Trades [FR]

EDIT: Since this is just a simple byte change, I'm keeping this up, but I suggest you use this instead, which allows for this and more.

Prior to Gen V, Pokemon you receive from in-game trades will be at the same level as the Pokemon you traded. From Black and White onwards, however, they come at a particular level. To get that in FR, simply make the following change:

Code:
0x08053B5E: 3A 20 28 5C C0 46 C0 46 C0 46 C0 46 C0 46

To actually set the level for a particular Pokemon, you'll need a hex editor and a calculator. In an unmodified FR 1.0 ROM, sIngameTrades is stored at 0x0826CF8C. Each in game trade takes 0x3C bytes, and the level is stored at offset 0x3A from the start of the struct. So you'll need to calculate 0x0826CF8C + 0x3C * id + 0x3A, where id is the index of the in-game trade you're modifying (e.g. Reyley's Mimien is 0, and Norma's Tangela is 7). Pull up the resulting address in a hex editor, and modify that byte to set the level for that Pokemon.

Since this uses some of the padding bytes in the existing struct which were zeroed out (because they were originally unused), you'll need to set levels for all of them or they'll come at level 0.

If you have any problems, let me know.
 
Last edited:
[FR] Remove TM/HM PP replenishing
If you want to port the behaviour of TMs/HMs' interaction with PP from Gen V+ to FireRed, where teaching a move retains its current PP, assemble and insert the following routine:

Code:
.thumb

.equ free_space, 0x @ Replace with your desired address
.equ move_data, 0x250C04 @ Replace with the address of your move data
.equ rom, 0x08000000

.org 0x124F48, 0xFF
branch1:
    ldr r1, =(rom + hack1 + 1)
    bx r1
.pool

.org 0x125FC4, 0xFF
branch2:
    ldr r1, =(rom + hack2 + 1)
    bx r1
.pool

.org 0x1260B4, 0xFF
branch3:
    ldr r1, =(rom + hack3 + 1)
    bx r1
.pool

.org free_space, 0xFF
hack1:
    mov r1, r0
    lsl r1, r1, #0x10
    lsr r1, r1, #0x10
    mov r0, r5
    mov r2, r4
    bl set_move_and_pp
    ldr r0, =(rom + 0x124F56 + 1)
    bx r0
.pool

hack2:
    mov r0, r9
    ldrh r1, [r0, #0xE]
    mov r0, r6
    mov r2, r5
    bl set_move_and_pp
    ldr r0, =(rom + 0x125FD0 + 1)
    bx r0
.pool

hack3:
    mov r2, r0
    lsl r2, r2, #0x18
    lsr r2, r2, #0x18
    mov r0, r4
    mov r1, r5
    bl set_move_and_pp
    ldr r0, =(rom + 0x1260C2 + 1)
    bx r0
.pool

set_move_and_pp:
    push {r4,r5,lr}
    sub sp, sp, #4
    mov r5, r0
    mov r4, r2
    mov r0, sp
    strh r1, [r0]
    lsl r4, r4, #0x18
    lsr r4, r4, #0x18
    mov r1, r4
    add r1, #0xD
    mov r0, r5
    mov r2, sp
    bl pokemon_setattr

    add r4, #0x11
    mov r0, r5
    mov r1, r4
    bl pokemon_getattr
    lsl r0, r0, #0x18
    lsr r3, r0, #0x18

    mov r0, sp
    ldrh r0, [r0]
    lsl r2, r0, #1
    add r2, r2, r0
    lsl r2, r2, #2
    ldr r0, =(rom + move_data + 4) @ move_data.pp
    add r2, r2, r0
    ldrb r0, [r2]

    cmp r3, r0
    blt dont_change_pp

    mov r0, r5
    mov r1, r4
    bl pokemon_setattr
    
dont_change_pp:
    add sp, sp, #4
    pop {r4,r5}
    pop {r0}
    bx r0
.pool

pokemon_getattr:
    ldr r3, =(rom + 0x3FBE8 + 1)
    bx r3
.pool

pokemon_setattr:
    ldr r3, =(rom + 0x4037C + 1)
    bx r3
.pool

EDIT 1st June 2020: Added two other hooks which are needed to ensure the same behaviour is applied when the player skips the TM learning animation.
 
Last edited:
Choice Specs [Ruby]

Spoiler:


Choice Scarf [Ruby]

Spoiler:


Light Ball [Ruby]

Spoiler:


I don't have the routine since I took the data from the mrdollsteak database and adapted it to ruby
 
Last edited:
Didn't see this documented anywhere, so I thought I should share it here.

On the credits section in Fire Red:
The maps shown in the credits section are determined by a table at 0x414588. It's a table with 13 pointers, starting at 0x4143e8. Every entry has a length of 0x20.

The bytes that determine the starting point are as follows:
0x3 = The map bank
0x5 = The map number
0x9 = X starting coordinate
0xB = Y starting coordinate

Byte 0x11 to 0x14 of the entry determines the direction in which the camera moves:
00 00 01 00 = Down
00 00 FF FF = Up
01 00 00 00 = Right
FF FF 00 00 = Left
01 00 FF FF = Up-right Diagonally
01 00 01 00 = Down-right Diagonally
FF FF FF FF = Up-left Diagonally
FF FF 01 00 = Down-left Diagonally

That's all.

Credits to Spherical Ice.
 
[FR] Remove TM/HM PP replenishing
If you want to port the behaviour of TMs/HMs' interaction with PP from Gen V+ to FireRed, where teaching a move retains its current PP, assemble and insert the following routine:

Spoiler:
There's an issue with this ASM routine, and it's similar to something I recall happening years ago with a different piece of ASM code.

If you press the B button to cancel out of the TM/HM "learning" animation, the PP amount for the taught move is completely filled up. I'm guessing that's not intended behavior?
 
There's an issue with this ASM routine, and it's similar to something I recall happening years ago with a different piece of ASM code.

If you press the B button to cancel out of the TM/HM "learning" animation, the PP amount for the taught move is completely filled up. I'm guessing that's not intended behavior?

Ah, I missed two other places where I need to hook. This is the updated routine, I have edited my original post with this too:

Code:
.thumb

.equ free_space, 0x @ Replace with your desired address
.equ move_data, 0x250C04 @ Replace with the address of your move data
.equ rom, 0x08000000

.org 0x124F48, 0xFF
branch1:
    ldr r1, =(rom + hack1 + 1)
    bx r1
.pool

.org 0x125FC4, 0xFF
branch2:
    ldr r1, =(rom + hack2 + 1)
    bx r1
.pool

.org 0x1260B4, 0xFF
branch3:
    ldr r1, =(rom + hack3 + 1)
    bx r1
.pool

.org free_space, 0xFF
hack1:
    mov r1, r0
    lsl r1, r1, #0x10
    lsr r1, r1, #0x10
    mov r0, r5
    mov r2, r4
    bl set_move_and_pp
    ldr r0, =(rom + 0x124F56 + 1)
    bx r0
.pool

hack2:
    mov r0, r9
    ldrh r1, [r0, #0xE]
    mov r0, r6
    mov r2, r5
    bl set_move_and_pp
    ldr r0, =(rom + 0x125FD0 + 1)
    bx r0
.pool

hack3:
    mov r2, r0
    lsl r2, r2, #0x18
    lsr r2, r2, #0x18
    mov r0, r4
    mov r1, r5
    bl set_move_and_pp
    ldr r0, =(rom + 0x1260C2 + 1)
    bx r0
.pool

set_move_and_pp:
    push {r4,r5,lr}
    sub sp, sp, #4
    mov r5, r0
    mov r4, r2
    mov r0, sp
    strh r1, [r0]
    lsl r4, r4, #0x18
    lsr r4, r4, #0x18
    mov r1, r4
    add r1, #0xD
    mov r0, r5
    mov r2, sp
    bl pokemon_setattr

    add r4, #0x11
    mov r0, r5
    mov r1, r4
    bl pokemon_getattr
    lsl r0, r0, #0x18
    lsr r3, r0, #0x18

    mov r0, sp
    ldrh r0, [r0]
    lsl r2, r0, #1
    add r2, r2, r0
    lsl r2, r2, #2
    ldr r0, =(rom + move_data + 4) @ move_data.pp
    add r2, r2, r0
    ldrb r0, [r2]

    cmp r3, r0
    blt dont_change_pp

    mov r0, r5
    mov r1, r4
    bl pokemon_setattr
    
dont_change_pp:
    add sp, sp, #4
    pop {r4,r5}
    pop {r0}
    bx r0
.pool

pokemon_getattr:
    ldr r3, =(rom + 0x3FBE8 + 1)
    bx r3
.pool

pokemon_setattr:
    ldr r3, =(rom + 0x4037C + 1)
    bx r3
.pool

Thanks for letting me know, and if there is anything else I've missed please let me know!
 
Last edited:
Ah, I missed two other places where I need to hook. This is the updated routine, I have edited my original post with this too:

Spoiler:

Thanks for letting me know, and if there is anything else I've missed please let me know!
That seemed to do the trick. Thank you so much! This is an incredibly helpful complement to the hacks using infinite TMs.
 
Back
Top