• 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: Porting JPANs save_block_recycle to Emerald

91
Posts
14
Years
    • Seen Feb 22, 2023
    Hey you romhackers and developers out there, I kind of stumbled uppon a routine that JPAN made public in this thread: Screw it i'm not allowed to post URLs... It is in the Research: "Firered Pokedex" Thread, somewhere on page 9, but I guess it's not that important though and I included the original codelines by JPAN!
    Well, a few of you might be interested(or at least I am) if we could manage to port this to an emerald rom, german emerald in my case, but I don't think this should make much difference apart from a few adresses. Here is what I came up with so far as a "step by step" instruction sheet, just because it's easier for me to insert stuff when I have it like that(ATTENTION: DO NOT USE THIS IN YOUR ROM, IT CORRUPTS YOUR SAVE FILE COMPLETELY):


    • Compile "Code (BPED)" and write it to free space in your BPED ROM
    • At 0x152A3C change to 0x00 0x48 0x00 0x47 POINTER_TO_ROUTINE
    • At 0x1523F2 change to 0x38 0x47
    • At 0x152430 change to POINTER_TO_ROUTINE+0x61
    Also the code file I modified from the original one(Including JPANs comments and stuff, yeah):

    Code:
    .align 2
    .thumb
    
    /*cc left in first block
    70 +70+70+108 = 258 in people block
    8*70 + 820 = BA0 from box block
    grand total of EC4 wasted space (9/10 of block wasted)
    saved c000 to c0cc at first block (0x0)
    saved c0cc to c324 at fifth block (0x4)
    saved c324 to cec4 at 14th block (0xd)*/
    
    
    /*at 080D9EDC, in the save routine, place a branch to this (in r0)*/
    /*in pre-patched Fire Red, d9ef0*/
    load_hijack:    ldr r1, [r4]
            mov r3, #0xff 
            lsl r3, r3, #0x4
            add r3, r3, r1
            ldrh r0, [r3, #0x4]
            cmp r0, #0x0
            beq first_cc_load
            cmp r0, #0x4
            beq middle_load
            cmp r0, #0xd
            beq last_load
    
    
    load_ender:    cmp r5, #0xd
            ble next_loop_iter
            
            mov r0, #0x1
            pop {r3}
            mov r8, r3
            pop {r4-r7, pc}        
    
    first_cc_load:    mov r1, #0xcc
            ldr r2, c0c8_addr
            b load_loop    
        
    middle_load:    mov r1, #0x96
            lsl r1, r1, #0x2
            ldr r2, c320_addr
            b load_loop
    
    last_load:    mov r1, #0xba
            lsl r1, r1, #0x4
            ldr r2, cec0_addr
                    
    
    load_loop:    sub r3, #0x4
            ldr r0, [r3]
            str r0, [r2]
            sub r2, #0x4    
            sub r1, #0x4
            cmp r1, #0x0
            bne load_loop
            b load_ender
    .hword 0x0000
    c0c8_addr:    .word 0x0203c0c8
    c320_addr:    .word 0x0203c320
    cec0_addr:    .word 0x0203cec0
    
    next_loop_iter:    ldr r0, game_load_ret_addr
            bx r0
    game_load_ret_addr:    .word 0x081529D1
    /*d9e85 for pre-patched*/
    
    
    .word 0xffffffff
    /*for the Save routine, we hijack before the save on Flash routine
    that is located at 080d991e. Change there for bx r7, and at 80D995C
    place pointer to this*/
    /*in pre-patched version is d9932 and d9970*/
    
    store_hijack:    mov r7, #0xff
            lsl r7, r7, #0x4
            add r7, r1, r7
            strh r0, [r7,#0x6]
            ldrh r6, [r7, #0x4]
            cmp r6, #0x0
            beq first_store
            cmp r6, #0x4
            beq middle_store
            cmp r6, #0xd
            beq last_store
    
    .hword 0x0000
    store_ender:    ldr r0, game_store_ret_addr
            bx r0
    game_store_ret_addr:    .word 0x081523F7
    /*in pre-patched return is d9937*/
    
    
    first_store:    mov r3, #0xcc
            ldr r2, c0c8_addr_2
            b store_loop    
        
    middle_store:    mov r3, #0x96
            lsl r3, r3, #0x2
            ldr r2, c320_addr_2
            b store_loop
    
    last_store:    mov r3, #0xba
            lsl r3, r3, #0x4
            ldr r2, cec0_addr_2
    
    store_loop:    sub r7, #0x4
            ldr r0, [r2]
            str r0, [r7]
            sub r2, #0x4
            sub r3, #0x4
            cmp r3, #0x0
            bne store_loop
            b store_ender
    
    c0c8_addr_2:    .word 0x0203c0c8
    c320_addr_2:    .word 0x0203c320
    cec0_addr_2:    .word 0x0203cec0
    
    
    /*new table data*/
    /*500c block*/
    .hword 0x0
    .hword 0xf24
    
    /*5008 block*/
    .hword 0x0
    .hword 0xff0
    
    .hword 0xff0
    .hword 0xff0
    
    .hword 0x1fe0
    .hword 0xff0
    
    .hword 0x2fd0
    .hword 0xd98
    
    /*5010 (box) block*/
    
    .hword 0x0
    .hword 0xff0
    
    .hword 0xff0
    .hword 0xff0
    
    .hword 0x1fe0
    .hword 0xff0
    
    .hword 0x2fd0
    .hword 0xff0
    
    .hword 0x3fc0
    .hword 0xff0
    
    .hword 0x4fb0
    .hword 0xff0
    
    .hword 0x5fa0
    .hword 0xff0
    
    .hword 0x6f90
    .hword 0xff0
    
    .hword 0x7f80
    .hword 0x450
    ORIGINAL CODE BY JPAN FOR THE ENGLISH VERSION OF FIRERED:
    Code:
    .align 2
    .thumb
    
    
    /*cc left in first block
    70 +70+70+108 = 258 in people block
    8*70 + 820 = BA0 from box block
    grand total of EC4 wasted space (9/10 of block wasted)
    saved c000 to c0cc at first block (0x0)
    saved c0cc to c324 at fifth block (0x4)
    saved c324 to cec4 at 14th block (0xd)*/
    
    
    /*at 080D9EDC, in the save routine, place a branch to this (in r0)*/
    /*in pre-patched Fire Red, d9ef0*/
    load_hijack:    ldr r1, [r4]
            mov r3, #0xff 
            lsl r3, r3, #0x4
            add r3, r3, r1
            ldrh r0, [r3, #0x4]
            cmp r0, #0x0
            beq first_cc_load
            cmp r0, #0x4
            beq middle_load
            cmp r0, #0xd
            beq last_load
    
    
    load_ender:    cmp r5, #0xd
            ble next_loop_iter
            
            mov r0, #0x1
            pop {r3}
            mov r8, r3
            pop {r4-r7, pc}        
    
    first_cc_load:    mov r1, #0xcc
            ldr r2, c0c8_addr
            b load_loop    
        
    middle_load:    mov r1, #0x96
            lsl r1, r1, #0x2
            ldr r2, c320_addr
            b load_loop
    
    last_load:    mov r1, #0xba
            lsl r1, r1, #0x4
            ldr r2, cec0_addr
                    
    
    load_loop:    sub r3, #0x4
            ldr r0, [r3]
            str r0, [r2]
            sub r2, #0x4    
            sub r1, #0x4
            cmp r1, #0x0
            bne load_loop
            b load_ender
    .hword 0x0000
    c0c8_addr:    .word 0x0203c0c8
    c320_addr:    .word 0x0203c320
    cec0_addr:    .word 0x0203cec0
    
    next_loop_iter:    ldr r0, game_load_ret_addr
            bx r0
    game_load_ret_addr:    .word 0x080D9E71
    /*d9e85 for pre-patched*/
    
    
    .word 0xffffffff
    /*for the Save routine, we hijack before the save on Flash routine
    that is located at 080d991e. Change there for bx r7, and at 80D995C
    place pointer to this*/
    /*in pre-patched version is d9932 and d9970*/
    
    store_hijack:    mov r7, #0xff
            lsl r7, r7, #0x4
            add r7, r1, r7
            strh r0, [r7,#0x6]
            ldrh r6, [r7, #0x4]
            cmp r6, #0x0
            beq first_store
            cmp r6, #0x4
            beq middle_store
            cmp r6, #0xd
            beq last_store
    
    .hword 0x0000
    store_ender:    ldr r0, game_store_ret_addr
            bx r0
    game_store_ret_addr:    .word 0x080D9923
    /*in pre-patched return is d9937*/
    
    
    first_store:    mov r3, #0xcc
            ldr r2, c0c8_addr_2
            b store_loop    
        
    middle_store:    mov r3, #0x96
            lsl r3, r3, #0x2
            ldr r2, c320_addr_2
            b store_loop
    
    last_store:    mov r3, #0xba
            lsl r3, r3, #0x4
            ldr r2, cec0_addr_2
    
    store_loop:    sub r7, #0x4
            ldr r0, [r2]
            str r0, [r7]
            sub r2, #0x4
            sub r3, #0x4
            cmp r3, #0x0
            bne store_loop
            b store_ender
    
    c0c8_addr_2:    .word 0x0203c0c8
    c320_addr_2:    .word 0x0203c320
    cec0_addr_2:    .word 0x0203cec0
    
    
    /*new table data*/
    /*500c block*/
    .hword 0x0
    .hword 0xf24
    
    /*5008 block*/
    .hword 0x0
    .hword 0xff0
    
    .hword 0xff0
    .hword 0xff0
    
    .hword 0x1fe0
    .hword 0xff0
    
    .hword 0x2fd0
    .hword 0xd98
    
    /*5010 (box) block*/
    
    .hword 0x0
    .hword 0xff0
    
    .hword 0xff0
    .hword 0xff0
    
    .hword 0x1fe0
    .hword 0xff0
    
    .hword 0x2fd0
    .hword 0xff0
    
    .hword 0x3fc0
    .hword 0xff0
    
    .hword 0x4fb0
    .hword 0xff0
    
    .hword 0x5fa0
    .hword 0xff0
    
    .hword 0x6f90
    .hword 0xff0
    
    .hword 0x7f80
    .hword 0x450
    Yeah, seems pretty simple and I don't get a rom crash(at least), but as you can read in the warning above it does not seem to work properly: I can save, but when I load my game again it says "Der Spielstand wurde gelöscht" which kind of means "The save file was deleted" in english.
    Question: Did anyone try to do this before me and can give me a hand, what did I do wrong? Basically I just followed the instructions in the code file: first setting the branch to "load_hijack"(step two) after that setting a branch to "store_hijack" in r7(steps three and four)
    I sure changed the return adresses in the code aswell and I'm dramatically sure they are correct since the game does not even crash.

    Would be great if those awesome code-lines from JPAN could be used also in emerald hacks because... they are awesome ^-^

    ~SBird

    Edit: Just for those who are interested, here is the working snippet for BPED, if you want to use it for the english version I suppose it is enough to change the return adresses and add the necessary branches in the original save routine. Anyways, the snippet for BPED is as follows:

    Code:
    .align 2
    .thumb
    
    
    /*cc left in first block
    70 +70+70+108 = 258 in people block
    8*70 + 820 = BA0 from box block
    grand total of EC4 wasted space (9/10 of block wasted)
    saved c000 to c0cc at first block (0x0)
    saved c0cc to c324 at fifth block (0x4)
    saved c324 to cec4 at 14th block (0xd)*/
    
    
    /*at 080D9EDC, in the save routine, place a branch to this (in r0)*/
    /*in pre-patched Fire Red, d9ef0*/
    load_hijack:    ldr r1, [r4]
            mov r3, #0xff 
            lsl r3, r3, #0x4
            add r3, r3, r1
            ldrh r0, [r3, #0x4]
            cmp r0, #0x0
            beq first_cc_load
            cmp r0, #0x4
            beq middle_load
            cmp r0, #0xd
            beq last_load
    
    
    load_ender:    cmp r5, #0xd
            ble next_loop_iter
            
            mov r0, #0x1
            pop {r3}
            mov r8, r3
            pop {r4-r7, pc}        
    
    first_cc_load:    mov r1, #0xc4
            ldr r2, c0c8_addr
            b load_loop    
        
    middle_load:    mov r1, #0x1d
            lsl r1, r1, #0x3
            ldr r2, c320_addr
            b load_loop
    
    last_load:    mov r1, #0x41
            lsl r1, r1, #0x5
            ldr r2, cec0_addr
                    
    
    load_loop:    sub r3, #0x4
            ldr r0, [r3]
            str r0, [r2]
            sub r2, #0x4    
            sub r1, #0x4
            cmp r1, #0x0
            bne load_loop
            b load_ender
    .hword 0x0000
    c0c8_addr:    .word 0x0203c0c0
    c320_addr:    .word 0x0203c1A8
    cec0_addr:    .word 0x0203c9C8
    
    next_loop_iter:    ldr r0, game_load_ret_addr
            bx r0
    game_load_ret_addr:    .word 0x081529D1
    /*d9e85 for pre-patched*/
    
    
    .word 0xffffffff
    /*for the Save routine, we hijack before the save on Flash routine
    that is located at 080d991e. Change there for bx r7, and at 80D995C
    place pointer to this*/
    /*in pre-patched version is d9932 and d9970*/
    
    store_hijack:    mov r7, #0xff
            lsl r7, r7, #0x4
            add r7, r1, r7
            strh r0, [r7,#0x6]
            ldrh r6, [r7, #0x4]
            cmp r6, #0x0
            beq first_store
            cmp r6, #0x4
            beq middle_store
            cmp r6, #0xd
            beq last_store
    
    .hword 0x0000
    store_ender:    ldr r0, game_store_ret_addr
            bx r0
    game_store_ret_addr:    .word 0x081523F7
    /*in pre-patched return is d9937*/
    
    
    first_store:    mov r3, #0xc4
            ldr r2, c0c8_addr_2
            b store_loop    
        
    middle_store:    mov r3, #0x1D
            lsl r3, r3, #0x3
            ldr r2, c320_addr_2
            b store_loop
    
    last_store:    mov r3, #0x41
            lsl r3, r3, #0x5
            ldr r2, cec0_addr_2
    
    store_loop:    sub r7, #0x4
            ldr r0, [r2]
            str r0, [r7]
            sub r2, #0x4
            sub r3, #0x4
            cmp r3, #0x0
            bne store_loop
            b store_ender
    
    c0c8_addr_2:    .word 0x0203c0c0
    c320_addr_2:    .word 0x0203c1A8
    cec0_addr_2:    .word 0x0203c9C8
    Those are the instructions I put in my notefile when editing the snippet:

    • At 0x152A3C change to 0x00 0x48 0x00 0x47 POINTER_TO_ROUTINE
    • At 0x1523F2 change to 0x38 0x47
    • At 0x152430 change to POINTER_TO_ROUTINE+0x61
    I am using the emerald save_table, which is located at 0x5DEFC8 as follows:


    00002C0F0000F00FF00FF00FE01FF00
    FD02F080F0000F00FF00FF00FE01FF0
    0FD02FF00FC03FF00FB04FF00FA05FF
    00F906FF00F807FD007


    Since emerald uses much more space compared to firered it is not possible to recycle that much space, but there are still 2508(0x9CC) Bytes left from 0x0203C000 - 0x0203C9CC that you can use to store data in the save...


    For further information please view the original post from JPAN, I also want to state that most of the work is as you can think from him, not from me or anyone else.


    ~SBird
     
    Last edited:
    Back
    Top