dsp_rom.ds 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. IROM_BASE: equ 0x8000
  2. lri $CR, #0x00ff
  3. lri $SR, #0x2000
  4. si @DMBH, #0x8071
  5. si @DMBL, #0xfeed
  6. mainloop:
  7. clr $ACC1
  8. clr $ACC0
  9. call wait_for_cpu_mbox+#IROM_BASE
  10. ;mmem-addr
  11. param1:
  12. lr $AC1.M, @CMBL
  13. lri $AC0.M, #0xa001
  14. cmp
  15. jnz param2+#IROM_BASE
  16. call wait_for_cpu_mbox+#IROM_BASE
  17. lr $IX0, @CMBH
  18. lr $IX1, @CMBL
  19. jmp mainloop+#IROM_BASE
  20. ;iram-addr
  21. param2:
  22. lri $AC0.M, #0xc002
  23. cmp
  24. jnz param3+#IROM_BASE
  25. call wait_for_cpu_mbox+#IROM_BASE
  26. lr $IX2, @CMBL
  27. jmp mainloop+#IROM_BASE
  28. ;iram-length
  29. param3:
  30. lri $AC0.M, #0xa002
  31. cmp
  32. jnz param4+#IROM_BASE
  33. call wait_for_cpu_mbox+#IROM_BASE
  34. lr $IX3, @CMBL
  35. jmp mainloop+#IROM_BASE
  36. ;dram-length
  37. param4:
  38. lri $AC0.M, #0xb002
  39. cmp
  40. jnz param5+#IROM_BASE
  41. call wait_for_cpu_mbox+#IROM_BASE
  42. lr $AX0.L, @CMBL
  43. jmp mainloop+#IROM_BASE
  44. ;iram-start-addr
  45. param5:
  46. lri $AC0.M, #0xd001
  47. cmp
  48. jnz mainloop+#IROM_BASE
  49. call wait_for_cpu_mbox+#IROM_BASE
  50. lr $AR0, @CMBL
  51. ; skip the branch of bootucode that uses the AX registers
  52. jmp bootucode_ix+#IROM_BASE
  53. wait_dma:
  54. lrs $AC0.M, @DSCR
  55. andcf $AC0.M, #0x0004
  56. jlz wait_dma+#IROM_BASE
  57. ret
  58. WARNPC 0x78
  59. ORG 0x78
  60. ; called by GBA ucode
  61. wait_for_cpu_mbox:
  62. lrs $AC0.M, @CMBH
  63. andcf $AC0.M, #0x8000
  64. jlnz wait_for_cpu_mbox+#IROM_BASE
  65. ret
  66. WARNPC 0x7e
  67. ORG 0x7e
  68. ; called by GBA ucode
  69. wait_for_dsp_mbox:
  70. lrs $AC0.M, @DMBH
  71. andcf $AC0.M, #0x8000
  72. jlz wait_for_dsp_mbox+#IROM_BASE
  73. ret
  74. WARNPC 0x8b
  75. ORG 0x8b
  76. ; called by GBA ucode
  77. dram_to_cpu:
  78. sr @DSMAH, $AX0.H
  79. sr @DSMAL, $AX0.L
  80. si @DSCR, #0x1
  81. sr @DSPA, $AX1.H
  82. sr @DSBL, $AX1.L
  83. call wait_dma+#IROM_BASE
  84. ret
  85. WARNPC 0xb5
  86. ORG 0xb5
  87. bootucode:
  88. set16
  89. clr $ACC0
  90. mrr $AC0.M, $AX1.L
  91. andi $AC0.M, #0xffff
  92. jz bootucode_ix+#IROM_BASE
  93. WARNPC 0xbc
  94. ORG 0xbc
  95. ; called by GBA ucode
  96. bootucode_ax:
  97. lris $AC0.M, #0
  98. srs @DSCR, $AC0.M
  99. sr @DSMAH, $AX0.H
  100. sr @DSMAL, $AX0.L
  101. sr @DSPA, $AX1.H
  102. sr @DSBL, $AX1.L
  103. call wait_dma+#IROM_BASE
  104. bootucode_ix:
  105. mrr $AC0.M, $IX3
  106. andi $AC0.M, #0xffff
  107. jz bootucode_epilogue+#IROM_BASE
  108. lris $AC0.M, #0x2
  109. srs @DSCR, $AC0.M
  110. sr @DSMAH, $IX0
  111. sr @DSMAL, $IX1
  112. sr @DSPA, $IX2
  113. sr @DSBL, $IX3
  114. call wait_dma+#IROM_BASE
  115. bootucode_epilogue:
  116. clr $ACC1
  117. lr $AC1.M, @DSBL
  118. jmpr $AR0
  119. WARNPC 0xe7
  120. ORG 0xe7
  121. ; Args:
  122. ; AR0 points to the 32 input 1 samples (s16)
  123. ; AR1 points to the volume data (init1, delta1, init2, delta2)
  124. ; AR2 points to the already mixed samples for output 1 (s32)
  125. ; AR3 points to where the output 1 should be stored (s32)
  126. ; IX0 points to the 32 input 2 samples (s16)
  127. ; IX1 points to where the output 2 should be stored (s32)
  128. ;
  129. ; Returns:
  130. ; AX0.L is the value of the last sample from input 1
  131. ; AX1.H is the value of the last sample from input 2
  132. ;
  133. ; for i = 0..31:
  134. ; ar3[i] = ((ar2[i] << 16) + ar0[i] * ar1[0]) >> 16
  135. ; for i = 0..31:
  136. ; ix1[i] = ((ix1[i] << 16) + ix0[i] * ar1[2]) >> 16
  137. ; ax0.l = ar0[31] * ar1[0]
  138. ; ax1.h = ix0[31] * ar1[2]
  139. mix_two_add:
  140. call mix_add+#IROM_BASE
  141. mrr $AR0, $IX0
  142. mrr $AR2, $IX1
  143. mrr $AR3, $IX1
  144. mrr $IX0, $AX0.L
  145. call mix_add+#IROM_BASE
  146. mrr $AX1.H, $AX0.L
  147. mrr $AX0.L, $IX0
  148. ret
  149. WARNPC 0x1f4
  150. ORG 0x1f4
  151. ; used by GBA ucode for joyboot length and is the end of some mixing function
  152. ; (for an example of hitting the full function, try running the main menu of
  153. ; Metroid Prime using the Nintendo DSP ROM).
  154. sub_81f4:
  155. asr16'ir $ACC1 : $AR1
  156. clr's $ACC0 : @$AR3, $AC1.M ; AC1.M is always #0x0 here.
  157. ; necessary both to match register state of official ROM, and for the
  158. ; following mul. could also be mrr $AX1.H, $AC0.M (before clearing ACC0).
  159. mrr $AX1.H, $AX0.H
  160. ; make the product register match.
  161. mul's $AX1.L, $AX1.H : @$AR3, $AC1.L
  162. ret
  163. WARNPC 0x1f9
  164. ORG 0x1f9
  165. ; Args:
  166. ; AR0 points to the 32 input samples (s16)
  167. ; AR1 points to the volume data (init, delta)
  168. ; AR2 points to the already mixed samples (s32)
  169. ; AR3 points to where the output should be stored (s32)
  170. ;
  171. ; Returns:
  172. ; AX0.L is the value of the last sample
  173. ; AX1.H is the first address after the output
  174. ;
  175. ; for i = 0..31:
  176. ; ar3[i] = ((ar2[i] << 16) + ar0[i] * ar1[0]) >> 16
  177. ; ax0.l = ar0[31] * ar1[0]
  178. ; ax1.h = ar3 + 32 // assuming ar3 is a s32 pointer
  179. mix_add:
  180. lrri $AX1.L, @$AR1
  181. iar $AR1
  182. bloopi #32, ____mix_add_end_loop+#IROM_BASE
  183. lrri $AC0.M, @$AR2
  184. lrri $AC0.L, @$AR2
  185. lsl16 $ACC0
  186. lrri $AX0.H, @$AR0
  187. mulx $AX0.H, $AX1.L
  188. addp $ACC0
  189. asr16 $ACC0
  190. srri @$AR3, $AC0.M
  191. ____mix_add_end_loop:
  192. srri @$AR3, $AC0.L
  193. movp $ACC0
  194. mrr $AX0.L, $AC0.M
  195. mrr $AX1.H, $AR3
  196. ret
  197. WARNPC 0x282
  198. ORG 0x282
  199. ; for i = 0..31:
  200. ; ar3[i] = ar1[0] + i * ar1[1]
  201. ; ar2[i] = ((ar2[i] << 16) + ar0[i] * ar3[i]) >> 16
  202. ; ar3[i+32] = ar1[2] + i * ar1[3]
  203. ; ix1[i] = ((ix1[i] << 16) + ix0[i] * ar3[i+32]) >> 16
  204. ; ax0.l = ar0[31] * ar3[31]
  205. ; ax1.h = ix0[31] * ar3[63]
  206. mix_two_add_ramp:
  207. call mix_add_ramp+#IROM_BASE
  208. mrr $AR0, $IX0
  209. mrr $AR2, $IX1
  210. mrr $IX1, $AX0.L
  211. call mix_add_ramp+#IROM_BASE
  212. mrr $AX1.H, $AX0.L
  213. mrr $AX0.L, $IX1
  214. ret
  215. WARNPC 0x458
  216. ORG 0x458
  217. ; used by GBA ucode for joyboot length
  218. sub_8458:
  219. ; AC1.L after = AC1.M before + 7. this looks really stupid, but matches
  220. ; captured traces and seems to work.
  221. addis $AC1.M, #0x7
  222. asr16 $ACC1
  223. srri @$AR3, $AC1.M ; or just #0x0.
  224. srri @$AR3, $AC1.L
  225. ret
  226. WARNPC 0x45d
  227. ORG 0x45d
  228. ; for i = 0..31:
  229. ; ar3[i] = ar1[0] + i * ar1[1]
  230. ; ar2[i] = ((ar2[i] << 16) + ar0[i] * ar3[i]) >> 16
  231. ; ax0.l = ar0[31] * ar3[31]
  232. mix_add_ramp:
  233. clr $ACC0
  234. clr $ACC1
  235. lrri $AC0.L, @$AR1
  236. lrrd $AC1.L, @$AR1
  237. mrr $IX2, $AR3
  238. bloopi #32, ____mix_add_ramp_end_ramp+#IROM_BASE
  239. srri @$AR3, $AC0.L
  240. ____mix_add_ramp_end_ramp:
  241. add $ACC0, $ACC1
  242. srri @$AR1, $AC0.L
  243. iar $AR1
  244. mrr $IX3, $AR1
  245. mrr $AR1, $IX2
  246. mrr $AR3, $AR2
  247. bloopi #32, ____mix_add_ramp_end_loop+#IROM_BASE
  248. lrri $AC0.M, @$AR2
  249. lrri $AC0.L, @$AR2
  250. lsl16 $ACC0
  251. lrri $AX0.H, @$AR0
  252. lrri $AX1.L, @$AR1
  253. mulx $AX0.H, $AX1.L
  254. addp $ACC0
  255. asr16 $ACC0
  256. srri @$AR3, $AC0.M
  257. ____mix_add_ramp_end_loop:
  258. srri @$AR3, $AC0.L
  259. movp $ACC0
  260. mrr $AX0.L, $AC0.M
  261. mrr $AR1, $IX3
  262. mrr $AR3, $IX2
  263. ret
  264. WARNPC 0x723
  265. ORG 0x723
  266. ; called by GBA ucode
  267. sub_8723:
  268. ; in GBA-HLE, the nonce challenge is XOR'd with 0x6f646573, which happens
  269. ; to match the values of the AX1.H register across these two calls.
  270. xorr $AC1.M, $AX1.H
  271. ; the value of @AR2 is always the same as AC1.M after
  272. srrd @$AR2, $AC1.M
  273. ret
  274. WARNPC 0x809
  275. ORG 0x809
  276. ; called by GBA ucode
  277. sub_8809:
  278. ; AR2 is the only addressing register that corresponds to the dmem writes
  279. ; could be AC1.L or AX0.L in the second call, but can't be AX0.L in the
  280. ; third call.
  281. srr @$AR2, $AC1.L
  282. ; AC1.M after calling always look like either AC1.M | AC0.M or
  283. ; AC1.M | AX0.H. TODO: Why pick AX0.H?
  284. orr $AC1.M, $AX0.H
  285. ; the second dmem write is incremented only in calls #3A and #3B. There,
  286. ; IX2 is the only register set to 1, and it's specifically set to 1 in the
  287. ; ucode. It's set to 0 in the first two calls.
  288. addarn $AR2, $IX2
  289. ; obvious
  290. srri @$AR2, $AC1.M
  291. ret
  292. WARNPC 0x8e5
  293. ORG 0x8e5
  294. ; used by GBA ucode for challenge nonce, logo palette/speed, and joyboot length
  295. sub_88e5:
  296. dar $AR1 ; always gets decremented, no effect on rest of function
  297. lrri $AC1.M, @$AR2
  298. lrrd $AC1.L, @$AR2
  299. add $ACC0, $ACC1 ; signed addition
  300. orr $AC0.M, $AX0.H
  301. srri @$AR2, $AC0.M
  302. srr @$AR2, $AC0.L
  303. ret
  304. WARNPC 0x1000
  305. ORG 0x1000