- 218
- Posts
- 11
- Years
- Seen Nov 12, 2021
Hi, thanks for sharing this. Though I have a question : what is the difference with Jambo51 method ?
No difference,However Jambo51 is Fire Red,This is Emerald。
Hello everyone, I am a Chinese, not how to speak English, this is my first time here posting, so I hope you can take care of!
Spoiler:
Code:.thumb @ 0x0869400-0x0869423 zero clear .org 0x69350 .byte: 0x1F, 0xD0, 0x29, 0x4C .org 0x6935A main: ldr r2, aaa mov r5, r9 lsl r3, r5, #0x2 add r5, r3, r2 ldr r0, [r5, #0x0] ldrb r0, [r0, #0x2] mov r6, r4 mov r12, r2 mov r4, r10 cmp r0, r4 beq c mov r2, r6 mov r3, r5 b: ldrb r0, [r2, #0x0] add r0, #0x1 strb r0, [r2, #0x0] ldrb r0, [r2, #0x0] lsl r1, r0, #0x1 add r0, r1 ldr r1, [r3, #0x0] add r0, r1 ldrb r1, [r0, #0x2] cmp r1, #0xff bne a mov r0, #0x0 b d a: cmp r1, r4 bne b ldr r3, aaa mov r1, r9 lsl r4, r1, #0x2 add r1, r4, r3 ldr r2, bbb ldrb r0, [r2, #0x0] ldr r1, [r1, #0x0] lsl r6, r0, #0x1 add r0, r6 add r0, r1 ldrb r0, [r0, #0x2] mov r1, r10 mov r6, r2 mov r12, r3 mov r3, r4 cmp r0, r1 bne end c: ldr r2, ddd mov r0, r12 add r1, r3, r0 ldrb r0, [r6, #0x0] ldr r1, [r1, #0x0] lsl r7, r0, #0x1 add r0, r7 add r0, r1 ldrb r1, [r0, #0x1] lsl r1, r1, #0x8 ldrb r0, [r0, #0x0] orr r0, r1 strh r0, [r2, #0x0] ldrb r0, [r6, #0x0] add r0, #0x1 strb r0, [r6, #0x0] ldrh r1, [r2, #0x0] mov r0, r8 bl 0x6912C lsl r0, r0, #0x10 lsr r0, r0, #0x10 str r0, [sp, #0x0] end: ldr r0, [sp, #0x0] d: add sp, #0x4 pop {r3-r5} mov r8, r3 mov r9, r4 mov r10, r5 pop {r4-r7} pop {r1} bx r1 .align 2 aaa: .word 0xFFFFFFFF @moveset table Offset bbb: .word 0x020244E8 ddd: .word 0x020244E2
Code:.thumb @ 0x08069300-0x08069317 zero clear .org 0x69298 main: ldr r0, aaa lsl r6, r4, #0x2 add r0, r6 ldr r0, [r0, #0x0] ldrb r1, [r0, #0x2] cmp r1, #0xFF beq end mov r3, #0x0 a: ldr r0, aaa add r7, r6, r0 ldr r0, [r7, #0x0] add r0, r3 ldrb r2, [r0, #0x2] mov r1, r10 cmp r2, r1 bgt end ldrb r1, [r0, #0x1] lsl r1, r1, #0x8 ldrb r0, [r0, #0x0] orr r1, r0 mov r4, r1 mov r0, r8 str r3, [sp, #0x0] bl 0x69140 ldr r1, bbb ldr r3, [sp, #0x0] cmp r0, r1 bne b mov r0, r8 mov r1, r4 bl 0x694D0 ldr r3, [sp, #0x0] b: add r3, #0x3 ldr r0, [r7, #0x0] add r0, r3 ldrb r0, [r0, #0x2] cmp r0, #0xFF bne a end: add sp, #0x4 pop {r3-r5} mov r8, r3 mov r9, r4 mov r10, r5 pop {r4-r7} pop {r1} bx r1 .align 2 aaa: .word 0xFFFFFFFF @moveset table Offset bbb: .hword 0xFFFF
Code:.thumb @ 0x0806E1F8-0x0806E203 zero clear .org 0x6E100 main: mov r5, #0x0 ldr r6, aaa lsl r1, r7, #0x2 add r2, r1, r6 ldr r3, [r2, #0x0] ldrb r0, [r3, #0x2] str r1, [sp, #0x14] cmp r0, #0xFF beq end mov r9, r2 str r3, [sp, #0x10] f: lsl r2, r5, #0x1 add r2, r5 ldr r1, [sp, #0x10] add r0, r2, r1 ldrb r3, [r0, #0x2] ldr r1, [sp, #0xC] mov r7, r2 add r5, #0x1 mov r12, r5 cmp r3, r1 bgt d mov r4, #0x0 mov r1, sp ldrh r1, [r1, #0x0] ldrb r3, [r0, #0x1] lsl r3, r3, #0x8 ldrb r0, [r0, #0x0] orr r0, r3 cmp r1, r0 beq b ldr r0, [sp, #0x14] ldr r1, aaa add r6, r0, r1 mov r3, sp mov r5, r7 a: add r3, #0x2 add r4, #0x1 cmp r4, #0x3 bgt b ldr r0, [r6, #0x0] add r0, r5 ldrb r1, [r0, #0x1] lsl r1, r1, #0x8 ldrb r0, [r0, #0x0] orr r0, r1 ldrh r2, [r3, #0x0] cmp r2, r0 bne a b: cmp r4, #0x4 bne d mov r4, #0x0 cmp r4, r10 bge e mov r1, r9 ldr r0, [r1, #0x0] add r0, r7 ldrb r1, [r0, #0x1] lsl r1, r1, #0x8 ldrb r0, [r0, #0x0] orr r0, r1 ldr r1, [sp, #0x8] ldrh r2, [r1, #0x0] cmp r2, r0 beq e ldr r1, [sp, #0x14] ldr r2, aaa add r6, r1, r2 ldr r3, [sp, #0x8] mov r5, r7 c: add r3, #0x2 add r4, #0x1 cmp r4, r10 bge e ldr r0, [r6, #0x0] add r0, r5 ldrb r1, [r0, #0x1] lsl r1, r1, #0x8 ldrb r0, [r0, #0x0] orr r0, r1 ldrh r2, [r3, #0x0] cmp r2, r0 bne c e: cmp r4, r10 bne d 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, r1 mov r4, r9 ldr r0, [r4, #0x0] add r0, r7 ldrb r1, [r0, #0x1] lsl r1, r1, #0x8 ldrb r0, [r0, #0x0] orr r0, r1 strh r0, [r2, #0x0] d: mov r5, r12 cmp r5, #0x13 bgt end mov r1, r9 ldr r0, [r1, #0x0] lsl r1, r5, #0x1 add r1, r5 add r1, r0 ldrb r0, [r1, #0x2] cmp r0, #0xFF bne f end: 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 aaa: .word 0xFFFFFFFF @moveset table Offset
Jambo51 original words:
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
.text
.align 2
.thumb
.thumb_func
.global newmovesetstyle4
/*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 newmovesetstyle4
/*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
/*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 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 this 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 this 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 0x0803E8B5
gothere2: .word 0x0803EC43
movesettable: .word 0x0825D7B4
.text
.align 2
.thumb
.thumb_func
.global newmovesetstyle3
/* By: Gamer2020 */
/* Change 0x043CD0 to 00490847 XXXXXXXX where the XX XX XX stands for the pointer to this 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 may 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
Yes...Gamer2020, are the routines you are talking about the working routines for moves above 511 to work?
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
yea it's 13 bytes/attack and repoint it to the end of the previously pasted attack data bytesTwo questions:
1. when you say 13 * the number of new attacks, If I'm adding 100 attacks would then be 13 times 100? so 1300 bytes?
2. Do we paste that data at the end of our previously pasted 4615 bytes?
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.
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: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:
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.