|
@@ -0,0 +1,217 @@
|
|
|
+.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
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|