• 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?".
  • Forum moderator applications are now open! Click here for details.
  • 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