Variable Fix.tmb 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. .align 2
  2. .thumb
  3. /*A very pertinent problem arose from the study of Variables. The fact is, we
  4. never knew much about them, and just used them. But in the end, those variables
  5. were, in fact, pieces of other program's memory. Solution is to find a location
  6. where we can lay our own variables, and use those to our advantage.
  7. Every pokemon game accesses variables through the same mechanism every time.
  8. Variable is accessed by using a call to a specialized function, that because of
  9. its lack of boundaries, let us use every piece of code there as our own.
  10. The proposed solution is to find a large RAM address (0x1000 long) and use it to
  11. make a place for 0x800 variables (something like 0x5000 to 0x57ff.) This should
  12. be enough for most games, and they're perfectly safe. Then, during the Save and
  13. Load Routines, add a new module to load from 0xe01f000 (bank1, slot f), that is
  14. unused by the game, and can carry that much information.
  15. Also proposed, to solve the problem, is to use any variable from 0x5800 to 0x5fff
  16. as a mirror to the first pair, any variable from 0x6000 to 0x6fff as a byte-load
  17. for the 0x5000 variables, and any from the 0x7000 as a word-load for the 0x5000
  18. variable family, and 0x7400-0x7fff as flag-load for some select few.*/
  19. /*first, and most important, we need the 0x5000 flags stored somewhere, even if
  20. the game didn't save them. That is where the Var-Decrypt come in.*/
  21. /*var decrypt is located at 0x0806E454. Because most of the code is harmless in
  22. its own, we will only change the part that loads variables above 0x4000 and below
  23. 0x8000. That is located at 0x6e4f2. We change 0x6e4f4 to 0x10 47, and place the
  24. pointer to this function at 0x6e508
  25. Even though Emerald code is different, it's in fact much simpler. As such all
  26. old rules apply. at 0809D682 place 10 47 and at 0809D690 the pointer*/
  27. /*begin*/
  28. Var_decrypt_change: mov r1, #0x50
  29. lsl r1, r1, #0x8
  30. sub r1, r6, r1 /*if it is lower than 0x5000, it will be less than 0*/
  31. cmp r1, #0x0
  32. blt is_4xxx
  33. mov r2, #0x80
  34. lsl r2, r2, #0x4
  35. cmp r1, r2 /*r2 = 0x800*/
  36. blt load_5xxx
  37. sub r1, r1, r2
  38. cmp r1, r2 /*r2 = 0x800, this is the mirrored line*/
  39. blt load_5xxx
  40. sub r1, r1, r2
  41. lsl r2, #0x1
  42. cmp r1, r2
  43. blt load_6xxx
  44. sub r1, r1, r2
  45. lsr r2, r2, #0x2
  46. cmp r1, r2
  47. blt load_7xxx
  48. mov r0, #0x0
  49. pop {r4-r6,pc}
  50. is_4xxx: ldr r2, mask_9x
  51. lsl r1, r6, #0x1
  52. add r1, r2, r1
  53. ldr r0, [r0]
  54. add r0, r0, r1
  55. pop {r4-r6,pc}
  56. load_7xxx: lsl r1, r1, #0x1 /*r1<<2 = word address */
  57. load_5xxx: lsl r1, r1, #0x1 /*r1 << 1 = halfword address*/
  58. load_6xxx: ldr r0, new_var_location /*no shift means byte address*/
  59. add r0, r0, r1
  60. pop {r4-r6,pc}
  61. .hword 0x0000
  62. mask_9x: .word 0xffff9000 /*for Emerald, it's 0xffff939c*/
  63. new_var_location: .word 0x0203e000
  64. /*end*/
  65. /*the other way to load variables is through the Variable Loader. But that raises
  66. a problem: It only loads halfwords. To solve that problem, at 0806e574, place
  67. 0049 0847 pointer to this
  68. In Emerald, place at 0809d6a0 the 0049 0847 pointer to this
  69. */
  70. /*begin*/
  71. VarLoader_change: cmp r0, #0x0
  72. beq no_variable_loaded
  73. mov r1, #0x60
  74. lsl r1, r1, #0x8
  75. sub r1, r4, r1
  76. cmp r1, #0x0
  77. blt var_load_hword
  78. mov r2, #0x80
  79. lsl r2, r2, #0x8
  80. cmp r4, r2
  81. bge var_load_hword
  82. lsr r2, r2, #0x3
  83. sub r1, r1, r2
  84. cmp r1, #0x0
  85. blt var_load_byte
  86. ldr r0, [r0]
  87. pop {r4,pc}
  88. no_variable_loaded: add r0, r4, #0x0
  89. pop {r4, pc}
  90. var_load_byte: ldrb r0, [r0]
  91. pop {r4,pc}
  92. var_load_hword: ldrh r0, [r0]
  93. pop {r4,pc}
  94. .hword 0x0000
  95. /*end*/
  96. /*var store will be fixed for Storing only 0x4000-0x6fff.
  97. That way, you can have byte storage for variables
  98. In Fire Red, place at 0x0806E584 30 b5 05 04 28 0c
  99. at 0x0806E592 01 49 08 47 00 00 pointer
  100. In Emerald, place at 0x0809d6b0 30 b5 05 04 28 0c
  101. at 0x0809d6be 01 49 08 47 00 00 pointer
  102. */
  103. /*begin*/
  104. Var_store_cont: cmp r0, #0x0
  105. beq no_store
  106. mov r1, #0x60
  107. lsl r1, r1, #0x8
  108. sub r1, r5, r1
  109. cmp r1, #0x0
  110. blt var_store_hword
  111. mov r2, #0x80
  112. lsl r2, r2, #0x8
  113. cmp r5, r2
  114. bge var_store_hword
  115. lsr r2, r2, #0x3
  116. sub r1, r1, r2
  117. cmp r1, #0x0
  118. blt var_store_byte
  119. no_store: pop {r4-r5,pc}
  120. var_store_byte: strb r4, [r0]
  121. pop {r4-r5,pc}
  122. var_store_hword: strh r4, [r0]
  123. pop {r4-r5,pc}
  124. /*end*/
  125. /*finally, we need to save those variables from being purged at the end of the
  126. game. So, we will modify the Save file to allow us to keep the variables
  127. somewhere where nobody gets hurt (bank 0x1f)*/
  128. /*this first code is the save one, and allows us to save the new variable
  129. location at bank 0x1f. for that, we need to edit the code at 080D9838, right
  130. after the standart save is finished. Lucky, that is a load that has a pointer!
  131. Then, change 0x080d983a with 00 47 and 0x080D986C with the pointer to this.
  132. In Emerald, change 0x0815276a with 00 47 and 0x0815279C with the pointer */
  133. /*begin*/
  134. Save_vars: mov r0, #0x1f
  135. ldr r1, variable_new_addr
  136. bl SetFlash4k
  137. ldr r1, Save_ret
  138. sub r6, #0x4
  139. ldr r0, [r6]
  140. add r6, #0x4
  141. bx r1
  142. .hword 0x0000
  143. Save_ret: .word 0x080D983d /*in Emerald, change this to 0815276d*/
  144. /*end*/
  145. /*then we also need the Load code. This one is more wordy, as we need to
  146. load byte by byte the entire content we need from the Flash.
  147. In Emerald, the location to change is 0x08152ea0
  148. In fire red, the location to change is 0x080D9EE4
  149. place a 0048 0047 pointer. We'll take care of exiting the
  150. function*/
  151. /*begin*/
  152. Load_Vars: bl SetSecondBank
  153. ldr r0, variable_new_addr
  154. mov r1, #0xf0
  155. lsl r1, r1, #0x8
  156. orr r3, r1
  157. mov r2, #0x10
  158. lsl r2, r2, #0x8
  159. byte_load_loop: ldrb r1, [r3]
  160. strb r1, [r0]
  161. add r0, #0x1
  162. add r3, #0x1
  163. sub r2, #0x1
  164. cmp r2, #0x0
  165. bgt byte_load_loop
  166. add r0, r5, #0x0
  167. pop {r1}
  168. mov r8, r1
  169. pop {r4-r7, pc}
  170. .hword 0x0000
  171. /*end*/
  172. variable_new_addr: .word 0x0203e000
  173. SetFlash4k: ldr r3, set_flash_addr
  174. bx r3
  175. set_flash_addr: .word 0x081DF071 /*for emerald, 0x082E20Ad*/
  176. SetSecondBank: mov r3, #0x0e
  177. mov r2, #0x55
  178. lsl r3, r3, #0x18
  179. lsl r1, r2, #0x8 /*r1 = 5500*/
  180. orr r1, r3 /*r1 = 0e005500*/
  181. orr r1, r2 /*r1 = 0e005555*/
  182. mov r0, #0xAA
  183. strb r0, [r1]
  184. mov r2, #0x2a
  185. lsl r2, r2, #0x8 /*r2 = 2a00*/
  186. orr r2, r0 /*r2 = 2aaa*/
  187. orr r2, r3 /*r2 = 0e002aaa*/
  188. mov r0, #0x55
  189. strb r0, [r2]
  190. mov r0, #0xb0
  191. strb r0, [r1]
  192. mov r0, #0x1
  193. strb r0, [r3]
  194. bx lr