codehandler.s 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. #MIT License
  2. #Copyright (c) 2010-2017 Nuke, brkirch, Y.S, Kenobi, gamemasterplc
  3. #Permission is hereby granted, free of charge, to any person obtaining a copy
  4. #of this software and associated documentation files (the "Software"), to deal
  5. #in the Software without restriction, including without limitation the rights
  6. #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. #copies of the Software, and to permit persons to whom the Software is
  8. #furnished to do so, subject to the following conditions:
  9. #The above copyright notice and this permission notice shall be included in all
  10. #copies or substantial portions of the Software.
  11. #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. #SOFTWARE.
  18. # Based off of codehandleronly.s from Gecko OS source code.
  19. # Example command to build:
  20. # powerpc-elf-gcc -mpowerpc -mpaired -mbig codehandler.s -nostartfiles -nodefaultlibs -nostdlib -T codehandler.ld -o codehandler.bin
  21. .text
  22. #Register Defines
  23. .set r0,0; .set r1,1; .set r2,2; .set r3,3; .set r4,4
  24. .set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
  25. .set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
  26. .set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
  27. .set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
  28. .set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
  29. .set r30,30; .set r31,31; .set f0,0; .set f2,2; .set f3,3
  30. .globl _start
  31. gameid:
  32. .long 0,0
  33. cheatdata:
  34. .long frozenvalue
  35. .space 39*4
  36. # Warning, _strip_and_align expects cheat codes to start on 0x0 or 0x8.
  37. # Properly compiling it will add a nop if needed.
  38. _start:
  39. stwu r1,-172(r1) # stores sp
  40. stw r0,8(r1) # stores r0
  41. mflr r0
  42. stw r0,176(r1) # stores lr
  43. mfcr r0
  44. stw r0,12(r1) # stores cr
  45. mfctr r0
  46. stw r0,16(r1) # stores ctr
  47. mfxer r0
  48. stw r0,20(r1) # stores xer
  49. stmw r3,24(r1) # saves r3-r31
  50. mfmsr r25
  51. stw r25,168(r1) # save msr
  52. ori r26,r25,0x2000 #enable floating point ?
  53. andi. r26,r26,0xF9FF
  54. mtmsr r26
  55. stfd f2,152(r1) # stores f2
  56. stfd f3,160(r1) # stores f3
  57. lis r31,cheatdata@h #0x8000
  58. lis r20, 0xCC00
  59. lhz r28, 0x4010(r20)
  60. ori r21, r28, 0xFF
  61. sth r21, 0x4010(r20) # disable MP3 memory protection
  62. lis r15, codelist@h
  63. ori r15, r15, codelist@l
  64. ori r7, r31, cheatdata@l # set pointer for storing data (before the codelist)
  65. lis r6,0x8000 # default base address = 0x80000000 (code handler)
  66. mr r16,r6 # default pointer =0x80000000 (code handler)
  67. li r8,0 # code execution status set to true (code handler)
  68. lis r3,0x00D0
  69. ori r3,r3,0xC0DE
  70. lwz r4,0(r15)
  71. cmpw r3,r4
  72. bne- _exitcodehandler
  73. lwz r4,4(r15)
  74. cmpw r3,r4
  75. bne- _exitcodehandler # lf no code list skip code handler
  76. addi r15,r15,8
  77. b _readcodes
  78. _exitcodehandler:
  79. sth r28,0x4010(r20) # restore memory protection value
  80. lfd f2,152(r1) # loads f2
  81. lfd f3,160(r1) # loads f3
  82. lwz r25,168(r1)
  83. mtmsr r25
  84. lwz r0,176(r1)
  85. mtlr r0 # restores lr
  86. lwz r0,12(r1)
  87. mtcr r0 # restores cr
  88. lwz r0,16(r1)
  89. mtctr r0 # restores ctr
  90. lwz r0,20(r1)
  91. mtxer r0 # restores xer
  92. lmw r3,24(r1) # restores r3-r31
  93. lwz r0,8(r1) # loads r0
  94. addi r1,r1,172
  95. isync
  96. blr # return back to game
  97. _readcodes:
  98. lwz r3,0(r15) #load code address
  99. lwz r4,4(r15) #load code value
  100. addi r15,r15,8 #r15 points to next code
  101. andi. r9,r8,1
  102. cmpwi cr7,r9,0 #check code execution status in cr7. eq = true, ne = false
  103. li r9,0 #Clears r9
  104. rlwinm r10,r3,3,29,31 #r10 = extract code type, 3 bits
  105. rlwinm r5,r3,7,29,31 #r5 = extract sub code type 3 bits
  106. andis. r11,r3,0x1000 #test pointer
  107. rlwinm r3,r3,0,7,31 #r3 = extract address in r3 (code type 0/1/2) #0x01FFFFFF
  108. bne +12 #jump lf the pointer is used
  109. rlwinm r12,r6,0,0,6 #lf pointer is not used, address = base address
  110. b +8
  111. mr r12,r16 #lf pointer is used, address = pointer
  112. cmpwi cr4,r5,0 #compares sub code type with 0 in cr4
  113. cmpwi r10,1
  114. blt+ _write #code type 0 : write
  115. beq+ _conditional #code type 1 : conditional
  116. cmpwi r10,3
  117. blt+ _ba_pointer #Code type 2 : base address operation
  118. beq- _repeat_goto #Code type 3 : Repeat & goto
  119. cmpwi r10,5
  120. blt- _operation_rN #Code type 4 : rN Operation
  121. beq+ _compare16_NM_counter #Code type 5 : compare [rN] with [rM]
  122. cmpwi r10,7
  123. blt+ _hook_execute #Code type 6 : hook, execute code
  124. b _terminator_onoff_ #code type 7 : End of code list
  125. _Write_32:
  126. lwz r18, 0(r12) #Load data from registry that will be written to
  127. cmpw r18, r5 #Is data to be written equal to the data in memory
  128. beq+ +72 #Skip if yes
  129. stw r5, 0(r12) #store opcode
  130. li r9, 0 #safe, check r9 if more write_32's are linked.
  131. b +48
  132. _Write_08x:
  133. lbzx r18, r9, r12
  134. rlwinm r0, r4, 0, 24,31 #Clears any other data with r4's byte, for compare
  135. cmpw r0, r18
  136. beq+ +44
  137. stbx r4,r9,r12
  138. b +24
  139. _Write_16x:
  140. lhzx r18, r9, r12
  141. rlwinm r0, r4, 0, 16,31 #Makes sure r4 is just a halfword for compare
  142. cmpw r0, r18
  143. beq+ +20
  144. sthx r4,r9,r12
  145. icbi r9, r12 #branch target. Clears cache. Need dcbf?
  146. sync
  147. isync
  148. blr
  149. #CT0=============================================================================
  150. #write 8bits (0): 00XXXXXX YYYY00ZZ
  151. #write 16bits (1): 02XXXXXX YYYYZZZZ
  152. #write 32bits (2): 04XXXXXX ZZZZZZZZ
  153. #string code (3): 06XXXXXX YYYYYYYY, d1d1d1d1 d2d2d2d2, d3d3d3d3 ....
  154. #Serial Code (4): 08XXXXXX YYYYYYYY TNNNZZZZ VVVVVVVV
  155. _write:
  156. add r12,r12,r3 #address = (ba/po)+(XXXXXX)
  157. cmpwi r5,3
  158. beq- _write_string #r5 == 3, goto string code
  159. bgt- _write_serial #r5 >= 4, goto serial code
  160. bne- cr7,_readcodes #lf code execution set to false skip code
  161. cmpwi cr4,r5,1 #compares sub code type and 1 in cr4
  162. bgt- cr4,_write32 #lf sub code type == 2, goto write32
  163. #lf sub code type = 0 or 1 (8/16bits)
  164. rlwinm r10,r4,16,16,31 #r10 = extract number of times to write (16bits value)
  165. _write816:
  166. beq cr4,+16 #lf r5 = 1 then 16 bits write
  167. bl _Write_08x
  168. addi r9,r9,1
  169. b +12
  170. bl _Write_16x
  171. addi r9, r9, 2
  172. subic. r10,r10,1 #number of times to write -1
  173. bge- _write816
  174. b _readcodes
  175. _write32:
  176. rlwinm r12,r12,0,0,29 #32bits align adress
  177. mr r5, r4
  178. bl _Write_32
  179. b _readcodes
  180. _write_string: #endianess ?
  181. mr r9,r4
  182. mr r22, r4
  183. bne- cr7,_skip_and_align #lf code execution is false, skip string code data
  184. _stb:
  185. subic. r9,r9,1 #r9 -= 1 (and compares r9 with 0)
  186. blt- _skip_and_align #lf r9 < 0 then exit
  187. lbzx r5,r9,r15
  188. mr r4, r5
  189. bl _Write_08x #loop until all the data has been written
  190. mr r4, r22
  191. b _stb
  192. _write_serial:
  193. addi r15,r15,8 #r15 points to the code after the serial code
  194. bne- cr7,_readcodes #lf code execution is false, skip serial code
  195. lwz r5,-8(r15) #load TNNNZZZZ
  196. lwz r11,-4(r15) #r11 = load VVVVVVVV
  197. rlwinm r17,r5,0,16,31 #r17 = ZZZZ
  198. rlwinm r10,r5,16,20,31 #r10 = NNN (# of times to write -1)
  199. rlwinm r5,r5,4,28,31 #r5 = T (0:8bits/1:16bits/2:32bits)
  200. _loop_serial:
  201. cmpwi cr5,r5,1
  202. beq- cr5,+16 #lf 16bits
  203. bgt+ cr5,+20 #lf 32bits
  204. bl _Write_08x
  205. b +40
  206. bl _Write_16x #write serial halfword (CT04,T=1)
  207. b +32
  208. lwzx r18, r9, r12
  209. cmpw r4, r18
  210. beq+ +20
  211. stwx r4,r9,r12 #write serial word (CT04,T>=2)
  212. icbi r9, r12 #Invalidate Icache around real memory offset
  213. sync
  214. isync
  215. add r4,r4,r11 #value +=VVVVVVVV
  216. add r9,r9,r17 #address +=ZZZZ
  217. subic. r10,r10,1
  218. bge+ _loop_serial #loop until all the data has been written
  219. b _readcodes
  220. #CT1=============================================================================
  221. #32bits conditional (0,1,2,3): 20XXXXXX YYYYYYYY
  222. #16bits conditional (4,5,6,7): 28XXXXXX ZZZZYYYY
  223. #PS : 31 bit of address = endlf.
  224. _conditional:
  225. rlwinm. r9,r3,0,31,31 #r10 = (bit31 & 1) (endlf enabled?)
  226. beq +16 #jump lf endlf is not enabled
  227. rlwinm r8,r8,31,1,31 #Endlf (r8>>1)
  228. andi. r9,r8,1 #r9=code execution status
  229. cmpwi cr7,r9,0 #check code execution status in cr7
  230. cmpwi cr5,r5,4 #compares sub code type and 4 in cr5
  231. cmpwi cr3,r10,5 #compares code type and 5 in cr3
  232. rlwimi r8,r8,1,0,30 #r8<<1 and current execution status = old execution status
  233. bne- cr7,_true_end #lf code execution is set to false -> exit
  234. bgt cr3,_addresscheck2 #lf code type==6 -> address check
  235. add r12,r12,r3 #address = (ba/po)+(XXXXXX)
  236. blt cr3,+12 #jump lf code type <5 (==1)
  237. blt cr5,_condition_sub #compare [rN][rM]
  238. b _conditional16_2 #counter compare
  239. bge cr5,_conditional16 #lf sub code type>=4 -> 16 bits conditional
  240. _conditional32:
  241. rlwinm r12,r12,0,0,29 #32bits align
  242. lwz r11,0(r12)
  243. b _condition_sub
  244. _conditional16:
  245. rlwinm r12,r12,0,0,30 #16bits align
  246. lhz r11,0(r12)
  247. _conditional16_2:
  248. nor r9,r4,r4
  249. rlwinm r9,r9,16,16,31 #r9 = extract mask
  250. and r11,r11,r9 #r11 &= r9
  251. rlwinm r4,r4,0,16,31 #r4 = extract data to check against
  252. _condition_sub:
  253. cmpl cr6,r11,r4 #Unsigned compare. r11=data at address, r4=YYYYYYYY
  254. andi. r9,r5,3
  255. beq _skip_NE #lf sub code (type & 3) == 0
  256. cmpwi r9,2
  257. beq _skip_LE #lf sub code (type & 3) == 2
  258. bgt _skip_GE #lf sub code (type & 3) == 3
  259. _skip_EQ:#1
  260. bne- cr6,_true_end #CT21, CT25, CT29 or CT2D (lf !=)
  261. b _skip
  262. _skip_NE:#0
  263. beq- cr6,_true_end #CT20, CT24, CT28 or CT2C (lf==)
  264. b _skip
  265. _skip_LE:#2
  266. bgt- cr6,_true_end #CT22, CT26, CT2A or CT2E (lf r4>[])
  267. b _skip
  268. _skip_GE:#3
  269. blt- cr6,_true_end #CT23, CT27, CT2B or CT2F (lf r4<r4)
  270. _skip:
  271. ori r8,r8,1 #r8|=1 (execution status set to false)
  272. _true_end:
  273. bne+ cr3,_readcodes #lf code type <> 5
  274. blt cr5,_readcodes
  275. lwz r11,-8(r15) #load counter
  276. bne cr7,_clearcounter #lf previous code execution false clear counter
  277. andi. r12,r3,0x8 #else lf clear counter bit not set increase counter
  278. beq _increase_counter
  279. andi. r12,r8,0x1 #else lf.. code result true clear counter
  280. beq _clearcounter
  281. _increase_counter:
  282. addi r12,r11,0x10 #else increase the counter
  283. rlwimi r11,r12,0,12,27 #update counter
  284. b _savecounter
  285. _clearcounter:
  286. rlwinm r11,r11,0,28,11 #clear the counter
  287. _savecounter:
  288. stw r11,-8(r15) #save counter
  289. b _readcodes
  290. #CT2============================================================================
  291. #load base address (0): 40TYZ00N XXXXXXXX = (load/add:T) ba from [(ba/po:Y)+XXXXXXXX(+rN:Z)]
  292. #set base address (1): 42TYZ00N XXXXXXXX = (set/add:T) ba to (ba/po:Y)+XXXXXXXX(+rN:Z)
  293. #store base address (2): 440Y0000 XXXXXXXX = store base address to [(ba/po)+XXXXXXXX]
  294. #set base address to (3): 4600XXXX 00000000 = set base address to code address+XXXXXXXX
  295. #load pointer (4): 48TYZ00N XXXXXXXX = (load/add:T) po from [(ba/po:Y)+XXXXXXXX(+rN:Z)]
  296. #set pointer (5): 4ATYZ00N XXXXXXXX = (set/add:T) po to (ba/po:Y)+XXXXXXXX(+rN:Y)
  297. #store pointer (6): 4C0Y0000 XXXXXXXX = store pointer to [(ba/po)+XXXXXXXX]
  298. #set pointer to (7): 4E00XXXX 00000000 = set pointer to code address+XXXXXXXX
  299. _ba_pointer:
  300. bne- cr7,_readcodes
  301. rlwinm r9,r3,2,26,29 #r9 = extract N, makes N*4
  302. rlwinm r14,r3,16,31,31 #r3 = add ba/po flag bit (Y)
  303. cmpwi cr3,r14,0
  304. cmpwi cr4,r5,4 #cr4 = compare sub code type with 4 (ba/po)
  305. andi. r14,r5,3 #r14 = sub code type and 3
  306. cmpwi cr5,r14,2 #compares sub code type and 2
  307. blt- cr5,_p01
  308. beq- cr5,_p2 #sub code type 2
  309. _p3:
  310. extsh r4,r3
  311. add r4,r4,r15 #r4=XXXXXXXX+r15 (code location in memory)
  312. b _pend
  313. _p01:
  314. rlwinm. r5,r3,20,31,31 #r3 = rN use bit (Z)
  315. beq +12 #flag is not set(=0), address = XXXXXXXX
  316. lwzx r9,r7,r9 #r9 = load register N
  317. add r4,r4,r9 #flag is set (=1), address = XXXXXXXX+rN
  318. beq cr3,+8 #(Y) flag is not set(=0), address = XXXXXXXX (+rN)
  319. add r4,r12,r4 #address = XXXXXXXX (+rN) + (ba/po)
  320. cmpwi cr5,r14,1
  321. beq cr5,+8 #address = (ba/po)+XXXXXXXX(+rN)
  322. lwz r4,0(r4) #address = [(ba/po)+XXXXXXXX(+rN)]
  323. rlwinm. r3,r3,12,31,31 #r5 = add/replace flag (T)
  324. beq _pend #flag is not set (=0), (ba/po)= XXXXXXXX (+rN) + (ba/po)
  325. bge cr4,+12
  326. add r4,r4,r6 #ba += XXXXXXXX (+rN) + (ba/po)
  327. b _pend
  328. add r4,r4,r16 #po += XXXXXXXX (+rN) + (ba/po)
  329. b _pend
  330. _p2:
  331. rlwinm. r5,r3,20,31,31 #r3 = rN use bit (Z)
  332. beq +12 #flag is not set(=0), address = XXXXXXXX
  333. lwzx r9,r7,r9 #r9 = load register N
  334. add r4,r4,r9 #flag is set (=1), address = XXXXXXXX+rN
  335. bge cr4,+12
  336. stwx r6,r12,r4 #[(ba/po)+XXXXXXXX] = base address
  337. b _readcodes
  338. stwx r16,r12,r4 #[(ba/po)+XXXXXXXX] = pointer
  339. b _readcodes
  340. _pend:
  341. bge cr4,+12
  342. mr r6,r4 #store result to base address
  343. b _readcodes
  344. mr r16,r4 #store result to pointer
  345. b _readcodes
  346. #CT3============================================================================
  347. #set repeat (0): 6000ZZZZ 0000000P = set repeat
  348. #execute repeat (1): 62000000 0000000P = execute repeat
  349. #return (2): 64S00000 0000000P = return (lf true/false/always)
  350. #goto (3): 66S0XXXX 00000000 = goto (lf true/false/always)
  351. #gosub (4): 68S0XXXX 0000000P = gosub (lf true/false/always)
  352. _repeat_goto:
  353. rlwinm r9,r4,3,25,28 #r9 = extract P, makes P*8
  354. addi r9,r9,0x40 #offset that points to block P's
  355. cmpwi r5,2 #compares sub code type with 2
  356. blt- _repeat
  357. rlwinm. r11,r3,10,0,1 #extract (S&3)
  358. beq +20 #S=0, skip lf true, don't skip lf false
  359. bgt +8
  360. b _b_bl_blr_nocheck #S=2/3, always skip (code exec status turned to true)
  361. beq- cr7,_readcodes #S=1, skip lf false, don't skip lf true
  362. b _b_bl_blr_nocheck
  363. _b_bl_blr:
  364. bne- cr7,_readcodes #lf code execution set to false skip code
  365. _b_bl_blr_nocheck:
  366. cmpwi r5,3
  367. bgt- _bl #sub code type >=4, bl
  368. beq+ _b #sub code type ==3, b
  369. _blr:
  370. lwzx r15,r7,r9 #loads the next code address
  371. b _readcodes
  372. _bl:
  373. stwx r15,r7,r9 #stores the next code address in block P's address
  374. _b:
  375. extsh r4,r3 #XXXX becomes signed
  376. rlwinm r4,r4,3,9,28
  377. add r15,r15,r4 #next code address +/-=line XXXX
  378. b _readcodes
  379. _repeat:
  380. bne- cr7,_readcodes #lf code execution set to false skip code
  381. add r5,r7,r9 #r5 points to P address
  382. bne- cr4,_execute_repeat #branch lf sub code type == 1
  383. _set_repeat:
  384. rlwinm r4,r3,0,16,31 #r4 = extract NNNNN
  385. stw r15,0(r5) #store current code address to [bP's address]
  386. stw r4,4(r5) #store NNNN to [bP's address+4]
  387. b _readcodes
  388. _execute_repeat:
  389. lwz r9,4(r5) #load NNNN from [M+4]
  390. cmpwi r9,0
  391. beq- _readcodes
  392. subi r9,r9,1
  393. stw r9,4(r5) #saves (NNNN-1) to [bP's address+4]
  394. lwz r15,0(r5) #load next code address from [bP's address]
  395. b _readcodes
  396. #CT4============================================================================
  397. #set/add to rN(0) : 80SY000N XXXXXXXX = rN = (ba/po) + XXXXXXXX
  398. #load rN (1) : 82UY000N XXXXXXXX = rN = [XXXXXXXX] (offset support) (U:8/16/32)
  399. #store rN (2) : 84UYZZZN XXXXXXXX = store rN in [XXXXXXXX] (offset support) (8/16/32)
  400. #operation 1 (3) : 86TY000N XXXXXXXX = operation rN?XXXXXXXX ([rN]?XXXXXXXX)
  401. #operation 2 (4) : 88TY000N 0000000M = operation rN?rM ([rN]?rM, rN?[rM], [rN]?[rM])
  402. #copy1 (5) : 8AYYYYNM XXXXXXXX = copy YYYY bytes from [rN] to ([rM]+)XXXXXXXX
  403. #copy2 (6) : 8CYYYYNM XXXXXXXX = copy YYYY bytes from ([rN]+)XXXXXX to [rM]
  404. #for copy1/copy2, lf register == 0xF, base address is used.
  405. #of course, sub codes types 0/1, 2/3 and 4/5 can be put together lf we need more subtypes.
  406. _operation_rN:
  407. bne- cr7,_readcodes
  408. rlwinm r11,r3,2,26,29 #r11 = extract N, makes N*4
  409. add r26,r7,r11 #1st value address = rN's address
  410. lwz r9,0(r26) #r9 = rN
  411. rlwinm r14,r3,12,30,31 #extracts S, U, T (3bits)
  412. beq- cr4,_op0 #lf sub code type = 0
  413. cmpwi cr4,r5,5
  414. bge- cr4,_op56 #lf sub code type = 5/6
  415. cmpwi cr4,r5,3
  416. bge- cr4,_op34 #lf sub code type = 3/4
  417. cmpwi cr4,r5,1
  418. _op12: #load/store
  419. rlwinm. r5,r3,16,31,31 #+(ba/po) flag : Y
  420. beq +8 #address = XXXXXXXX
  421. add r4,r12,r4
  422. cmpwi cr6,r14,1
  423. bne- cr4,_store
  424. _load:
  425. bgt+ cr6,+24
  426. beq- cr6,+12
  427. lbz r4,0(r4) #load byte at address
  428. b _store_reg
  429. lhz r4,0(r4) #load halfword at address
  430. b _store_reg
  431. lwz r4,0(r4) #load word at address
  432. b _store_reg
  433. _store:
  434. rlwinm r19,r3,28,20,31 #r9=r3 ror 12 (N84UYZZZ)
  435. mr r12, r4
  436. mr r4, r9
  437. mr r5, r9
  438. li r9, 0
  439. _storeloop:
  440. bgt+ cr6,+32
  441. beq- cr6,+16
  442. bl _Write_08x #store byte at address
  443. addi r12,r12,1
  444. b _storeloopend
  445. bl _Write_16x #store byte at address
  446. addi r12,r12,2
  447. b _storeloopend
  448. bl _Write_32
  449. addi r12,r12,4
  450. _storeloopend:
  451. subic. r19,r19,1
  452. bge _storeloop
  453. b _readcodes
  454. _op0:
  455. rlwinm. r5,r3,16,31,31 #+(ba/po) flag : Y
  456. beq +8 #value = XXXXXXXX
  457. add r4,r4,r12 #value = XXXXXXXX+(ba/po)
  458. andi. r5,r14,1 #add flag : S
  459. beq _store_reg #add flag not set (=0), rN=value
  460. add r4,r4,r9 #add flag set (=1), rN=rN+value
  461. b _store_reg
  462. _op34: #operation 1 & 2
  463. rlwinm r10,r3,16,30,31 #extracts Y
  464. rlwinm r14,r4,2,26,29 #r14 = extract M (in r4), makes M*=4
  465. add r19,r7,r14 #2nd value address = rM's address
  466. bne cr4,+8
  467. subi r19,r15,4 #lf CT3, 2nd value address = XXXXXXXX's address
  468. lwz r4,0(r26) #1st value = rN
  469. lwz r9,0(r19) #2nd value = rM/XXXXXXXX
  470. andi. r11,r10,1 #lf [] for 1st value
  471. beq +8
  472. mr r26,r4
  473. andi. r11,r10,2 #lf [] for 2nd value
  474. beq +16
  475. mr r19,r9
  476. bne+ cr4,+8
  477. add r19,r12,r19 #lf CT3, 2nd value address = XXXXXXXX+(ba/op)
  478. rlwinm. r5,r3,12,28,31 #operation # flag : T
  479. cmpwi r5,9
  480. bge _op_float
  481. _operation_bl:
  482. bl _operation_bl_return
  483. _op450:
  484. add r4,r9,r4 #N + M
  485. b _store_reg
  486. _op451:
  487. mullw r4,r9,r4 #N * M
  488. b _store_reg
  489. _op452:
  490. or r4,r9,r4 #N | M
  491. b _store_reg
  492. _op453:
  493. and r4,r9,r4 #N & M
  494. b _store_reg
  495. _op454:
  496. xor r4,r9,r4 #N ^ M
  497. b _store_reg
  498. _op455:
  499. slw r4,r9,r4 #N << M
  500. b _store_reg
  501. _op456:
  502. srw r4,r9,r4 #N >> M
  503. b _store_reg
  504. _op457:
  505. rlwnm r4,r9,r4,0,31 #N rol M
  506. b _store_reg
  507. _op458:
  508. sraw r4,r9,r4 #N asr M
  509. _store_reg:
  510. stw r4,0(r26) #Store result in rN/[rN]
  511. b _readcodes
  512. _op_float:
  513. cmpwi r5,0xA
  514. bgt _readcodes
  515. lfs f2,0(r26) #f2 = load 1st value
  516. lfs f3,0(r19) #f3 = load 2nd value
  517. beq- _op45A
  518. _op459:
  519. fadds f2,f3,f2 #N = N + M (float)
  520. b _store_float
  521. _op45A:
  522. fmuls f2,f3,f2 #N = N * M (float)
  523. _store_float:
  524. stfs f2,0(r26) #Store result in rN/[rN]
  525. b _readcodes
  526. _operation_bl_return:
  527. mflr r10
  528. rlwinm r5,r5,3,25,28 #r5 = T*8
  529. add r10,r10,r5 #jumps to _op5: + r5
  530. lwz r4,0(r26) #load [rN]
  531. lwz r9,0(r19) #2nd value address = rM/XXXXXXXX
  532. mtlr r10
  533. blr
  534. #copy1 (5) : 8AYYYYNM XXXXXXXX = copy YYYY bytes from [rN] to ([rM]+)XXXXXXXX
  535. #copy2 (6) : 8CYYYYNM XXXXXXXX = copy YYYY bytes from ([rN]+)XXXXXX to [rM]
  536. _op56:
  537. bne- cr7,_readcodes #lf code execution set to false skip code
  538. rlwinm r9,r3,24,0,31 #r9=r3 ror 8 (NM8AYYYY, NM8CYYYY)
  539. mr r14,r12 #r14=(ba/po)
  540. bl _load_NM
  541. beq- cr4,+12
  542. add r17,r17,r4 #lf sub code type==0 then source+=XXXXXXXX
  543. b +8
  544. add r9,r9,r4 #lf sub code type==1 then destination+=XXXXXXXX
  545. rlwinm. r4,r3,24,16,31 #Extracts YYYY, compares it with 0
  546. li r5,0
  547. _copy_loop:
  548. beq _readcodes #Loop until all bytes have been copied.
  549. lbzx r10,r5,r17
  550. stbx r10,r5,r9
  551. addi r5,r5,1
  552. cmpw r5,r4
  553. b _copy_loop
  554. #===============================================================================
  555. #This is a routine called by _memory_copy and _compare_NM_16
  556. _load_NM:
  557. cmpwi cr5,r10,4 #compare code type and 4(rn Operations) in cr5
  558. rlwinm r17,r9,6,26,29 #Extracts N*4
  559. cmpwi r17,0x3C
  560. lwzx r17,r7,r17 #Loads rN value in r17
  561. bne +8
  562. mr r17,r14 #lf N==0xF then source address=(ba/po)(+XXXXXXXX, CT5)
  563. beq cr5,+8
  564. lhz r17,0(r17) #...and lf CT5 then N = 16 bits at [XXXXXX+base address]
  565. rlwinm r9,r9,10,26,29 #Extracts M*4
  566. cmpwi r9,0x3C
  567. lwzx r9,r7,r9 #Loads rM value in r9
  568. bne +8
  569. mr r9,r14 #lf M==0xF then dest address=(ba/po)(+XXXXXXXX, CT5)
  570. beq cr5,+8
  571. lhz r9,0(r9) #...and lf CT5 then M = 16 bits at [XXXXXX+base address]
  572. blr
  573. #CT5============================================================================
  574. #16bits conditional (0,1,2,3): A0XXXXXX NM00YYYY (unknown values)
  575. #16bits conditional (4,5,6,7): A8XXXXXX ZZZZYYYY (counter)
  576. #sub codes types 0,1,2,3 compare [rN] with [rM] (both 16bits values)
  577. #lf register == 0xF, the value at [base address+XXXXXXXX] is used.
  578. _compare16_NM_counter:
  579. cmpwi r5,4
  580. bge _compare16_counter
  581. _compare16_NM:
  582. mr r9,r4 #r9=NM00YYYY
  583. add r14,r3,r12 #r14 = XXXXXXXX+(ba/po)
  584. rlwinm r14,r14,0,0,30 #16bits align (base address+XXXXXXXX)
  585. bl _load_NM #r17 = N's value, r9 = M's value
  586. nor r4,r4,r4 #r4=!r4
  587. rlwinm r4,r4,0,16,31 #Extracts !YYYY
  588. and r11,r9,r4 #r3 = (M AND !YYYY)
  589. and r4,r17,r4 #r4 = (N AND !YYYY)
  590. b _conditional
  591. _compare16_counter:
  592. rlwinm r11,r3,28,16,31 #extract counter value from r3 in r11
  593. b _conditional
  594. #===============================================================================
  595. #execute (0) : C0000000 NNNNNNNN = execute. End with 4E800020 00000000.
  596. #hook1 (2) : C4XXXXXX NNNNNNNN = insert instructions at XXXXXX. Same as C2.
  597. #hook2 (3) : C6XXXXXX YYYYYYYY = branch from XXXXXX to YYYYYY
  598. #on/off (6) : CC000000 00000000 = on/off switch
  599. #range check (7) : CE000000 XXXXYYYY = is ba/po in XXXX0000-YYYY0000
  600. _hook_execute:
  601. mr r26,r4 #r26 = 0YYYYYYY
  602. rlwinm r4,r4,3,0,28 #r4 = NNNNNNNN*8 = number of lines (and not number of bytes)
  603. bne- cr4,_hook_addresscheck #lf sub code type != 0
  604. bne- cr7,_skip_and_align
  605. _execute:
  606. mtlr r15
  607. blrl
  608. _skip_and_align:
  609. add r15,r4,r15
  610. addi r15,r15,7
  611. rlwinm r15,r15,0,0,28 #align 64-bit
  612. b _readcodes
  613. _hook_addresscheck:
  614. cmpwi cr4,r5,3
  615. bgt- cr4,_addresscheck1 #lf sub code type ==6 or 7
  616. lis r5,0x4800
  617. add r12,r3,r12
  618. rlwinm r12,r12,0,0,29 #align address
  619. bne- cr4,_hook1 #lf sub code type ==2
  620. _hook2:
  621. bne- cr7,_readcodes
  622. rlwinm r4,r26,0,0,29 #address &=0x01FFFFFC
  623. sub r4,r4,r12 #r4 = to-from
  624. rlwimi r5,r4,0,6,29 #r5 = (r4 AND 0x03FFFFFC) OR 0x48000000
  625. rlwimi r5,r3,0,31,31 #restore lr bit
  626. bl _Write_32
  627. b _readcodes
  628. _hook1:
  629. bne- cr7,_skip_and_align
  630. sub r9,r15,r12 #r9 = to-from
  631. rlwimi r5,r9,0,6,29 #r5 = (r9 AND 0x03FFFFFC) OR 0x48000000
  632. bl _Write_32
  633. addi r12,r12,4
  634. add r11,r15,r4
  635. subi r11,r11,4 #r11 = address of the last word of the hook1 code
  636. sub r9,r12,r11
  637. rlwimi r5,r9,0,6,29 #r5 = (r9 AND 0x03FFFFFC) OR 0x48000000
  638. mr r12, r11
  639. bl _Write_32
  640. b _skip_and_align
  641. _addresscheck1:
  642. cmpwi cr4,r5,6
  643. beq cr4,_onoff
  644. b _conditional
  645. _addresscheck2:
  646. rlwinm r12,r12,16,16,31
  647. rlwinm r4,r26,16,16,31
  648. rlwinm r26,r26,0,16,31
  649. cmpw r12,r4
  650. blt _skip
  651. cmpw r12,r26
  652. bge _skip
  653. b _readcodes
  654. _onoff:
  655. rlwinm r5,r26,31,31,31 #extracts old exec status (x b a)
  656. xori r5,r5,1
  657. andi. r3,r8,1 #extracts current exec status
  658. cmpw r5,r3
  659. beq _onoff_end
  660. rlwimi r26,r8,1,30,30
  661. xori r26,r26,2
  662. rlwinm. r5,r26,31,31,31 #extracts b
  663. beq +8
  664. xori r26,r26,1
  665. stw r26,-4(r15) #updates the code value in the code list
  666. _onoff_end:
  667. rlwimi r8,r26,0,31,31 #current execution status = a
  668. b _readcodes
  669. #===============================================================================
  670. #Full terminator (0) = E0000000 XXXXXXXX = full terminator
  671. #Endlfs/Else (1) = E2T000VV XXXXXXXX = endlfs (+else)
  672. #End code handler = F0000000 00000000
  673. _terminator_onoff_:
  674. cmpwi r11,0 #lf code type = 0xF
  675. beq _notTerminator
  676. cmpwi r5,1
  677. beq _asmTypeba
  678. cmpwi r5,2
  679. beq _asmTypepo
  680. cmpwi r5,3
  681. beq _patchType
  682. b _exitcodehandler
  683. _asmTypeba:
  684. rlwinm r12,r6,0,0,6 # use base address
  685. _asmTypepo:
  686. rlwinm r23,r4,8,24,31 # extract number of half words to XOR
  687. rlwinm r24,r4,24,16,31 # extract XOR checksum
  688. rlwinm r4,r4,0,24,31 # set code value to number of ASM lines only
  689. bne cr7,_goBackToHandler #skip code if code execution is set to false
  690. rlwinm. r25,r23,0,24,24 # check for negative number of half words
  691. mr r26,r12 # copy ba/po address
  692. add r26,r3,r26 # add code offset to ba/po code address
  693. rlwinm r26,r26,0,0,29 # clear last two bits to align address to 32-bit
  694. beq _positiveOffset # if number of half words is negative, extra setup needs to be done
  695. extsb r23,r23
  696. neg r23,r23
  697. mulli r25,r23,2
  698. addi r25,r25,4
  699. subf r26,r25,r26
  700. _positiveOffset:
  701. cmpwi r23,0
  702. beq _endXORLoop
  703. li r25,0
  704. mtctr r23
  705. _XORLoop:
  706. lhz r27,4(r26)
  707. xor r25,r27,r25
  708. addi r26,r26,2
  709. bdnz _XORLoop
  710. _endXORLoop:
  711. cmpw r24,r25
  712. bne _goBackToHandler
  713. b _hook_execute
  714. _patchType:
  715. rlwimi r8,r8,1,0,30 #r8<<1 and current execution status = old execution status
  716. bne cr7,_exitpatch #lf code execution is set to false -> exit
  717. rlwinm. r23,r3,22,0,1
  718. bgt _patchfail
  719. blt _copytopo
  720. _runpatch:
  721. rlwinm r30,r3,0,24,31
  722. mulli r30,r30,2
  723. rlwinm r23,r4,0,0,15
  724. xoris r24,r23,0x8000
  725. cmpwi r24,0
  726. bne- _notincodehandler
  727. ori r23,r23,0x3000
  728. _notincodehandler:
  729. rlwinm r24,r4,16,0,15
  730. mulli r25,r30,4
  731. subf r24,r25,r24
  732. _patchloop:
  733. li r25,0
  734. _patchloopnext:
  735. mulli r26,r25,4
  736. lwzx r27,r15,r26
  737. lwzx r26,r23,r26
  738. addi r25,r25,1
  739. cmplw r23,r24
  740. bgt _failpatchloop
  741. cmpw r25,r30
  742. bgt _foundaddress
  743. cmpw r26,r27
  744. beq _patchloopnext
  745. addi r23,r23,4
  746. b _patchloop
  747. _foundaddress:
  748. lwz r3,-8(r15)
  749. ori r3,r3,0x300
  750. stw r3,-8(r15)
  751. stw r23,-4(r15)
  752. mr r16,r23
  753. b _exitpatch
  754. _failpatchloop:
  755. lwz r3,-8(r15)
  756. ori r3,r3,0x100
  757. stw r3,-8(r15)
  758. _patchfail:
  759. ori r8,r8,1 #r8|=1 (execution status set to false)
  760. b _exitpatch
  761. _copytopo:
  762. mr r16,r4
  763. _exitpatch:
  764. rlwinm r4,r3,0,24,31 # set code to number of lines only
  765. _goBackToHandler:
  766. mulli r4,r4,8
  767. add r15,r4,r15 # skip the lines of the code
  768. b _readcodes
  769. _notTerminator:
  770. _terminator:
  771. bne cr4,+12 #check lf sub code type == 0
  772. li r8,0 #clear whole code execution status lf T=0
  773. b +20
  774. rlwinm. r9,r3,0,27,31 #extract VV
  775. # bne +8 #lf VV!=0
  776. # bne- cr7,+16
  777. rlwinm r5,r3,12,31,31 #extract "else" bit
  778. srw r8,r8,r9 #r8>>VV, meaning endlf VV lfs
  779. rlwinm. r23,r8,31,31,31
  780. bne +8 # execution is false if code execution >>, so don't invert code status
  781. xor r8,r8,r5 #lf 'else' is set then invert current code status
  782. _load_baseaddress:
  783. rlwinm. r5,r4,0,0,15
  784. beq +8
  785. mr r6,r5 #base address = r4
  786. rlwinm. r5,r4,16,0,15
  787. beq +8
  788. mr r16,r5 #pointer = r4
  789. b _readcodes
  790. #===============================================================================
  791. frozenvalue: #frozen value, then LR
  792. .long 0,0
  793. dwordbuffer:
  794. .long 0,0
  795. rem:
  796. .long 0
  797. bpbuffer:
  798. .long 0 #int address to bp on
  799. .long 0 #data address to bp on
  800. .long 0 #alignement check
  801. .long 0 #counter for alignement
  802. regbuffer:
  803. .space 72*4
  804. .align 3
  805. codelist:
  806. .space 2*4
  807. .end