.align 2 .thumb /*A very pertinent problem arose from the study of Variables. The fact is, we never knew much about them, and just used them. But in the end, those variables were, in fact, pieces of other program's memory. Solution is to find a location where we can lay our own variables, and use those to our advantage. Every pokemon game accesses variables through the same mechanism every time. Variable is accessed by using a call to a specialized function, that because of its lack of boundaries, let us use every piece of code there as our own. The proposed solution is to find a large RAM address (0x1000 long) and use it to make a place for 0x800 variables (something like 0x5000 to 0x57ff.) This should be enough for most games, and they're perfectly safe. Then, during the Save and Load Routines, add a new module to load from 0xe01f000 (bank1, slot f), that is unused by the game, and can carry that much information. Also proposed, to solve the problem, is to use any variable from 0x5800 to 0x5fff as a mirror to the first pair, any variable from 0x6000 to 0x6fff as a byte-load for the 0x5000 variables, and any from the 0x7000 as a word-load for the 0x5000 variable family, and 0x7400-0x7fff as flag-load for some select few.*/ /*first, and most important, we need the 0x5000 flags stored somewhere, even if the game didn't save them. That is where the Var-Decrypt come in.*/ /*var decrypt is located at 0x0806E454. Because most of the code is harmless in its own, we will only change the part that loads variables above 0x4000 and below 0x8000. That is located at 0x6e4f2. We change 0x6e4f4 to 0x10 47, and place the pointer to this function at 0x6e508 Even though Emerald code is different, it's in fact much simpler. As such all old rules apply. at 0809D682 place 10 47 and at 0809D690 the pointer*/ /*begin*/ Var_decrypt_change: mov r1, #0x50 lsl r1, r1, #0x8 sub r1, r6, r1 /*if it is lower than 0x5000, it will be less than 0*/ cmp r1, #0x0 blt is_4xxx mov r2, #0x80 lsl r2, r2, #0x4 cmp r1, r2 /*r2 = 0x800*/ blt load_5xxx sub r1, r1, r2 cmp r1, r2 /*r2 = 0x800, this is the mirrored line*/ blt load_5xxx sub r1, r1, r2 lsl r2, #0x1 cmp r1, r2 blt load_6xxx sub r1, r1, r2 lsr r2, r2, #0x2 cmp r1, r2 blt load_7xxx mov r0, #0x0 pop {r4-r6,pc} is_4xxx: ldr r2, mask_9x lsl r1, r6, #0x1 add r1, r2, r1 ldr r0, [r0] add r0, r0, r1 pop {r4-r6,pc} load_7xxx: lsl r1, r1, #0x1 /*r1<<2 = word address */ load_5xxx: lsl r1, r1, #0x1 /*r1 << 1 = halfword address*/ load_6xxx: ldr r0, new_var_location /*no shift means byte address*/ add r0, r0, r1 pop {r4-r6,pc} .hword 0x0000 mask_9x: .word 0xffff9000 /*for Emerald, it's 0xffff939c*/ new_var_location: .word 0x0203e000 /*end*/ /*the other way to load variables is through the Variable Loader. But that raises a problem: It only loads halfwords. To solve that problem, at 0806e574, place 0049 0847 pointer to this In Emerald, place at 0809d6a0 the 0049 0847 pointer to this */ /*begin*/ VarLoader_change: cmp r0, #0x0 beq no_variable_loaded mov r1, #0x60 lsl r1, r1, #0x8 sub r1, r4, r1 cmp r1, #0x0 blt var_load_hword mov r2, #0x80 lsl r2, r2, #0x8 cmp r4, r2 bge var_load_hword lsr r2, r2, #0x3 sub r1, r1, r2 cmp r1, #0x0 blt var_load_byte ldr r0, [r0] pop {r4,pc} no_variable_loaded: add r0, r4, #0x0 pop {r4, pc} var_load_byte: ldrb r0, [r0] pop {r4,pc} var_load_hword: ldrh r0, [r0] pop {r4,pc} .hword 0x0000 /*end*/ /*var store will be fixed for Storing only 0x4000-0x6fff. That way, you can have byte storage for variables In Fire Red, place at 0x0806E584 30 b5 05 04 28 0c at 0x0806E592 01 49 08 47 00 00 pointer In Emerald, place at 0x0809d6b0 30 b5 05 04 28 0c at 0x0809d6be 01 49 08 47 00 00 pointer */ /*begin*/ Var_store_cont: cmp r0, #0x0 beq no_store mov r1, #0x60 lsl r1, r1, #0x8 sub r1, r5, r1 cmp r1, #0x0 blt var_store_hword mov r2, #0x80 lsl r2, r2, #0x8 cmp r5, r2 bge var_store_hword lsr r2, r2, #0x3 sub r1, r1, r2 cmp r1, #0x0 blt var_store_byte no_store: pop {r4-r5,pc} var_store_byte: strb r4, [r0] pop {r4-r5,pc} var_store_hword: strh r4, [r0] pop {r4-r5,pc} /*end*/ /*finally, we need to save those variables from being purged at the end of the game. So, we will modify the Save file to allow us to keep the variables somewhere where nobody gets hurt (bank 0x1f)*/ /*this first code is the save one, and allows us to save the new variable location at bank 0x1f. for that, we need to edit the code at 080D9838, right after the standart save is finished. Lucky, that is a load that has a pointer! Then, change 0x080d983a with 00 47 and 0x080D986C with the pointer to this. In Emerald, change 0x0815276a with 00 47 and 0x0815279C with the pointer */ /*begin*/ Save_vars: mov r0, #0x1f ldr r1, variable_new_addr bl SetFlash4k ldr r1, Save_ret sub r6, #0x4 ldr r0, [r6] add r6, #0x4 bx r1 .hword 0x0000 Save_ret: .word 0x080D983d /*in Emerald, change this to 0815276d*/ /*end*/ /*then we also need the Load code. This one is more wordy, as we need to load byte by byte the entire content we need from the Flash. In Emerald, the location to change is 0x08152ea0 In fire red, the location to change is 0x080D9EE4 place a 0048 0047 pointer. We'll take care of exiting the function*/ /*begin*/ Load_Vars: bl SetSecondBank ldr r0, variable_new_addr mov r1, #0xf0 lsl r1, r1, #0x8 orr r3, r1 mov r2, #0x10 lsl r2, r2, #0x8 byte_load_loop: ldrb r1, [r3] strb r1, [r0] add r0, #0x1 add r3, #0x1 sub r2, #0x1 cmp r2, #0x0 bgt byte_load_loop add r0, r5, #0x0 pop {r1} mov r8, r1 pop {r4-r7, pc} .hword 0x0000 /*end*/ variable_new_addr: .word 0x0203e000 SetFlash4k: ldr r3, set_flash_addr bx r3 set_flash_addr: .word 0x081DF071 /*for emerald, 0x082E20Ad*/ SetSecondBank: mov r3, #0x0e mov r2, #0x55 lsl r3, r3, #0x18 lsl r1, r2, #0x8 /*r1 = 5500*/ orr r1, r3 /*r1 = 0e005500*/ orr r1, r2 /*r1 = 0e005555*/ mov r0, #0xAA strb r0, [r1] mov r2, #0x2a lsl r2, r2, #0x8 /*r2 = 2a00*/ orr r2, r0 /*r2 = 2aaa*/ orr r2, r3 /*r2 = 0e002aaa*/ mov r0, #0x55 strb r0, [r2] mov r0, #0xb0 strb r0, [r1] mov r0, #0x1 strb r0, [r3] bx lr