Adding more attacks to Fire Red and Emerald!
Hello. Today I will be writing about how to add more attacks to Fire Red and Emerald. Please note that this will only apply to the English versions of these games. If you are using a different version you will need to find the appropriate offsets. I will also be assuming that you already know how to repoint data and insert ASM routines. If for some reason you don’t wish to add the attacks yourself please use Pokemon Game Editor. This is meant for more advanced users.
Some of you may have heard of a ROM hacker named Jambo51. He is a ROM hacker that created the first ROM base with added Pokemon. While working on it he realized that the level up format would have to be changed in order to support more than 511 moves. This is all based on the work that he started; I’ve simply added on to it.
To begin you’ll want to repoint the attack names. The names are 13 bytes per name and the original length of all the names is 4615 bytes. Repoint the current data to free space. Pad the data with “ACACACACACACACFF0000000000″ for every new name you want to add. Offsets for the original data are below.
[spoiler title=”Fire Red”]247094
[/spoiler]
[spoiler title=”Emerald”]31977C
[/spoiler]
Next up will be the attack data. The attack data is 12 bytes per attack and the original length of all the data is 4260 bytes. Repoint the current data to free space. Pad the data with “000000000000000000000000” for every new attack that you want to add. The offsets for the data are below.
[spoiler title=”Fire Red”]250C04
[/spoiler]
[spoiler title=”Emerald”]31C898
[/spoiler]
Also keep in mind that there are pointers for the PP data. The pointers will have these same offsets plus 4.
[spoiler title=”Fire Red”]250C08
[/spoiler]
[spoiler title=”Emerald”]31C89C
[/spoiler]
Next you will be repointing the move description table. The data is a pointer, or 4 bytes per attack and the original length of the table is 1420 bytes. Repoint the current table to free space. Pad the data with a pointer for any existing description for every new attack that you want to add. The offsets for the table are below.
[spoiler title=”Fire Red”]4886E8
[/spoiler]
[spoiler title=”Emerald”]61C524
[/spoiler]
Next you have to repoint the attack animation table. The data is a pointer, or 4 bytes per attack and the original length of the table is 1420 bytes. Repoint the current table to free space. Pad the data with a pointer for any existing animation for every new attack that you want to add. The offsets for the table are below.
[spoiler title=”Fire Red”]1C68F4
[/spoiler]
[spoiler title=”Emerald”]2C8D6C
[/spoiler]
As far as repointing goes, you are done at this point when dealing with Fire Red. When dealing with Emerald, however, you have contest attack data to repoint as well. The data is 8 bytes per attack and the original length of the data is 2840 bytes. Repoint the current data to free space. Pad the data with “0000000000000000” for every new attack that you want to add. The offset for the table is below.
[spoiler title=”Emerald Contest Attack Data”]58C2B4
[/spoiler]
At this point you are done with the repointing. Now you just need to do a few things to make the attacks work properly. There is a limiter that needs to be changed in order for the attack names to be used. Write “00000000000013E0″ at the offset for your version.
[spoiler title=”Fire Red”]D75FC
[/spoiler]
[spoiler title=”Emerald”]14E504
[/spoiler]
Yet again we are done when it comes to Fire Red but we have to do a little more when it comes to Emerald due to the contest data. Write “0000000000000000” at the following offset. This seems to do the same but for contests.
[spoiler title=”Emerald Contest Attack Name Limiter”]D8F0C
[/spoiler]
At the next offset, write “00000000000000E0″ to change a limiter that seems to be related to the attack animations for contests.
[spoiler title=”Emerald Contest Attack Animation Limiter”]DE83A
[/spoiler]
At this point you’ve done most of what you need to do. If you don’t need more than 511 attacks, you are done. If you do need more than 511, you will need to insert the following ASM routines. The instructions are with the respective routines.
[spoiler title=”Fire Red”]
.text .align 2 .thumb .thumb_func .global newmovesetstyle1 /* By: Jambo51 */ /* 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. */ 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 there: .word 0x02024022 table: .word 0x0825D7B4
.text .align 2 .thumb .thumb_func .global newmovesetstyle2 /* By: Jambo51 */ /* Improved by: DoesntKnowHowToPlay */ /* 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. */ main: ldrb r1, [r0, #0x2] mov r2, #0xFF cmp r1, r2 beq exit2 lsl r2, #0x8 add r2, #0xFF 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] mov r4, r1 bl branchone mov r5, #0xFF 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 mov r1, #0x3 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,lr} ldr r7, gothere2 bx r7 .align gothere: .word 0x0803E8B5 gothere2: .word 0x0803EC43 movesettable: .word 0x0825D7B4
.text .align 2 .thumb .thumb_func .global newmovesetstyle3 /* By: Gamer2020 */ /* Change 0x08043CD0 to 00490847 XXXXXXXX where the XX XX XX stands for the pointer to your new routine plus 1. */ main: MOV R5, #0x0 LDR R6, .learned_moves_ptr LSL R1, R7, #0x2 ADD R2, R1, R6 LDR R3, [R2] ldrb r0, [r3, #0x2] STR R1, [SP,#0x14] CMP R0, #0xFF BEQ loc_8043DB4 MOV R9, R2 STR R3, [SP,#0x10] loc_8043CE8: mov r2,#0x03 mul r2, r2, r5 /*mult 3*/ ldr r1,[sp, #0x10] /* Use these two lines to get current attack address.*/ add r0,r2,r1 mov r7,r2 ldrb r1, [r0, #0x0] ldrb r3, [r0, #0x1] lsl r3, r3, #0x8 orr r3, r1 /*Puts attack in r3.*/ ldrb r0, [r0, #0x2] /*Puts level in r0.*/ ldr r1,[sp,#0x0C] /* Loads current level */ add r5, #0x1 /* Loop counter? */ mov r12,r5 cmp r0,r1 /* compares levels */ bgt loc_8043D9E mov r4, #0x0 mov r0,r13 ldrh r1,[r0] mov r0,r3 /* Puts attack in r0 */ cmp r1,r0 beq loc_8043D38 ldr r0,[sp,#0x14] ldr r1, .learned_moves_ptr add r6,r0,r1 mov r3,r13 mov r5,r7 loc_8043D20: add r3, #0x2 add r4, #0x1 cmp r4, #0x3 bgt loc_8043D38 ldr r0,[r6] add r0,r5,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ ldrh r2,[r3] cmp r2,r0 bne loc_8043D20 loc_8043D38: cmp r4,#0x4 bne loc_8043D9E mov r4,#0x0 cmp r4,r10 bge loc_8043D7C mov r1,r9 ldr r0,[r1] add r0,r7,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ ldr r2,[sp,#0x8] ldrh r2,[r2] cmp r2,r0 beq loc_8043D7C ldr r1,[sp, #0x14] ldr r2, .learned_moves_ptr add r6,r1,r2 ldr r3,[sp, #0x8] mov r5,r7 loc_8043D64: add r3, #0x2 add r4,#0x1 cmp r4,r10 bge loc_8043D7C ldr r0,[r6] add r0,r5,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ ldrh r2,[r3] cmp r2,r0 bne loc_8043D64 loc_8043D7C: cmp r4,r10 bne loc_8043D9E mov r0,r10 add r0,#0x1 lsl r0,r0,#0x18 lsr r0,r0,#0x18 mov r10,r0 lsl r2,r4, #0x1 ldr r1,[sp,#0x8] add r2,r2,r1 mov r4,r9 ldr r0,[r4] add r0,r7,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ strh r0,[r2] loc_8043D9E: mov r5,r12 cmp r5, #0x13 bgt loc_8043DB4 mov r1,r9 ldr r0,[r1] mov r1,#0x03 mul r1, r1, r5 /*mult 3*/ add r1,r1,r0 ldrh r0,[r1] /* Load bytes for term check. */ ldrb r0, [r1, #0x2] cmp r0, #0xFF /*Term Check*/ bne loc_8043CE8 loc_8043DB4: 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 2 .learned_moves_ptr: .word 0x0825D7B4
.text .align 2 .thumb .thumb_func .global newmovesetstyle4 /* By: Gamer2020 */ /*at 8043E2C 004B1847xxxxxxxx */ /*08043E2C*/ main: PUSH {R4-R7,LR} MOV R7, R10 MOV R6, R9 MOV R5, R8 PUSH {R5-R7} sub sp, sp, #0x3C add r6, r0, #0x0 mov r0, #0x0 mov r10, r0 add r0, r6, #0x0 mov r1, #0x41 mov r2, #0x0 ldr r3, .READ_Poke_DATA /*Get Species*/ bl bx_r3 lsl r0, r0, #0x10 lsr r4, r0, #0x10 add r0, r6, #0x0 mov r1, #0x38 mov r2, #0x0 ldr r3, .READ_Poke_DATA /*Get Level*/ bl bx_r3 lsl r0, r0, #0x18 /*Drops leading 000000??*/ lsr r0, r0, #0x18 str r0, [sp, #0x30] mov r0, #0xce /*Check if slot 412*/ lsl r0, r0, #0x01 cmp r4, r0 bne loc_8043E68 mov r0, #0x0 b exit loc_8043E68: mov r5, #0x0 lsl r4, r4, #0x02 /*Species x 4*/ str r4, [sp, #0x38] /*Stores value for later */ mov r4, sp loc_8043E70: mov r1, r5 add r1, #0xd mov r0, r6 mov r2, #0x0 ldr r3, .READ_Poke_DATA /*Get attacks*/ bl bx_r3 strh r0, [r4] add r4, #0x2 add r5, #0x1 /*Loops through 4 attacks on Poke*/ cmp r5, #0x3 ble loc_8043E70 mov r5, #0x0 ldr r3, .learned_moves_ptr ldr r2, [sp, #0x38] add r1, r2, r3 ldr r0,[r1] ldrb r0, [r0, #0x2] CMP R0, #0xFF BEQ loc_8043F70 mov r9,r1 mov r4,r13 add r4,#0x8 str r4,[sp,#0x34] loc_8043EA0: mov r1,r9 ldr r0,[r1] mov r2,#0x03 mul r2, r2, r5 /*mult 3*/ add r0,r2,r0 ldrb r0, [r0, #0x2] /*Puts level in r0.*/ ldr r4,[sp, #0x30] /*Loads mon level*/ mov r1,r4 mov r7,r2 add r5, #0x1 /*Incremeants place*/ mov r12,r5 cmp r0,r1 /*Level Check*/ bgt loc_8043F5A mov r4, #0x0 mov r0,r9 ldr r0,[r0] ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ mov r1,r13 ldrh r1,[r1] cmp r1,r0 beq loc_8043EF2 ldr r0,[sp, #0x38] ldr r1, .learned_moves_ptr add r6,r0,r1 mov r3,r13 mov r5,r7 loc_8043EDA: add r3, #0x2 add r4, #0x1 cmp r4, #0x3 bgt loc_8043EF2 ldr r0,[r6] add r0,r5,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Loads bytes Gets attack put into r0*/ ldrh r2,[r3] cmp r2,r0 bne loc_8043EDA loc_8043EF2: cmp r4, #0x4 bne loc_8043F5A mov r4, #0x0 cmp r4,r10 bge loc_8043F38 mov r1,r9 ldr r0,[r1] add r0,r7,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r1, r0 /*Loads bytes Gets attack put into r1*/ ldr r0,[sp,#0x34] ldrh r2,[r0] mov r0,r1 /*Gets attack put into r0*/ add r1,sp,#0x8 cmp r2,r0 beq loc_8043F38 ldr r2,[sp,#0x38] ldr r0, .learned_moves_ptr add r6,r2,r0 mov r3,r1 mov r5,r7 loc_8043F20: add r3, #0x2 add r4, #0x1 cmp r4,r10 bge loc_8043F38 ldr r0,[r6] add r0,r5,r0 /*Attack*/ ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Loads bytes Gets attack put into r0*/ ldrh r2,[r3] cmp r2,r0 bne loc_8043F20 loc_8043F38: cmp r4,r10 bne loc_8043F5A mov r0,r10 add r0, #0x1 lsl r0,r0, #0x18 lsr r0,r0, #0x18 mov r10,r0 lsl r2,r4, #0x1 /*mult 2?*/ ldr r4,[sp,#0x34] add r2,r4,r2 mov r1,r9 ldr r0,[r1] add r0,r7,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Loads bytes Gets attack put into r0*/ strh r0,[r2] loc_8043F5A: mov r5,r12 cmp r5, #0x13 /*Some kind of limit to attacks?*/ bgt loc_8043F70 mov r2,r9 ldr r0,[r2] mov r1,#0x03 mul r1, r1, r5 add r1,r1,r0 ldrb r0, [r1, #0x2] cmp r0, #0xFF /*Term Check*/ bne loc_8043EA0 loc_8043F70: mov r0,r10 /*Return Value*/ exit: add sp, #0x3C pop {r3-r5} mov r8,r3 mov r9,r4 mov r10,r5 pop {r4-r7} pop {r1} bx r1 bx_r3: bx r3 .align 2 .READ_Poke_DATA: .word 0x0803FBE9 .learned_moves_ptr: .word 0x0825D7B4
.text .align 2 .thumb .thumb_func .global newmovesetstyle5 /* By: Gamer2020 */ /*at 0803EAFC write 00490847xxxxxxxx */ /* At 0803EAD4 write 8078C046C046C046C046*/ /* At 0803EB04 write FF29*/ /* at 0803EAE2 write 5446C046*/ /* at 0803EB18 write 081CC046*/ /*0803EAFC*/ main: mov r1,#0x03 mul r0, r0, r1 /*mult 3*/ ldr r1,[r3] /* Loads offset for mon*/ add r0,r0,r1 ldrb r1, [r0, #0x2] ldr r0, .return bx r0 .align 2 .return: .word 0x0803EB05
.text .align 2 .thumb .thumb_func .global newmovesetstyle6 /* By: Gamer2020 */ /* Write this routine at 08043DD4. If you edit the routine and make it longer you will have to branch to it.*/ /*08043DD4*/ main: push {r4-r7,r14} mov r6,r1 lsl r0,r0,#0x10 /* r0 holds species.*/ mov r5, #0x0 mov r4, #0x0 ldr r1,=.learned_moves_ptr lsr r0,r0, #0x0E add r0,r0,r1 ldr r2,[r0] ldrb r0, [r2, #0x2] cmp r0, #0xFF /*Term Check*/ beq loc_8043E18 mov r3,r2 loc_8043DF6: mov r1,r5 add r0,r1, #0x1 lsl r0,r0, #0x18 lsr r5,r0, #0x18 lsl r1,r1, #0x1 add r1,r1,r6 ldrb r2, [r3, #0x0] ldrb r0, [r3, #0x1] lsl r0, r0, #0x8 orr r0, r2 /*Loads bytes Gets attack put into r0*/ strh r0,[r1] add r3, #0x3 /* Increment. */ add r4, #0x1 cmp r4, #0x13 bgt loc_8043E18 ldrb r0, [r3, #0x2] cmp r0, #0xFF /*Term Check*/ bne loc_8043DF6 loc_8043E18: mov r0,r5 pop {r4-r7} pop {r1} bx r1 .align 2 .learned_moves_ptr: .word 0x0825D7B4
[/spoiler]
[spoiler title=”Emerald”]
.text .align 2 .thumb .thumb_func .global newmovesetstyle1 /* By: Jambo51 */ /* Ported to Emerald by: Gamer2020*/ /* Change 0x693B0 to 18 49 08 47. Then navigate to 0x69414 and change it to XX XX XX 08, where the XX XX XX stands for the pointer to your new routine plus 1. */ 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 0x080693F5 return2: .word 0x08069403 there: .word 0x020244E2 table: .word 0x0832937C
.text .align 2 .thumb .thumb_func .global newmovesetstyle2 /* By: Jambo51 */ /* Improved by: DoesntKnowHowToPlay */ /* Ported to Emerald by: Gamer2020*/ /* Change 0x692A0 to 00 49 08 47 XX XX XX 08 where the XX XX XX stands for the pointer to your new routine plus 1. */ main: ldrb r1, [r0, #0x2] mov r2, #0xFF cmp r1, r2 beq exit2 lsl r2, #0x8 add r2, #0xFF 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] mov r4, r1 bl branchone mov r5, #0xFF 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 mov r1, #0x3 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,lr} ldr r7, gothere2 bx r7 .align gothere: .word 0x08069145 gothere2: .word 0x080694D3 movesettable: .word 0x0832937C
.text .align 2 .thumb .thumb_func .global newmovesetstyle3 /* By: Gamer2020 */ /* Change 0x0806E100 to 00490847 XXXXXXXX where the XX XX XX stands for the pointer to your new routine plus 1. */ main: MOV R5, #0x0 LDR R6, .learned_moves_ptr LSL R1, R7, #0x2 ADD R2, R1, R6 LDR R3, [R2] ldrb r0, [r3, #0x2] STR R1, [SP,#0x14] CMP R0, #0xFF BEQ loc_8043DB4 MOV R9, R2 STR R3, [SP,#0x10] loc_8043CE8: mov r2,#0x03 mul r2, r2, r5 /*mult 3*/ ldr r1,[sp, #0x10] /* Use these two lines to get current attack address.*/ add r0,r2,r1 mov r7,r2 ldrb r1, [r0, #0x0] ldrb r3, [r0, #0x1] lsl r3, r3, #0x8 orr r3, r1 /*Puts attack in r3.*/ ldrb r0, [r0, #0x2] /*Puts level in r0.*/ ldr r1,[sp,#0x0C] /* Loads current level */ add r5, #0x1 /* Loop counter? */ mov r12,r5 cmp r0,r1 /* compares levels */ bgt loc_8043D9E mov r4, #0x0 mov r0,r13 ldrh r1,[r0] mov r0,r3 /* Puts attack in r0 */ cmp r1,r0 beq loc_8043D38 ldr r0,[sp,#0x14] ldr r1, .learned_moves_ptr add r6,r0,r1 mov r3,r13 mov r5,r7 loc_8043D20: add r3, #0x2 add r4, #0x1 cmp r4, #0x3 bgt loc_8043D38 ldr r0,[r6] add r0,r5,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ ldrh r2,[r3] cmp r2,r0 bne loc_8043D20 loc_8043D38: cmp r4,#0x4 bne loc_8043D9E mov r4,#0x0 cmp r4,r10 bge loc_8043D7C mov r1,r9 ldr r0,[r1] add r0,r7,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ ldr r2,[sp,#0x8] ldrh r2,[r2] cmp r2,r0 beq loc_8043D7C ldr r1,[sp, #0x14] ldr r2, .learned_moves_ptr add r6,r1,r2 ldr r3,[sp, #0x8] mov r5,r7 loc_8043D64: add r3, #0x2 add r4,#0x1 cmp r4,r10 bge loc_8043D7C ldr r0,[r6] add r0,r5,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ ldrh r2,[r3] cmp r2,r0 bne loc_8043D64 loc_8043D7C: cmp r4,r10 bne loc_8043D9E mov r0,r10 add r0,#0x1 lsl r0,r0,#0x18 lsr r0,r0,#0x18 mov r10,r0 lsl r2,r4, #0x1 ldr r1,[sp,#0x8] add r2,r2,r1 mov r4,r9 ldr r0,[r4] add r0,r7,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ strh r0,[r2] loc_8043D9E: mov r5,r12 cmp r5, #0x13 bgt loc_8043DB4 mov r1,r9 ldr r0,[r1] mov r1,#0x03 mul r1, r1, r5 /*mult 3*/ add r1,r1,r0 ldrh r0,[r1] /* Load bytes for term check. */ ldrb r0, [r1, #0x2] cmp r0, #0xFF /*Term Check*/ bne loc_8043CE8 loc_8043DB4: 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 2 .learned_moves_ptr: .word 0x0832937C
.text .align 2 .thumb .thumb_func .global newmovesetstyle4 /* By: Gamer2020 */ /*at 0806E25C 004B1847xxxxxxxx */ main: PUSH {R4-R7,LR} MOV R7, R10 MOV R6, R9 MOV R5, R8 PUSH {R5-R7} sub sp, sp, #0x3C add r6, r0, #0x0 mov r0, #0x0 mov r10, r0 add r0, r6, #0x0 mov r1, #0x41 mov r2, #0x0 ldr r3, .READ_Poke_DATA /*Get Species*/ bl bx_r3 lsl r0, r0, #0x10 lsr r4, r0, #0x10 add r0, r6, #0x0 mov r1, #0x38 mov r2, #0x0 ldr r3, .READ_Poke_DATA /*Get Level*/ bl bx_r3 lsl r0, r0, #0x18 /*Drops leading 000000??*/ lsr r0, r0, #0x18 str r0, [sp, #0x30] mov r0, #0xce /*Check if slot 412*/ lsl r0, r0, #0x01 cmp r4, r0 bne loc_8043E68 mov r0, #0x0 b exit loc_8043E68: mov r5, #0x0 lsl r4, r4, #0x02 /*Species x 4*/ str r4, [sp, #0x38] /*Stores value for later */ mov r4, sp loc_8043E70: mov r1, r5 add r1, #0xd mov r0, r6 mov r2, #0x0 ldr r3, .READ_Poke_DATA /*Get attacks*/ bl bx_r3 strh r0, [r4] add r4, #0x2 add r5, #0x1 /*Loops through 4 attacks on Poke*/ cmp r5, #0x3 ble loc_8043E70 mov r5, #0x0 ldr r3, .learned_moves_ptr ldr r2, [sp, #0x38] add r1, r2, r3 ldr r0,[r1] ldrb r0, [r0, #0x2] CMP R0, #0xFF BEQ loc_8043F70 mov r9,r1 mov r4,r13 add r4,#0x8 str r4,[sp,#0x34] loc_8043EA0: mov r1,r9 ldr r0,[r1] mov r2,#0x03 mul r2, r2, r5 /*mult 3*/ add r0,r2,r0 ldrb r0, [r0, #0x2] /*Puts level in r0.*/ ldr r4,[sp, #0x30] /*Loads mon level*/ mov r1,r4 mov r7,r2 add r5, #0x1 /*Incremeants place*/ mov r12,r5 cmp r0,r1 /*Level Check*/ bgt loc_8043F5A mov r4, #0x0 mov r0,r9 ldr r0,[r0] ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Puts attack in r0.*/ mov r1,r13 ldrh r1,[r1] cmp r1,r0 beq loc_8043EF2 ldr r0,[sp, #0x38] ldr r1, .learned_moves_ptr add r6,r0,r1 mov r3,r13 mov r5,r7 loc_8043EDA: add r3, #0x2 add r4, #0x1 cmp r4, #0x3 bgt loc_8043EF2 ldr r0,[r6] add r0,r5,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Loads bytes Gets attack put into r0*/ ldrh r2,[r3] cmp r2,r0 bne loc_8043EDA loc_8043EF2: cmp r4, #0x4 bne loc_8043F5A mov r4, #0x0 cmp r4,r10 bge loc_8043F38 mov r1,r9 ldr r0,[r1] add r0,r7,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r1, r0 /*Loads bytes Gets attack put into r1*/ ldr r0,[sp,#0x34] ldrh r2,[r0] mov r0,r1 /*Gets attack put into r0*/ add r1,sp,#0x8 cmp r2,r0 beq loc_8043F38 ldr r2,[sp,#0x38] ldr r0, .learned_moves_ptr add r6,r2,r0 mov r3,r1 mov r5,r7 loc_8043F20: add r3, #0x2 add r4, #0x1 cmp r4,r10 bge loc_8043F38 ldr r0,[r6] add r0,r5,r0 /*Attack*/ ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Loads bytes Gets attack put into r0*/ ldrh r2,[r3] cmp r2,r0 bne loc_8043F20 loc_8043F38: cmp r4,r10 bne loc_8043F5A mov r0,r10 add r0, #0x1 lsl r0,r0, #0x18 lsr r0,r0, #0x18 mov r10,r0 lsl r2,r4, #0x1 /*mult 2?*/ ldr r4,[sp,#0x34] add r2,r4,r2 mov r1,r9 ldr r0,[r1] add r0,r7,r0 ldrb r1, [r0, #0x0] ldrb r0, [r0, #0x1] lsl r0, r0, #0x8 orr r0, r1 /*Loads bytes Gets attack put into r0*/ strh r0,[r2] loc_8043F5A: mov r5,r12 cmp r5, #0x13 /*Some kind of limit to attacks?*/ bgt loc_8043F70 mov r2,r9 ldr r0,[r2] mov r1,#0x03 mul r1, r1, r5 add r1,r1,r0 ldrb r0, [r1, #0x2] cmp r0, #0xFF /*Term Check*/ bne loc_8043EA0 loc_8043F70: mov r0,r10 /*Return Value*/ exit: add sp, #0x3C pop {r3-r5} mov r8,r3 mov r9,r4 mov r10,r5 pop {r4-r7} pop {r1} bx r1 bx_r3: bx r3 .align 2 .READ_Poke_DATA: .word 0x0806A519 .learned_moves_ptr: .word 0x0832937C
.text .align 2 .thumb .thumb_func .global newmovesetstyle5 /* By: Gamer2020 */ /*at 0806938C write 00490847xxxxxxxx */ /* At 08069364 write 8078C046C046C046C046*/ /* At 08069394 write FF29*/ /* at 08069372 write 5446C046*/ /* at 080693A8 write 081CC046*/ main: mov r1,#0x03 mul r0, r0, r1 /*mult 3*/ ldr r1,[r3] /* Loads offset for mon*/ add r0,r0,r1 ldrb r1, [r0, #0x2] ldr r0, .return bx r0 .align 2 .return: .word 0x08069395
.text .align 2 .thumb .thumb_func .global newmovesetstyle6 /* By: Gamer2020 */ /* Write this routine at 0806E204. If you edit the routine and make it longer you may have to branch to it.*/ main: push {r4-r7,r14} mov r6,r1 lsl r0,r0,#0x10 /* r0 holds species.*/ mov r5, #0x0 mov r4, #0x0 ldr r1,=.learned_moves_ptr lsr r0,r0, #0x0E add r0,r0,r1 ldr r2,[r0] ldrb r0, [r2, #0x2] cmp r0, #0xFF /*Term Check*/ beq loc_8043E18 mov r3,r2 loc_8043DF6: mov r1,r5 add r0,r1, #0x1 lsl r0,r0, #0x18 lsr r5,r0, #0x18 lsl r1,r1, #0x1 add r1,r1,r6 ldrb r2, [r3, #0x0] ldrb r0, [r3, #0x1] lsl r0, r0, #0x8 orr r0, r2 /*Loads bytes Gets attack put into r0*/ strh r0,[r1] add r3, #0x3 /* Increment. */ add r4, #0x1 cmp r4, #0x13 bgt loc_8043E18 ldrb r0, [r3, #0x2] cmp r0, #0xFF /*Term Check*/ bne loc_8043DF6 loc_8043E18: mov r0,r5 pop {r4-r7} pop {r1} bx r1 .align 2 .learned_moves_ptr: .word 0x0832937C
Aside from these routines you should also note that there are two more routines in Emerald that reference this table located at 19FF98 and 1A01E8. I have not included edited versions of these routines simply because I could not get the debugger to break on them. I have no idea what uses them but I can tell you that the 6 routines provided are enough to make things work. If I ever figure out what the other routines are I will post an update but they do not seem to be important at this time.
[/spoiler]
Once those ASM routines are inserted it is time to for some boring stuff. The level up tables for each Pokemon need to be changed to the new format used by these routines. The format is the following with “0000FF” as the terminator.
[MOVE - Half-Word - Reverse Hex] [Level - Byte]
Unfortunately this is a lot to do but it is needed for the hack to work. Luckily if you do not wish to convert the level up tables yourself, you can use Pokemon Game Editor to add more attacks and it will convert the tables for you.
Once you’ve done all this, you are done. At this point you may want to edit inis for any programs you may want to use your ROM with. The following are the entries you would need to edit for Pokemon Game Editor.
AttackNames=31977C NumberOfAttacks=354 AttackData=31C898 ContestMoveData=58C2B4 AttackDescriptionTable=61C524 AttackAnimationTable=2C8D6C MoveTableHack=True
This should be all you need to add more attacks to your ROM. Now you can go ahead creating animations, effects, and all that good stuff. Please feel free to comment if you have any questions.