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

Development: Adding New Moves to Gen 3

218
Posts
10
Years
    • Seen Nov 12, 2021
    Hi, thanks for sharing this. Though I have a question : what is the difference with Jambo51 method ?
     
    218
    Posts
    10
    Years
    • Seen Nov 12, 2021
    No difference,However Jambo51 is Fire Red,This is Emerald。

    In the thread the emerald offset are posted too, though it's true that it's not really clear since it's spread on the thread.

    I think a mod should update Jambo51's thread with your post or those on the thread rather than create a new thread
     
    218
    Posts
    10
    Years
    • Seen Nov 12, 2021
    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:

    EDIT : Ok I added the -hopefully- corrected instruction, in bold, in the spoiler

    UPDATE : There were still some errors, I hope it now works.
     
    Last edited:
    36
    Posts
    13
    Years
  • No matter what I do, I can't seem to get this to work correctly in PGE. Upon selecting the new, added move, I get an unhandled exception of the form "RecordNumber is not a valid value", at which point the program will not allow me to do anything else on the grounds of another program apparently using the file.

    Has anyone else had similar errors? I'm pretty sure the table repointing has gone correctly for the most part, but PGE just seems to not handle the new moves after Psycho Boost.


    EDIT: Ok, it seems as if the problem was the Attack Description Table. I tried recreating an extended version of that and repointing as necessary and it's working fine now. I wonder why this wasn't included in the tutorials in the same way as the Data, Names and Animation tables? It seems to be just as necessary from experience.
     
    Last edited:

    Gamer2020

    Accept no Imitations!
    1,062
    Posts
    15
    Years
  • While coding the attack expander in PGE I noticed that if you delete the old data, field moves will end up looking like this:

    Q1yY3dG.png


    To fix it you just have to repoint a few pointers to the new name locations for those attacks. These are the pointer locations:

    Flash - 45A6A8
    Cut - 45A6B0
    Fly - 45A6B8
    Strength - 45A6C0
    Surf - 45A6C8
    Rock Smash - 45A6D0
    Waterfall - 45A6D8
    Teleport - 45A6E0
    Dig - 45A6E8
    Milk Drink - 45A6F0
    Softboiled - 45A6F8
    Sweet Scent - 45A700
     
    Last edited:

    Gamer2020

    Accept no Imitations!
    1,062
    Posts
    15
    Years
  • These are the field move pointer locations for Emerald.

    Flash - 615CA8
    Cut - 615CA0
    Fly - 615CC8
    Strength - 615CB8
    Surf -615CC0
    Rock Smash - 615CB0
    Waterfall - 615CD8
    Dive - 615CD0
    Teleport - 615CE0
    Dig - 615CE8
    Secret Power - 615CF0
    Milk Drink - 615CF8
    Softboiled - 615D00
    Sweet Scent - 615D08
     
    Last edited:
    160
    Posts
    8
    Years
  • Hello Gamer2020,
    I have a problem with PokemonGameEditor.
    I add 100 attacks and then I want to edit them, but they aren´t saving. What can I do?
    Lastly I have another question: When will you finish the next update?
     

    Gamer2020

    Accept no Imitations!
    1,062
    Posts
    15
    Years
  • A week or so ago, someone (A-bird?) on the irc mentioned to me that the move relearner would not work properly if the Pokemon could not learn any moves. I tried to reproduce the problem and sure enough this happens:

    EaFmY7s.png


    I made a mental note to look into it at some point. While working on PGE I noticed that there were 6 pointers to the level up attacks but remembered that Jambo51 only posted 3 routines. I took a look and there are 3 more routines that need to be edited.

    One of these routines is called when the move relearner is run. This routine, located at 08043E2C, seems to return the number of attacks the Pokemon can relearn. I rewrote the routine and here it is:

    This is for Fire Red. I will port it eventually.
    Code:
    .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
    This routine takes care of the pointer at 08043F84. I tested this routine and it seemed to work fine but it could always be optimized a bit more. This seems to fix most of the problems but I think that Jambo51's third routine may need some tweaking. There are two more pointers at 0803EB10 and 08043E20 but I currently have no time to look into the routines that use them.
     
    Last edited:

    Gamer2020

    Accept no Imitations!
    1,062
    Posts
    15
    Years
  • I've updated the above routine because LDRH doesn't work with misaligned data I guess.

    This is for Fire Red. I will port it eventually.
    Code:
    .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
     
    Last edited:

    Gamer2020

    Accept no Imitations!
    1,062
    Posts
    15
    Years
  • Ok so I figured out that the routine at 0803EA88 was a check for the Rare Candy to see if the Pokemon can learn a move once it's leveled up. If you were to try to use a Rare Candy on a Pokemon it would not learn moves when it should. The following small routine and byte changes fixes that. Now all that's left is to fix the routine at 08043DD4.

    This is for Fire Red. I will port it eventually.
    Code:
    .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
    I am going to be going on a trip that will last at least a month. I will not have internet during that time. I will continue ROM hacking but will not be able to post updates till I get back. By then whatever I find will be added to PGE to make it easier for people. Cya then!
     

    Gamer2020

    Accept no Imitations!
    1,062
    Posts
    15
    Years
  • I'm back from my "vacation" and can finally post what I've got. I finished the last routine. I also rewrote the 3rd routine and all problems with the move tutor now seem to be fixed. These are for Fire Red.

    I did not have time to finish the routines for Emerald since I was working on several things. Emerald has 8 routines in total. I was able to port the 6 from FR but the last two are still needed. The routines are at 0819FF98 and 081A01E8. I will release all 8 routines once I have the last 2.

    I've gathered all the needed routines for Fire Red so that they can all be in one post. Just follow the tutorial and use these routines instead. I've also added these routines to Pokemon Game Editor's Attack Adder for those that aren't as experienced with this stuff. Pokemon Game Editor will even convert the move sets to the new style for you so it will be way faster than doing it by hand. I'll be releasing the update as soon as I get settled in.

    Spoiler:

    Happy Hacking!
     
    9
    Posts
    10
    Years
    • Age 33
    • Seen Apr 7, 2018
    "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." Just how can i repoint anything anyway ? I'm using Gold Finger Hex Editor.
     
    62
    Posts
    5
    Years
  • 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

    Two 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?
     

    BluRose

    blu rass
    811
    Posts
    10
    Years
  • Two 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?
    yea it's 13 bytes/attack and repoint it to the end of the previously pasted attack data bytes
     
    6
    Posts
    3
    Years
    • Age 34
    • Seen Oct 27, 2020
    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:


    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:


    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.

    Can someone post a version of this tutorial but for Emerald?
     
    Back
    Top