Jambo51
Glory To Arstotzka
- 736
- Posts
- 15
- Years
- Seen Jan 28, 2018
Hello, Jambo51 here again, and I'm here today to ask and hopefully answer the following statement:
How do we add the new moves to our beloved Generation 3 ROMs?
The answers I will provide will be for BPRE 1.0 (aka FR US 1.0), but they will also be applicable to Ruby and Emerald with a bit of thinking and some reading of ini files.
PLEASE NOTE: You can only successfully add attacks which actually do damage at this time. Status inflicting moves (whether purely status or damage and status inflicting) are a no go for now.
What's needed:
A Hex Editor
Pokémon Game Editor by Gamer2020, it perfectly supports the extended data!
Some knowledge of how the INI for PGE works
A Brain
Some PATIENCE
So, there are 2 different ways to add the new moves. The first, in the spoiler below, only supports up to 511 moves (there are a total of 559 in generation 5), but keeps support for the standard style of moveset used in generation 3.
And this is how to add more than 511 moves. Please note, this is substantially more difficult and awkward than the above method, and requires you to redo every single moveset in the game.
So far, I'm betting you're wondering why I decided to post this in R&D when it's clearly a tutorial, right?
Wrong! It's just a necessary evil before we can discuss the REAL thing I want to research!
What I want us to research is the ANIMATIONS and BATTLE SCRIPTS associated with the moves and how we can extend both of the above so that we can create new moves which truly imitate their "real" counterparts.
So, does anyone have any pertinent information (above and beyond what we already know) about either subject mentioned above?
FWIW, this is (AFAIK) our best understanding of Battle Scripts.
EDIT: Since I posted this, I found the table which controls animations and was able to make a new move use an existing animation. Based on what I saw, I suspect that the game uses an "Animation Script" in the same vein as the "Battle Scripts". A specially set aside set of commands specifically used for creating move animations.
How do we add the new moves to our beloved Generation 3 ROMs?
The answers I will provide will be for BPRE 1.0 (aka FR US 1.0), but they will also be applicable to Ruby and Emerald with a bit of thinking and some reading of ini files.
PLEASE NOTE: You can only successfully add attacks which actually do damage at this time. Status inflicting moves (whether purely status or damage and status inflicting) are a no go for now.
What's needed:
A Hex Editor
Pokémon Game Editor by Gamer2020, it perfectly supports the extended data!
Some knowledge of how the INI for PGE works
A Brain
Some PATIENCE
So, there are 2 different ways to add the new moves. The first, in the spoiler below, only supports up to 511 moves (there are a total of 559 in generation 5), but keeps support for the standard style of moveset used in generation 3.
Spoiler:
This is so easy to do, it's not even funny.
All you need to do is repoint the attack table and the attack names array, and add the extra attacks.
How easy is that!?!
In all seriousness, you want to navigate to 0x250C04 and select 4260 bytes of data, then copy it to some aligned free space in your rom, and then repoint all references to that table. This is the silly part, there are ALSO pointers to 0x250C08 in the ROM which must also be repointed, which are used when writing the new moves' PP onto your Pokémon's data. Obviously, when repointing the PP part, you add 4 to the location you replaced 0x250C04 with. Ie, if you replaced 0x2504C04 with 0x960000, then you'd replace 0x250C08 with 0x960004.
Now, navigate back to 0x250C04 and copy (12 * number of new attacks) worth of data. This should ensure that the new attacks you add inherit some sensible data which PGE can work with.
Then navigate to 0x247094, and copy 4615 bytes and paste it into free space, then repoint as necessary.
Go back to 0x247094 and now copy (13 * number of new attacks) worth of attack names. Again, this will ensure that PGE will inherit names it can work with.
Next, navigate to 0x1C68F4, and copy 1420 bytes, and paste them into free space in the ROM, making sure the pointer is THUMB aligned. That is, ends with a 0, 4, 8 or C.
Then, go back to 0x1C68F4 and copy (4 * number of new attacks) bytes of data, and paste it into the area after the already copied data. So for example, if you repointed to 0x9F0000, you would paste this latest data starting at 0x9F058C.
Finally, repoint the pointer to 0x1C68F4 to your new data. This will allow the new moves to have animations. As of now, they will simply inherit the animations of the first however many attacks you added. Ie, Attack 355 will have Attack 0's animation (Attack 0 shares Pound's animation, so don't worry about that little problem), and so on and so forth.
Then, update PGE's ini to add support in the tool for the new moves.
You simply need to change the pointer to the attack data table to the location you repointed your data to, and update the number of attacks parameter so that it accounts for all your nice, shiny new attacks.
That is change:
to:
Then, using PGE, simply modify the attacks after Psycho Blast to comply with the base stats of the moves you want to use.
Now, for the effects, see the post further down this page where I give a worked example of how to do Flare Blitz's effect to work out how to create custom effects. You will need to repoint the table as well, I give the offset of the table in that post.
Please note, the new attacks will have blank names at this stage if you correctly repointed. So make sure you don't put anything else into that area of the ROM until you've finished at least marking out where the names will end.
You can easily update the movesets to include these new moves without any further hassle.
Finally, overwrite the bytes at 0xD75FC with 00 00 00 00 00 00 to disable the only limiter in the ROM. If you do not edit this, rather than saying "Bulbasaur used VenoShock!", it will say "Bulbasaur used a POISON move!"
From here, your new attacks should work (almost - wrong animations) perfectly.
All you need to do is repoint the attack table and the attack names array, and add the extra attacks.
How easy is that!?!
In all seriousness, you want to navigate to 0x250C04 and select 4260 bytes of data, then copy it to some aligned free space in your rom, and then repoint all references to that table. This is the silly part, there are ALSO pointers to 0x250C08 in the ROM which must also be repointed, which are used when writing the new moves' PP onto your Pokémon's data. Obviously, when repointing the PP part, you add 4 to the location you replaced 0x250C04 with. Ie, if you replaced 0x2504C04 with 0x960000, then you'd replace 0x250C08 with 0x960004.
Now, navigate back to 0x250C04 and copy (12 * number of new attacks) worth of data. This should ensure that the new attacks you add inherit some sensible data which PGE can work with.
Then navigate to 0x247094, and copy 4615 bytes and paste it into free space, then repoint as necessary.
Go back to 0x247094 and now copy (13 * number of new attacks) worth of attack names. Again, this will ensure that PGE will inherit names it can work with.
Next, navigate to 0x1C68F4, and copy 1420 bytes, and paste them into free space in the ROM, making sure the pointer is THUMB aligned. That is, ends with a 0, 4, 8 or C.
Then, go back to 0x1C68F4 and copy (4 * number of new attacks) bytes of data, and paste it into the area after the already copied data. So for example, if you repointed to 0x9F0000, you would paste this latest data starting at 0x9F058C.
Finally, repoint the pointer to 0x1C68F4 to your new data. This will allow the new moves to have animations. As of now, they will simply inherit the animations of the first however many attacks you added. Ie, Attack 355 will have Attack 0's animation (Attack 0 shares Pound's animation, so don't worry about that little problem), and so on and so forth.
Then, update PGE's ini to add support in the tool for the new moves.
You simply need to change the pointer to the attack data table to the location you repointed your data to, and update the number of attacks parameter so that it accounts for all your nice, shiny new attacks.
That is change:
Code:
NumberOfAttacks=354
AttackData=&H250C04
AttackNames=&H247094
Code:
NumberOfAttacks=[Number of attacks]
AttackData=&[Location of repointed attack data table]
AttackNames=&[Location of repointed attack name array]
Then, using PGE, simply modify the attacks after Psycho Blast to comply with the base stats of the moves you want to use.
Now, for the effects, see the post further down this page where I give a worked example of how to do Flare Blitz's effect to work out how to create custom effects. You will need to repoint the table as well, I give the offset of the table in that post.
Please note, the new attacks will have blank names at this stage if you correctly repointed. So make sure you don't put anything else into that area of the ROM until you've finished at least marking out where the names will end.
You can easily update the movesets to include these new moves without any further hassle.
Finally, overwrite the bytes at 0xD75FC with 00 00 00 00 00 00 to disable the only limiter in the ROM. If you do not edit this, rather than saying "Bulbasaur used VenoShock!", it will say "Bulbasaur used a POISON move!"
From here, your new attacks should work (almost - wrong animations) perfectly.
And this is how to add more than 511 moves. Please note, this is substantially more difficult and awkward than the above method, and requires you to redo every single moveset in the game.
Spoiler:
Firstly, do exactly what is above. Everything which follows is based on the simple foundation of what is above. *Waits*
Done that? Good.
Now we must insert some ASM routines to rewrite how the movesets are read.
So, insert the following routine:
Change 0x3EB20 to 18 49 08 47. Then navigate to 0x3EB84 and change it to XX XX XX 08, where the XX XX XX stands for the pointer to your new routine plus 1.
The table I reference in here is the moveset table. So change your 0x8FFFFFF to point to it. This applies to all 3 routines here, so make sure you change them all.
This only fixes the PLAYER's learnsets, so you now need to insert this next routine:
Change 0x3EA10 to 00 49 08 47 XX XX XX 08 where the XX XX XX stands for the pointer to your new routine plus 1.
This will fix the moveset loading to it can now support up to 0xFFFF moves (instead of 0x1FF).
Finally, in order for the Move Relearner to work with the new system, insert this routine in your ROM:
Change 0x43CE8 to 00 4A 10 47 XX XX XX 08 where the XX XX XX stands for the pointer to your new routine plus 1.
In PGE, you now need to open up the settings drop-down menu, and select "Use Jambo's Moveset hack" to support the new moveset style.
It is good practise (and will help avoid crashes) to repoint all your movesets to free space and start fresh with the new movesets.
Hey, I never said it would be easy!
Bear in mind, the same rules apply here as before. No status inflicting moves will work, so don't try them.
And you are done!
NOTE: For any intrepid people who wish to use the new moveset style without using PGE (I wouldn't advise it!), this is a short explanation of how they now work:
The new movesets are collections of 3 bytes each which are set up thus:
[MOVE - Half-Word - Reverse Hex] [Level - Byte]
So if I wanted my Pokémon's moveset to contain Pound at level 52, it would be:
01 00 34
To end the moveset, you put:
00 00 FF
Done that? Good.
Now we must insert some ASM routines to rewrite how the movesets are read.
So, insert the following routine:
Code:
.text
.align 2
.thumb
.thumb_func
.global newmovesetstyle
main:
mov r1, r9
lsl r1, r1, #0x2
ldr r0, table
add r0, r0, r1
ldr r0, [r0, #0x0]
ldr r6, there
add r6, #0x6
ldrb r7, [r6, #0x0]
loop: lsl r1, r7, #0x1
add r1, r1, r7
add r3, r0, r1
ldrb r1, [r3, #0x2]
mov r4, r10
cmp r4, r1
beq learn
cmp r1, #0xFF
beq exit
add r7, #0x1
b loop
learn: ldr r2, there
add r7, #0x1
strb r7, [r6, #0x0]
ldrb r1, [r3, #0x1]
lsl r1, r1, #0x8
ldrb r0, [r3, #0x0]
orr r0, r1
strh r0, [r2, #0x0]
ldr r1, return
bx r1
exit: ldr r0, return2
bx r0
.align
return: .word 0x0803EB65
return2: .word 0x0803EB73
table: .word 0x08FFFFFF /*Replace with your table's location/*
there: .word 0x02024022
Change 0x3EB20 to 18 49 08 47. Then navigate to 0x3EB84 and change it to XX XX XX 08, where the XX XX XX stands for the pointer to your new routine plus 1.
The table I reference in here is the moveset table. So change your 0x8FFFFFF to point to it. This applies to all 3 routines here, so make sure you change them all.
This only fixes the PLAYER's learnsets, so you now need to insert this next routine:
Code:
.text
.align 2
.thumb
.thumb_func
.global newmovesetstyle2
main:
ldrb r1, [r0, #0x2]
mov r2, #0xFF
cmp r1, r2
beq exit2
mov r9, r2
mov r3, #0x0
loop: lsl r0, r3, #0x1
add r0, r0, r3
ldr r1, movesettable
add r1, r1, r6
ldr r1, [r1, #0x0]
add r7, r0, r1
ldrb r0, [r7, #0x2]
mov r4, r10
cmp r0, r4
bgt exit2
ldrb r1, [r7, #0x1]
ldrb r0, [r7, #0x0]
lsl r1, r1, #0x8
orr r1, r0
mov r0, r8
str r3, [sp, #0x0]
bl branchone
mov r5, r9
ldr r3, [sp, #0x0]
cmp r0, r9
bne exit
mov r0, r8
add r1, r4, #0x0
bl branchtwo
ldr r3, [sp, #0x0]
exit: add r3, #0x1
lsl r1, r3, #0x1
add r1, r1, r3
add r0, r7, r1
ldrb r0, [r0, #0x2]
cmp r0, r5
bne loop
exit2: add sp, #0x4
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7}
pop {r0}
bx r0
branchone: push {r4-r7,lr}
add sp, #-0x4
ldr r7, gothere
bx r7
branchtwo: push {r4-r7}
ldr r7, gothere2
bx r7
.align
gothere: .word 0x0803E8B5
gothere2: .word 0x0803EC43
movesettable: .word 0x08FFFFFF
Change 0x3EA10 to 00 49 08 47 XX XX XX 08 where the XX XX XX stands for the pointer to your new routine plus 1.
This will fix the moveset loading to it can now support up to 0xFFFF moves (instead of 0x1FF).
Finally, in order for the Move Relearner to work with the new system, insert this routine in your ROM:
Code:
.text
.align 2
.thumb
.thumb_func
.global newmovesetstyle
main:
lsl r2, r5, #0x1
add r2, r2, r5
ldr r1, [sp, #0x10]
add r0, r2, r1
ldrb r0, [r0, #0x2]
ldr r1, [sp, #0xC]
add r7, r2, #0x0
add r5, #0x1
mov r12, r5
cmp r0, r1
bgt later
mov r4, #0x0
cmp r1, r0
beq later2
mov r4, #0x1
neg r4, r4
ldr r0, [sp, #0x14]
ldr r1, table
add r6, r0, r1
mov r3, sp
sub r3, #0x2
add r5, r7, #0x0
there: add r3, #0x2
add r4, #0x1
cmp r4, #0x3
bgt later2
ldr r0, [r6, #0x0]
add r0, r5, r0
ldrb r2, [r0, #0x0]
ldrb r0, [r0, #0x1]
lsl r0, r0, #0x8
orr r0, r2
ldrh r2, [r3, #0x0]
cmp r0, r2
bne there
later2: cmp r4, #0x4
bne later
mov r4, #0x0
cmp r4, r10
bge later3
mov r1, r9
ldr r0, [r1, #0x0]
add r0, r7, r0
ldrb r2, [r0, #0x0]
ldrb r1, [r0, #0x1]
lsl r1, r1, #0x8
orr r1, r2
ldr r0, [sp, #0x8]
ldrh r2, [r0, #0x0]
cmp r1, r2
beq later3
ldr r1, [sp, #0x14]
ldr r2, table
add r6, r1, r2
ldr r3, [sp, #0x8]
add r5, r7, #0x0
there2: add r3, #0x2
add r4, #0x1
cmp r4, r10
bge later3
ldr r0, [r6, #0x0]
add r0, r5, r0
ldrb r2, [r0, #0x0]
ldrb r0, [r0, #0x1]
lsl r0, r0, #0x8
orr r0, r2
ldrh r2, [r3, #0x0]
cmp r0, r2
bne there2
later3: cmp r4, r10
bne later
mov r0, r10
add r0, #0x1
mov r10, r0
lsl r2, r4, #0x1
ldr r1, [sp, #0x8]
add r2, r2, r1
mov r4, r9
ldr r0, [r4, #0x0]
add r0, r7, r0
ldrb r1, [r0, #0x0]
ldrb r0, [r0, #0x1]
lsl r0, r0, #0x8
orr r0, r1
strh r0, [r2, #0x0]
later: mov r5, r12
mov r1, r9
ldr r0, [r1, #0x0]
lsl r1, r5, #0x1
add r1, r1, r5
add r1, r1, r0
ldrb r0, [r1, #0x2]
cmp r0, #0xFF
bne main
mov r0, r10
add sp, #0x18
pop {r3-r5}
mov r8, r3
mov r9, r4
mov r10, r5
pop {r4-r7}
pop {r1}
bx r1
.align
table: .word 0x08FFFFFF
Change 0x43CE8 to 00 4A 10 47 XX XX XX 08 where the XX XX XX stands for the pointer to your new routine plus 1.
In PGE, you now need to open up the settings drop-down menu, and select "Use Jambo's Moveset hack" to support the new moveset style.
It is good practise (and will help avoid crashes) to repoint all your movesets to free space and start fresh with the new movesets.
Hey, I never said it would be easy!
Bear in mind, the same rules apply here as before. No status inflicting moves will work, so don't try them.
And you are done!
NOTE: For any intrepid people who wish to use the new moveset style without using PGE (I wouldn't advise it!), this is a short explanation of how they now work:
The new movesets are collections of 3 bytes each which are set up thus:
[MOVE - Half-Word - Reverse Hex] [Level - Byte]
So if I wanted my Pokémon's moveset to contain Pound at level 52, it would be:
01 00 34
To end the moveset, you put:
00 00 FF
So far, I'm betting you're wondering why I decided to post this in R&D when it's clearly a tutorial, right?
Wrong! It's just a necessary evil before we can discuss the REAL thing I want to research!
What I want us to research is the ANIMATIONS and BATTLE SCRIPTS associated with the moves and how we can extend both of the above so that we can create new moves which truly imitate their "real" counterparts.
So, does anyone have any pertinent information (above and beyond what we already know) about either subject mentioned above?
FWIW, this is (AFAIK) our best understanding of Battle Scripts.
EDIT: Since I posted this, I found the table which controls animations and was able to make a new move use an existing animation. Based on what I saw, I suspect that the game uses an "Animation Script" in the same vein as the "Battle Scripts". A specially set aside set of commands specifically used for creating move animations.
Last edited: