No Description

main_mixer.s 48KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411
  1. @ created by ~ipatix~
  2. @ revision 2.1
  3. /* globals */
  4. .global main_mixer
  5. .global mixer_size
  6. .set mixer_size, (main_mixer_end - main_mixer) / 4
  7. /* game code definitions */
  8. .equ GAME_BPED, 0
  9. .equ GAME_BPEE, 1
  10. .equ GAME_BPRE, 2
  11. .equ GAME_KWJ6, 3
  12. .equ GAME_AE7E, 4
  13. .equ GAME_BPRD, 5
  14. .equ GAME_SOTS, 6
  15. /* SELECT USED GAME HERE */
  16. .equ USED_GAME, GAME_SOTS
  17. .equ FRAME_LENGTH_5734, 0x60
  18. .equ FRAME_LENGTH_7884, 0x84 @ THIS MODE IS NOT SUPPORTED BY THIS ENGINE BECAUSE IT DOESN'T USE AN 8 ALIGNED BUFFER LENGTH
  19. .equ FRAME_LENGTH_10512, 0xB0
  20. .equ FRAME_LENGTH_13379, 0xE0 @ DEFAULT
  21. .equ FRAME_LENGTH_15768, 0x108
  22. .equ FRAME_LENGTH_18157, 0x130
  23. .equ FRAME_LENGTH_21024, 0x160
  24. .equ FRAME_LENGTH_26758, 0x1C0
  25. .equ FRAME_LENGTH_31536, 0x210
  26. .equ FRAME_LENGTH_36314, 0x260
  27. .equ FRAME_LENGTH_40137, 0x2A0
  28. .equ FRAME_LENGTH_42048, 0x2C0
  29. .equ DECODER_BUFFER_BPE, 0x03001300
  30. .equ DECODER_BUFFER_BPR, 0x03002088
  31. .equ DECODER_BUFFER_KWJ, 0x03005800
  32. .equ BUFFER_IRAM_BPE, 0x03001AA8
  33. .equ BUFFER_IRAM_BPR, 0x030028E0
  34. .equ BUFFER_IRAM_SOTS, 0x030028A0
  35. .equ BUFFER_IRAM_KWJ, 0x03005840
  36. .equ BUFFER_IRAM_AE7, 0x03006D60
  37. /* stack variables */
  38. .equ ARG_FRAME_LENGTH, 0x0 @ TODO actually use this variable
  39. .equ ARG_REMAIN_CHN, 0x4 @ This is the channel count variable
  40. .equ ARG_BUFFER_POS, 0x8 @ stores the current output buffer pointer
  41. .equ ARG_LOOP_START_POS, 0xC @ stores wave loop start position in channel loop
  42. .equ ARG_LOOP_LENGTH, 0x10 @ '' '' '' end position
  43. .equ ARG_BUFFER_POS_INDEX_HINT, 0x14
  44. .equ ARG_PCM_STRUCT, 0x18 @ pointer to engine the main work area
  45. /* channel struct */
  46. .equ CHN_STATUS, 0x0 @ [byte] channel status bitfield
  47. .equ CHN_MODE, 0x1 @ [byte] channel mode bitfield
  48. .equ CHN_VOL_1, 0x2 @ [byte] volume right
  49. .equ CHN_VOL_2, 0x3 @ [byte] volume left
  50. .equ CHN_ATTACK, 0x4 @ [byte] wave attack summand
  51. .equ CHN_DECAY, 0x5 @ [byte] wave decay factor
  52. .equ CHN_SUSTAIN, 0x6 @ [byte] wave sustain level
  53. .equ CHN_RELEASE, 0x7 @ [byte] wave release factor
  54. .equ CHN_ADSR_LEVEL, 0x9 @ [byte] current envelope level
  55. .equ CHN_FINAL_VOL_1, 0xA @ [byte] not used anymore!
  56. .equ CHN_FINAL_VOL_2, 0xB @ [byte] not used anymore!
  57. .equ CHN_ECHO_VOL, 0xC @ [byte] pseudo echo volume
  58. .equ CHN_ECHO_REMAIN, 0xD @ [byte] pseudo echo length
  59. .equ CHN_SAMPLE_COUNTDOWN, 0x18 @ [word] sample countdown in mixing loop
  60. .equ CHN_FINE_POSITION, 0x1C @ [word] inter sample position (23 bits)
  61. .equ CHN_FREQUENCY, 0x20 @ [word] sample rate (in Hz)
  62. .equ CHN_WAVE_OFFSET, 0x24 @ [word] wave header pointer
  63. .equ CHN_POSITION_ABS, 0x28 @ [word] points to the current position in the wave data (relative offset for compressed samples)
  64. .equ CHN_BLOCK_COUNT, 0x3C @ [word] only used for compressed samples: contains the value of the block that is currently decoded
  65. /* wave header struct */
  66. .equ WAVE_LOOP_FLAG, 0x3 @ [byte] 0x0 = oneshot; 0x40 = looped
  67. .equ WAVE_FREQ, 0x4 @ [word] pitch adjustment value = mid-C samplerate * 1024
  68. .equ WAVE_LOOP_START, 0x8 @ [word] loop start position
  69. .equ WAVE_LENGTH, 0xC @ [word] loop end / wave end position
  70. .equ WAVE_DATA, 0x10 @ [byte array] actual wave data
  71. /* pulse wave synth configuration offset */
  72. .equ SYNTH_BASE_WAVE_DUTY, 0x1 @ [byte]
  73. .equ SYNTH_WIDTH_CHANGE_1, 0x2 @ [byte]
  74. .equ SYNTH_MOD_AMOUNT, 0x3 @ [byte]
  75. .equ SYNTH_WIDTH_CHANGE_2, 0x4 @ [byte]
  76. /* CHN_STATUS flags - 0x0 = OFF */
  77. .equ FLAG_CHN_INIT, 0x80 @ [bit] write this value to init a channel
  78. .equ FLAG_CHN_RELEASE, 0x40 @ [bit] write this value to release (fade out) the channel
  79. .equ FLAG_CHN_COMP, 0x20 @ [bit] is wave being played compressed (yes/no)
  80. .equ FLAG_CHN_LOOP, 0x10 @ [bit] loop (yes/no)
  81. .equ FLAG_CHN_ECHO, 0x4 @ [bit] echo phase
  82. .equ FLAG_CHN_ATTACK, 0x3 @ [bit] attack phase
  83. .equ FLAG_CHN_DECAY, 0x2 @ [bit] decay phase
  84. .equ FLAG_CHN_SUSTAIN, 0x1 @ [bit] sustain phase
  85. /* CHN_MODE flags */
  86. .equ MODE_FIXED_FREQ, 0x8 @ [bit] set to disable resampling (i.e. playback with output rate)
  87. .equ MODE_REVERSE, 0x10 @ [bit] set to reverse sample playback
  88. .equ MODE_COMP, 0x30 @ [bit] is wave being played compressed or reversed (TODO: rename flag)
  89. .equ MODE_SYNTH, 0x40 @ [bit] READ ONLY, indicates synthzied output
  90. /* variables of the engine work area */
  91. .equ VAR_REVERB, 0x5 @ [byte] 0-127 = reverb level
  92. .equ VAR_MAX_CHN, 0x6 @ [byte] maximum channels to process
  93. .equ VAR_MASTER_VOL, 0x7 @ [byte] PCM master volume
  94. .equ VAR_DEF_PITCH_FAC, 0x18 @ [word] this value get's multiplied with the samplerate for the inter sample distance
  95. .equ VAR_FIRST_CHN, 0x50 @ [CHN struct] relative offset to channel array
  96. /* just some more defines */
  97. .equ REG_DMA3_SRC, 0x040000D4
  98. .equ ARM_OP_LEN, 0x4
  99. @########### GAME CONFIGS ##############
  100. @ add the game's name above to the ASM .equ-s before creating new configs
  101. @#######################################
  102. @*********** IF GERMAN POKEMON EMERALD
  103. .if USED_GAME==GAME_BPED
  104. .equ hq_buffer_ptr, BUFFER_IRAM_BPE
  105. .equ decoder_buffer_target, DECODER_BUFFER_BPE
  106. .equ POKE_INIT, 1
  107. .equ DMA_FIX, 1
  108. .equ ENABLE_DECOMPRESSION, 1
  109. .endif
  110. @*********** IF ENGLISH POKEMON FIRE RED
  111. .if USED_GAME==GAME_BPRD
  112. .equ hq_buffer_ptr, 0x03002830
  113. .equ decoder_buffer_target, DECODER_BUFFER_BPR
  114. .equ POKE_INIT, 1
  115. .equ DMA_FIX, 1
  116. .equ ENABLE_DECOMPRESSION, 1
  117. .endif
  118. @*********** IF ENGLISH POKEMON EMERALD
  119. .if USED_GAME==GAME_BPEE
  120. .equ hq_buffer_ptr, BUFFER_IRAM_BPE
  121. .equ decoder_buffer_target, DECODER_BUFFER_BPE
  122. .equ POKE_INIT, 1
  123. .equ DMA_FIX, 1
  124. .equ ENABLE_DECOMPRESSION, 1
  125. .endif
  126. @*********** IF ENGLISH POKEMON FIRE RED
  127. .if USED_GAME==GAME_BPRE
  128. .equ hq_buffer_ptr, BUFFER_IRAM_BPR
  129. .equ decoder_buffer_target, DECODER_BUFFER_BPR
  130. .equ POKE_INIT, 1
  131. .equ DMA_FIX, 1
  132. .equ ENABLE_DECOMPRESSION, 1
  133. .endif
  134. @*********** IF POKEMON SOTS
  135. .if USED_GAME==GAME_SOTS
  136. .equ hq_buffer_ptr, BUFFER_IRAM_SOTS
  137. .equ decoder_buffer_target, DECODER_BUFFER_BPR
  138. .equ POKE_INIT, 1
  139. .equ DMA_FIX, 1
  140. .equ ENABLE_DECOMPRESSION, 1
  141. .endif
  142. @*********** IF KAWAs JUKEBOX 2006
  143. .if USED_GAME==GAME_KWJ6
  144. .equ hq_buffer_ptr, BUFFER_IRAM_KWJ
  145. .equ decoder_buffer_target, DECODER_BUFFER_KWJ
  146. .equ POKE_INIT, 0
  147. .equ DMA_FIX, 0
  148. .equ ENABLE_DECOMPRESSION, 0
  149. .endif
  150. @*********** IF US FIRE EMBLEM
  151. .if USED_GAME==GAME_AE7E
  152. .equ hq_buffer_ptr, BUFFER_IRAM_AE7
  153. .equ POKE_INIT, 0
  154. .equ DMA_FIX, 0
  155. .equ ENABLE_DECOMPRESSION, 0
  156. .endif
  157. @***********
  158. .thumb
  159. .align 2
  160. /*
  161. * main_mixer initial registers:
  162. * R0 = PCM Area
  163. * R1 = unknown, independant
  164. * R2 = unknown, independant
  165. * R3 = unknown, independant
  166. * R4 = if == 2 then this is last frame in out buffer
  167. * R5 = current output buffer position
  168. * R6 = buffer spaceing = 0x630
  169. * R7 = unknown, independent
  170. * R8 = samples per buffer
  171. * R9 = unknown, independent
  172. * R10 = unknown, independent
  173. * R11 = unknown, independent
  174. * R12 = unknown, independent
  175. */
  176. main_mixer:
  177. /* load Reverb level and check if we need to apply it */
  178. STR R4, [SP, #ARG_BUFFER_POS_INDEX_HINT]
  179. ADR R2, is_buffer_init
  180. LDRB R0, [R2]
  181. CMP R0, #0
  182. BNE C_setup_channel_state_loop
  183. /* if buffer not initialized, clear first */
  184. LDR R3, hq_buffer
  185. MOV R1, R8
  186. MOV R4, #0
  187. MOV R5, #0
  188. MOV R6, #0
  189. MOV R7, #0
  190. LSR R1, #3
  191. BCC C_clear_buffer_align_8
  192. STMIA R3!, {R4, R5, R6, R7}
  193. C_clear_buffer_align_8:
  194. LSR R1, #1
  195. BCC C_clear_buffer_align_16
  196. STMIA R3!, {R4, R5, R6, R7}
  197. STMIA R3!, {R4, R5, R6, R7}
  198. C_clear_buffer_align_16:
  199. STMIA R3!, {R4, R5, R6, R7}
  200. STMIA R3!, {R4, R5, R6, R7}
  201. STMIA R3!, {R4, R5, R6, R7}
  202. STMIA R3!, {R4, R5, R6, R7}
  203. SUB R1, #1
  204. BGT C_clear_buffer_align_16
  205. MOV R1, #1
  206. STRB R1, [R2]
  207. B C_setup_channel_state_loop
  208. .align 2
  209. is_buffer_init:
  210. .byte 0x0
  211. .align 1
  212. C_setup_channel_state_loop:
  213. /*
  214. * okay, before the actual mixing starts
  215. * the volume and envelope calculation takes place
  216. */
  217. MOV R4, R8 @ R4 = buffer length
  218. /*
  219. * this stroes the buffer length to a backup location
  220. */
  221. STR R4, [SP, #ARG_FRAME_LENGTH]
  222. /* init channel loop */
  223. LDR R4, [SP, #ARG_PCM_STRUCT] @ R4 = main work area pointer
  224. LDR R0, [R4, #VAR_DEF_PITCH_FAC] @ R0 = samplingrate pitch factor
  225. MOV R12, R0
  226. LDRB R0, [R4, #VAR_MAX_CHN]
  227. ADD R4, #VAR_FIRST_CHN @ R4 = Base channel Offset (Channel #0)
  228. C_channel_state_loop:
  229. /* this is the main channel processing loop */
  230. STR R0, [SP, #ARG_REMAIN_CHN]
  231. LDR R3, [R4, #CHN_WAVE_OFFSET]
  232. LDRB R6, [R4, #CHN_STATUS] @ R6 will hold the channel status
  233. MOVS R0, #0xC7 @ check if any of the channel status flags is set
  234. TST R0, R6 @ check if none of the flags is set
  235. BEQ C_skip_channel
  236. /* check channel flags */
  237. LSL R0, R6, #25 @ shift over the FLAG_CHN_INIT to CARRY
  238. BCC C_adsr_echo_check @ continue with normal channel procedure
  239. /* check leftmost bit */
  240. BMI C_stop_channel @ FLAG_CHN_INIT | FLAG_CHN_RELEASE -> stop directly
  241. /* channel init procedure */
  242. MOVS R6, #FLAG_CHN_ATTACK
  243. MOVS R0, R3 @ R0 = CHN_WAVE_OFFSET
  244. ADD R0, #WAVE_DATA @ R0 = wave data offset
  245. /* Pokemon games seem to init channels differently than other m4a games */
  246. .if POKE_INIT==0
  247. STR R0, [R4, #CHN_POSITION_ABS]
  248. LDR R0, [R3, #WAVE_LENGTH]
  249. STR R0, [R4, #CHN_SAMPLE_COUNTDOWN]
  250. .else
  251. LDR R1, [R4, #CHN_SAMPLE_COUNTDOWN]
  252. ADD R0, R0, R1
  253. STR R0, [R4, #CHN_POSITION_ABS]
  254. LDR R0, [R3, #WAVE_LENGTH]
  255. SUB R0, R0, R1
  256. STR R0, [R4, #CHN_SAMPLE_COUNTDOWN]
  257. .endif
  258. MOVS R5, #0 @ initial envelope = #0
  259. STRB R5, [R4, #CHN_ADSR_LEVEL]
  260. STR R5, [R4, #CHN_FINE_POSITION]
  261. LDRB R2, [R3, #WAVE_LOOP_FLAG]
  262. LSR R0, R2, #6
  263. BEQ C_adsr_attack
  264. /* loop enabled here */
  265. MOVS R0, #FLAG_CHN_LOOP
  266. ORR R6, R0
  267. B C_adsr_attack
  268. C_adsr_echo_check:
  269. /* this is the normal ADSR procedure without init */
  270. LDRB R5, [R4, #CHN_ADSR_LEVEL]
  271. LSL R0, R6, #29 @ FLAG_CHN_ECHO --> bit 31 (sign bit)
  272. BPL C_adsr_release_check
  273. /* pseudo echo handler */
  274. LDRB R0, [R4, #CHN_ECHO_REMAIN]
  275. SUB R0, #1
  276. STRB R0, [R4, #CHN_ECHO_REMAIN]
  277. BHI C_channel_vol_calc @ continue normal if channel is still on
  278. C_stop_channel:
  279. MOVS R0, #0
  280. STRB R0, [R4, #CHN_STATUS]
  281. C_skip_channel:
  282. /* go to end of the channel loop */
  283. B C_end_channel_state_loop
  284. C_adsr_release_check:
  285. LSL R0, R6, #25 @ FLAG_CHN_RELEASE --> bit 31 (sign bit)
  286. BPL C_adsr_decay_check
  287. /* release handler */
  288. LDRB R0, [R4, #CHN_RELEASE]
  289. @SUB R0, #0xFF @ linear decay; TODO make option for triggering it
  290. @SUB R0, #1
  291. @ADD R5, R5, R0
  292. MUL R5, R5, R0
  293. LSR R5, #8
  294. BLE C_adsr_released
  295. /* pseudo echo init handler */
  296. LDRB R0, [R4, #CHN_ECHO_VOL]
  297. CMP R5, R0
  298. BHI C_channel_vol_calc
  299. C_adsr_released:
  300. /* if volume released to #0 */
  301. LDRB R5, [R4, #CHN_ECHO_VOL]
  302. CMP R5, #0
  303. BEQ C_stop_channel
  304. /* pseudo echo volume handler */
  305. MOVS R0, #FLAG_CHN_ECHO
  306. ORR R6, R0 @ set the echo flag
  307. B C_adsr_save_and_finalize
  308. C_adsr_decay_check:
  309. /* check if decay is active */
  310. MOVS R2, #(FLAG_CHN_DECAY+FLAG_CHN_SUSTAIN)
  311. AND R2, R6
  312. CMP R2, #FLAG_CHN_DECAY
  313. BNE C_adsr_attack_check @ decay not active yet
  314. /* decay handler */
  315. LDRB R0, [R4, #CHN_DECAY]
  316. MUL R5, R5, R0
  317. LSR R5, R5, #8
  318. LDRB R0, [R4, #CHN_SUSTAIN]
  319. CMP R5, R0
  320. BHI C_channel_vol_calc @ sample didn't decay yet
  321. /* sustain handler */
  322. MOVS R5, R0 @ current level = sustain level
  323. BEQ C_adsr_released @ sustain level #0 --> branch
  324. /* step to next phase otherweise */
  325. B C_adsr_next_state
  326. C_adsr_attack_check:
  327. /* attack handler */
  328. CMP R2, #FLAG_CHN_ATTACK
  329. BNE C_channel_vol_calc @ if it isn't in attack attack phase, it has to be in sustain (keep vol) --> branch
  330. C_adsr_attack:
  331. /* apply attack summand */
  332. LDRB R0, [R4, #CHN_ATTACK]
  333. ADD R5, R0
  334. CMP R5, #0xFF
  335. BLO C_adsr_save_and_finalize
  336. /* cap attack at 0xFF */
  337. MOVS R5, #0xFF
  338. C_adsr_next_state:
  339. /* switch to next adsr phase */
  340. SUB R6, #1
  341. C_adsr_save_and_finalize:
  342. /* store channel status */
  343. STRB R6, [R4, #CHN_STATUS]
  344. C_channel_vol_calc:
  345. /* store the calculated ADSR level */
  346. STRB R5, [R4, #CHN_ADSR_LEVEL]
  347. /* apply master volume */
  348. LDR R0, [SP, #ARG_PCM_STRUCT]
  349. LDRB R0, [R0, #VAR_MASTER_VOL]
  350. ADD R0, #1
  351. MUL R5, R0
  352. /* left side volume */
  353. LDRB R0, [R4, #CHN_VOL_2]
  354. MUL R0, R5
  355. LSR R0, #13
  356. MOV R10, R0 @ R10 = left volume
  357. /* right side volume */
  358. LDRB R0, [R4, #CHN_VOL_1]
  359. MUL R0, R5
  360. LSR R0, #13
  361. MOV R11, R0 @ R11 = right volume
  362. /*
  363. * Now we get closer to actual mixing:
  364. * For looped samples some additional operations are required
  365. */
  366. MOVS R0, #FLAG_CHN_LOOP
  367. AND R0, R6
  368. BEQ C_skip_sample_loop_setup
  369. /* loop setup handler */
  370. ADD R3, #WAVE_LOOP_START
  371. LDMIA R3!, {R0, R1} @ R0 = loop start, R1 = loop end
  372. ADD R3, R0 @ R3 = loop start position (absolute)
  373. STR R3, [SP, #ARG_LOOP_START_POS]
  374. SUB R0, R1, R0
  375. C_skip_sample_loop_setup:
  376. /* do the rest of the setup */
  377. STR R0, [SP, #ARG_LOOP_LENGTH] @ if loop is off --> R0 = 0x0
  378. LDR R5, hq_buffer
  379. LDR R2, [R4, #CHN_SAMPLE_COUNTDOWN]
  380. LDR R3, [R4, #CHN_POSITION_ABS]
  381. LDRB R0, [R4, #CHN_MODE]
  382. ADR R1, C_mixing_setup
  383. BX R1
  384. .align 2
  385. hq_buffer:
  386. .word hq_buffer_ptr
  387. .arm
  388. .align 2
  389. C_mixing_setup:
  390. /* frequency and mixing loading routine */
  391. LDR R8, [SP, #ARG_FRAME_LENGTH]
  392. ORRS R11, R11, R10, LSL#16 @ R11 = 00LL00RR
  393. BEQ C_mixing_epilogue @ volume #0 --> branch and skip channel processing
  394. /* normal processing otherwise */
  395. TST R0, #MODE_FIXED_FREQ
  396. BNE C_setup_fixed_freq_mixing
  397. TST R0, #MODE_COMP
  398. BNE C_setup_special_mixing @ compressed? --> branch
  399. STMFD SP!, {R4, R9, R12}
  400. /*
  401. * This mixer supports 4 different kind of synthesized sounds
  402. * They are triggered if there is no samples to play
  403. * This get's checked below
  404. */
  405. MOVS R2, R2
  406. ORREQ R0, R0, #MODE_SYNTH
  407. STREQB R0, [R4, #CHN_MODE]
  408. ADD R4, R4, #CHN_FINE_POSITION
  409. LDMIA R4, {R7, LR} @ R7 = Fine Position, LR = Frequency
  410. MUL R4, LR, R12 @ R4 = inter sample steps = output rate factor * samplerate
  411. /* now the first samples get loaded */
  412. LDRSB R6, [R3], #1
  413. LDRSB R12, [R3]
  414. TST R0, #MODE_SYNTH
  415. BNE C_setup_synth
  416. /* incase no synth mode should be used, code contiues here */
  417. SUB R12, R12, R6 @ R12 = DELTA
  418. /*
  419. * Mixing goes with volume ranges 0-127
  420. * They come in 0-255 --> divide by 2
  421. */
  422. MOVS R11, R11, LSR#1
  423. ADC R11, R11, #0x8000
  424. BIC R11, R11, #0xFF00
  425. MOV R1, R7 @ R1 = inter sample position
  426. /*
  427. * There is 2 different mixing codepaths for uncompressed data
  428. * path 1: fast mixing, but doesn't supports loop or stop
  429. * path 2: not so fast but supports sample loops / stop
  430. * This checks if there is enough samples aviable for path 1.
  431. * important: R0 is expected to be #0
  432. */
  433. UMLAL R1, R0, R4, R8
  434. MOV R1, R1, LSR#23
  435. ORR R0, R1, R0, LSL#9
  436. CMP R2, R0 @ actual comparison
  437. BLE C_setup_unbuffered_mixing @ if not enough samples are available for path 1 --> branch
  438. /*
  439. * This is the mixer path 1.
  440. * The interesting thing here is that the code will
  441. * buffer enough samples on stack if enough space
  442. * on stack is available (or goes over the limit of 0x400 bytes)
  443. */
  444. SUB R2, R2, R0
  445. LDR R10, upper_stack_bounds
  446. ADD R10, R10, R0
  447. CMP R10, SP
  448. ADD R10, R3, R0
  449. /*
  450. * R2 = remaining samples after processing
  451. * R10 = final sample position
  452. * SP = original stack location
  453. * These values will get reloaded after channel processing
  454. * due to the lack of registers.
  455. */
  456. STMFD SP!, {R2, R10}
  457. CMPCC R0, #0x400 @ > 0x400 bytes --> read directly from ROM rather than buffered
  458. MOV R10, SP
  459. BCS C_select_highspeed_codepath
  460. /*
  461. * The code below inits the DMA to read word aligned
  462. * samples from ROM to stack
  463. */
  464. BIC R1, R3, #3
  465. MOV R9, #0x04000000
  466. ADD R9, R9, #0xD4
  467. ADD R0, R0, #7
  468. MOV R0, R0, LSR#2
  469. SUB SP, SP, R0, LSL#2
  470. AND R3, R3, #3
  471. ADD R3, R3, SP
  472. ORR LR, R0, #0x84000000
  473. STMIA R9, {R1, SP, LR} @ actually starts the DMA
  474. /* Somehow is neccesary for some games not to break */
  475. .if DMA_FIX==1
  476. MOV R0, #0
  477. MOV R1, #0
  478. MOV R2, #0
  479. STMIA R9, {R0, R1, R2}
  480. .endif
  481. C_select_highspeed_codepath:
  482. STMFD SP!, {R10} @ save original SP for VLA
  483. /*
  484. * This code decides which piece of code to load
  485. * depending on playback-rate / default-rate ratio.
  486. * Modes > 1.0 run with different volume levels.
  487. * R4 = inter sample step
  488. */
  489. ADR R0, high_speed_code_resource @ loads the base pointer of the code
  490. SUBS R4, R4, #0x800000
  491. MOVPL R11, R11, LSL#1 @ if >= 1.0* 0-127 --> 0-254 volume level
  492. ADDPL R0, R0, #(ARM_OP_LEN*6) @ 6 instructions further
  493. SUBPLS R4, R4, #0x800000 @ if >= 2.0*
  494. ADDPL R0, R0, #(ARM_OP_LEN*6)
  495. ADDPL R4, R4, #0x800000
  496. LDR R2, previous_fast_code
  497. CMP R0, R2 @ code doesn't need to be reloaded if it's already in place
  498. BEQ C_skip_fast_mixing_creation
  499. /* This loads the needed code to RAM */
  500. STR R0, previous_fast_code
  501. LDMIA R0, {R0-R2, R8-R10} @ load 6 opcodes
  502. ADR LR, fast_mixing_instructions
  503. C_fast_mixing_creation_loop:
  504. /* paste code to destination, see below for patterns */
  505. STMIA LR, {R0, R1}
  506. ADD LR, LR, #(ARM_OP_LEN*38)
  507. STMIA LR, {R0, R1}
  508. SUB LR, LR, #(ARM_OP_LEN*35)
  509. STMIA LR, {R2, R8-R10}
  510. ADD LR, LR, #(ARM_OP_LEN*38)
  511. STMIA LR, {R2, R8-R10}
  512. SUB LR, LR, #(ARM_OP_LEN*32)
  513. ADDS R5, R5, #0x40000000 @ do that for 4 blocks
  514. BCC C_fast_mixing_creation_loop
  515. LDR R8, [SP] @ restore R8 with the frame length
  516. LDR R8, [R8, #(ARG_FRAME_LENGTH + 0x8 + 0xC)]
  517. C_skip_fast_mixing_creation:
  518. MOV R2, #0xFF000000 @ load the fine position overflow bitmask
  519. C_fast_mixing_loop:
  520. /* This is the actual processing and interpolation code loop; NOPs will be replaced by the code above */
  521. LDMIA R5, {R0, R1, R10, LR} @ load 4 stereo samples to Registers
  522. MUL R9, R7, R12
  523. fast_mixing_instructions:
  524. NOP @ Block #1
  525. NOP
  526. MLANE R0, R11, R9, R0
  527. NOP
  528. NOP
  529. NOP
  530. NOP
  531. BIC R7, R7, R2, ASR#1
  532. MULNE R9, R7, R12
  533. NOP @ Block #2
  534. NOP
  535. MLANE R1, R11, R9, R1
  536. NOP
  537. NOP
  538. NOP
  539. NOP
  540. BIC R7, R7, R2, ASR#1
  541. MULNE R9, R7, R12
  542. NOP @ Block #3
  543. NOP
  544. MLANE R10, R11, R9, R10
  545. NOP
  546. NOP
  547. NOP
  548. NOP
  549. BIC R7, R7, R2, ASR#1
  550. MULNE R9, R7, R12
  551. NOP @ Block #4
  552. NOP
  553. MLANE LR, R11, R9, LR
  554. NOP
  555. NOP
  556. NOP
  557. NOP
  558. BIC R7, R7, R2, ASR#1
  559. STMIA R5!, {R0, R1, R10, LR} @ write 4 stereo samples
  560. LDMIA R5, {R0, R1, R10, LR} @ load the next 4 stereo samples
  561. MULNE R9, R7, R12
  562. NOP @ Block #1
  563. NOP
  564. MLANE R0, R11, R9, R0
  565. NOP
  566. NOP
  567. NOP
  568. NOP
  569. BIC R7, R7, R2, ASR#1
  570. MULNE R9, R7, R12
  571. NOP @ Block #2
  572. NOP
  573. MLANE R1, R11, R9, R1
  574. NOP
  575. NOP
  576. NOP
  577. NOP
  578. BIC R7, R7, R2, ASR#1
  579. MULNE R9, R7, R12
  580. NOP @ Block #3
  581. NOP
  582. MLANE R10, R11, R9, R10
  583. NOP
  584. NOP
  585. NOP
  586. NOP
  587. BIC R7, R7, R2, ASR#1
  588. MULNE R9, R7, R12
  589. NOP @ Block #4
  590. NOP
  591. MLANE LR, R11, R9, LR
  592. NOP
  593. NOP
  594. NOP
  595. NOP
  596. BIC R7, R7, R2, ASR#1
  597. STMIA R5!, {R0, R1, R10, LR} @ write 4 stereo samples
  598. SUBS R8, R8, #8
  599. BGT C_fast_mixing_loop
  600. /* restore previously saved values */
  601. LDMFD SP, {SP} @ reload original stack pointer from VLA
  602. LDMFD SP!, {R2, R3}
  603. B C_end_mixing
  604. /* Various variables for the cached mixer */
  605. .align 2
  606. upper_stack_bounds:
  607. .word 0x03007910
  608. previous_fast_code:
  609. .word 0x0 /* mark as invalid initially */
  610. /* Those instructions below are used by the high speed loop self modifying code */
  611. high_speed_code_resource:
  612. /* Block for Mix Freq < 1.0 * Output Frequency */
  613. MOV R9, R9, ASR#22
  614. ADDS R9, R9, R6, LSL#1
  615. ADDS R7, R7, R4
  616. ADDPL R6, R12, R6
  617. LDRPLSB R12, [R3, #1]!
  618. SUBPLS R12, R12, R6
  619. /* Block for Mix Freq > 1.0 AND < 2.0 * Output Frequency */
  620. ADDS R9, R6, R9, ASR#23
  621. ADD R6, R12, R6
  622. ADDS R7, R7, R4
  623. LDRPLSB R6, [R3, #1]!
  624. LDRSB R12, [R3, #1]!
  625. SUBS R12, R12, R6
  626. /* Block for Mix Freq > 2.0 * Output Frequency */
  627. ADDS R9, R6, R9, ASR#23
  628. ADD R7, R7, R4
  629. ADD R3, R3, R7, LSR#23
  630. LDRSB R6, [R3]
  631. LDRSB R12, [R3, #1]!
  632. SUBS R12, R12, R6
  633. /* incase a loop or end occurs during mixing, this code is used */
  634. C_setup_unbuffered_mixing:
  635. ADD R5, R5, R8, LSL#2 @ R5 = End of HQ buffer
  636. /* This below is the unbuffered mixing loop. R6 = base sample, R12 diff to next */
  637. C_unbuffered_mixing_loop:
  638. MUL R9, R7, R12
  639. MOV R9, R9, ASR#22
  640. ADDS R9, R9, R6, LSL#1
  641. LDRNE R0, [R5, -R8, LSL#2]
  642. MLANE R0, R11, R9, R0
  643. STRNE R0, [R5, -R8, LSL#2]
  644. ADD R7, R7, R4
  645. MOVS R9, R7, LSR#23
  646. BEQ C_unbuffered_mixing_skip_load @ skip the mixing load if it isn't required
  647. SUBS R2, R2, R7, LSR#23
  648. BLLE C_mixing_loop_or_end
  649. SUBS R9, R9, #1
  650. ADDEQ R6, R12, R6
  651. @RETURN LOCATION FROM LOOP HANDLER
  652. LDRNESB R6, [R3, R9]!
  653. LDRSB R12, [R3, #1]!
  654. SUB R12, R12, R6
  655. BIC R7, R7, #0x3F800000
  656. C_unbuffered_mixing_skip_load:
  657. SUBS R8, R8, #1 @ reduce the sample count for the buffer by #1
  658. BGT C_unbuffered_mixing_loop
  659. C_end_mixing:
  660. SUB R3, R3, #1 @ because the mixer always needs 1 byte lookahead, this reverts it
  661. LDMFD SP!, {R4, R9, R12}
  662. STR R7, [R4, #CHN_FINE_POSITION]
  663. B C_mixing_end_store
  664. C_mixing_loop_or_end:
  665. /* This loads the loop information end loops incase it should */
  666. ADD R3, SP, #ARG_LOOP_START_POS+0xC
  667. LDMIA R3, {R3, R6} @ R3 = Loop Start; R6 = Loop Length
  668. CMP R6, #0 @ check if loop is enabled; if Loop is enabled R6 is != 0
  669. RSBNE R9, R2, #0 @ loop wraparound logic
  670. ADDNE R2, R6, R2
  671. ADDNE PC, LR, #(ARM_OP_LEN*2)
  672. LDMFD SP!, {R4, R9, R12}
  673. B C_mixing_end_and_stop_channel @ R6 == 0 (always)
  674. C_fixed_mixing_loop_or_end:
  675. LDR R2, [SP, #ARG_LOOP_LENGTH+0x8]
  676. MOVS R6, R2 @ copy it to R6 and check whether loop is disabled
  677. LDRNE R3, [SP, #ARG_LOOP_START_POS+0x8]
  678. BXNE LR @ if it loops return to mixing function, if it doesn't go on end mixing
  679. LDMFD SP!, {R4, R9}
  680. C_mixing_end_and_stop_channel:
  681. STRB R6, [R4] @ update channel flag with chn halt
  682. B C_mixing_epilogue
  683. /* These are used for the fixed freq mixer */
  684. fixed_mixing_code_resource:
  685. MOVS R6, R10, LSL#24
  686. MOVS R6, R6, ASR#24
  687. MOVS R6, R10, LSL#16
  688. MOVS R6, R6, ASR#24
  689. MOVS R6, R10, LSL#8
  690. MOVS R6, R6, ASR#24
  691. MOVS R6, R10, ASR#24
  692. LDMIA R3!, {R10} @ load chunk of samples
  693. MOVS R6, R10, LSL#24
  694. MOVS R6, R6, ASR#24
  695. MOVS R6, R10, LSL#16
  696. MOVS R6, R6, ASR#24
  697. MOVS R6, R10, LSL#8
  698. MOVS R6, R6, ASR#24
  699. LDMFD SP!, {R4, R9, R12}
  700. C_setup_fixed_freq_mixing:
  701. STMFD SP!, {R4, R9}
  702. C_fixed_mixing_length_check:
  703. MOV LR, R2 @ sample countdown
  704. CMP R2, R8
  705. MOVGT LR, R8 @ min(buffer_size, sample_countdown)
  706. SUB LR, LR, #1
  707. MOVS LR, LR, LSR#2
  708. BEQ C_fixed_mixing_process_rest @ <= 3 samples to process
  709. SUB R8, R8, LR, LSL#2 @ subtract the amount of samples we need to process from the buffer length
  710. SUB R2, R2, LR, LSL#2 @ subtract the amount of samples we need to process from the remaining samples
  711. ADR R1, fixed_mixing_instructions
  712. ADR R0, fixed_mixing_code_resource
  713. MOV R9, R3, LSL#30
  714. ADD R0, R0, R9, LSR#27 @ alignment * 8 + resource offset = new resource offset
  715. LDMIA R0!, {R6, R7, R9, R10} @ load and write instructions
  716. STMIA R1, {R6, R7}
  717. ADD R1, R1, #0xC
  718. STMIA R1, {R9, R10}
  719. ADD R1, R1, #0xC
  720. LDMIA R0, {R6, R7, R9, R10}
  721. STMIA R1, {R6, R7}
  722. ADD R1, R1, #0xC
  723. STMIA R1, {R9, R10}
  724. LDMIA R3!, {R10} @ load 4 samples from ROM
  725. C_fixed_mixing_loop:
  726. LDMIA R5, {R0, R1, R7, R9} @ load 4 samples from hq buffer
  727. fixed_mixing_instructions:
  728. NOP
  729. NOP
  730. MLANE R0, R11, R6, R0 @ add new sample if neccessary
  731. NOP
  732. NOP
  733. MLANE R1, R11, R6, R1
  734. NOP
  735. NOP
  736. MLANE R7, R11, R6, R7
  737. NOP
  738. NOP
  739. MLANE R9, R11, R6, R9
  740. STMIA R5!, {R0, R1, R7, R9} @ write samples to the mixing buffer
  741. SUBS LR, LR, #1
  742. BNE C_fixed_mixing_loop
  743. SUB R3, R3, #4 @ we'll need to load this block again, so rewind a bit
  744. C_fixed_mixing_process_rest:
  745. MOV R1, #4 @ repeat the loop #4 times to completley get rid of alignment errors
  746. C_fixed_mixing_unaligned_loop:
  747. LDR R0, [R5]
  748. LDRSB R6, [R3], #1
  749. MLA R0, R11, R6, R0
  750. STR R0, [R5], #4
  751. SUBS R2, R2, #1
  752. BLEQ C_fixed_mixing_loop_or_end
  753. SUBS R1, R1, #1
  754. BGT C_fixed_mixing_unaligned_loop
  755. SUBS R8, R8, #4
  756. BGT C_fixed_mixing_length_check @ repeat the mixing procedure until the buffer is filled
  757. LDMFD SP!, {R4, R9}
  758. C_mixing_end_store:
  759. STR R2, [R4, #CHN_SAMPLE_COUNTDOWN]
  760. STR R3, [R4, #CHN_POSITION_ABS]
  761. C_mixing_epilogue:
  762. ADR R0, (C_end_channel_state_loop+1)
  763. BX R0
  764. .thumb
  765. C_end_channel_state_loop:
  766. LDR R0, [SP, #ARG_REMAIN_CHN]
  767. SUB R0, #1
  768. BLE C_main_mixer_return
  769. ADD R4, #0x40
  770. B C_channel_state_loop
  771. C_main_mixer_return:
  772. ADR R5, V_noise_shape
  773. LDRB R4, [R5, #0] @ left noise shape
  774. LSL R4, R4, #16
  775. LDRB R5, [R5, #1] @ right noise shape
  776. LSL R5, R5, #16
  777. ADR R0, C_downsampler
  778. BX R0
  779. V_noise_shape:
  780. .byte 0, 0
  781. .arm
  782. .align 2
  783. C_downsampler:
  784. LDR R8, [SP, #ARG_FRAME_LENGTH]
  785. LDR R9, [SP, #ARG_BUFFER_POS]
  786. LDR R10, hq_buffer
  787. MOV R11, #0xFF000000
  788. MOV LR, #0x007F0000
  789. C_downsampler_loop:
  790. LDMIA R10, {R0, R1, R2, R3}
  791. ADD R12, R4, R0 @ left sample #1
  792. CMP R12, #0x3FC00000
  793. MOVGE R12, #0x3FC00000
  794. CMP R12, #-0x40000000
  795. MOVLT R12, #-0x40000000
  796. AND R4, LR, R12
  797. AND R6, R11, R12, LSL#1
  798. ADD R0, R5, R0, LSL#16 @ right
  799. CMP R0, #0x3FC00000
  800. MOVGE R0, #0x3FC00000
  801. CMP R0, #-0x40000000
  802. MOVLT R0, #-0x40000000
  803. AND R5, LR, R0
  804. AND R7, R11, R0, LSL#1
  805. ADD R12, R4, R1 @ left sample #2
  806. CMP R12, #0x3FC00000
  807. MOVGE R12, #0x3FC00000
  808. CMP R12, #-0x40000000
  809. MOVLT R12, #-0x40000000
  810. AND R4, LR, R12
  811. AND R12, R11, R12, LSL#1
  812. ORR R6, R12, R6, LSR#8
  813. ADD R1, R5, R1, LSL#16 @ right
  814. CMP R1, #0x3FC00000
  815. MOVGE R1, #0x3FC00000
  816. CMP R1, #-0x40000000
  817. MOVLT R1, #-0x40000000
  818. AND R5, LR, R1
  819. AND R1, R11, R1, LSL#1
  820. ORR R7, R1, R7, LSR#8
  821. ADD R12, R4, R2 @ left sample #3
  822. CMP R12, #0x3FC00000
  823. MOVGE R12, #0x3FC00000
  824. CMP R12, #-0x40000000
  825. MOVLT R12, #-0x40000000
  826. AND R4, LR, R12
  827. AND R12, R11, R12, LSL#1
  828. ORR R6, R12, R6, LSR#8
  829. ADD R2, R5, R2, LSL#16 @ right
  830. CMP R2, #0x3FC00000
  831. MOVGE R2, #0x3FC00000
  832. CMP R2, #-0x40000000
  833. MOVLT R2, #-0x40000000
  834. AND R5, LR, R2
  835. AND R2, R11, R2, LSL#1
  836. ORR R7, R2, R7, LSR#8
  837. ADD R12, R4, R3 @ left sample #4
  838. CMP R12, #0x3FC00000
  839. MOVGE R12, #0x3FC00000
  840. CMP R12, #-0x40000000
  841. MOVLT R12, #-0x40000000
  842. AND R4, LR, R12
  843. AND R12, R11, R12, LSL#1
  844. ORR R6, R12, R6, LSR#8
  845. ADD R3, R5, R3, LSL#16 @ right
  846. CMP R3, #0x3FC00000
  847. MOVGE R3, #0x3FC00000
  848. CMP R3, #-0x40000000
  849. MOVLT R3, #-0x40000000
  850. AND R5, LR, R3
  851. AND R3, R11, R3, LSL#1
  852. ORR R7, R3, R7, LSR#8
  853. STR R6, [R9, #0x630]
  854. STR R7, [R9], #4
  855. MOV R0, #0
  856. MOV R1, #0
  857. MOV R2, #0
  858. MOV R3, #0
  859. STMIA R10!, {R0, R1, R2, R3}
  860. SUBS R8, #4
  861. BGT C_downsampler_loop
  862. ADR R1, V_noise_shape
  863. ADR R0, (C_downsampler_return+1)
  864. BX R0
  865. .pool
  866. .align 1
  867. .thumb
  868. C_downsampler_return:
  869. LSR R4, #16
  870. STRB R4, [R1, #0]
  871. LSR R5, #16
  872. STRB R5, [R1, #1]
  873. LDR R0, [SP, #ARG_PCM_STRUCT]
  874. LDR R3, mixer_finished_status @ this is used to indicate the interrupt handler the rendering was finished properly
  875. STR R3, [R0]
  876. ADD SP, SP, #0x1C
  877. POP {R0-R7}
  878. MOV R8, R0
  879. MOV R9, R1
  880. MOV R10, R2
  881. MOV R11, R3
  882. POP {R3}
  883. BX R3
  884. .align 2
  885. mixer_finished_status:
  886. .word 0x68736D53
  887. .arm
  888. .align 2
  889. C_setup_synth:
  890. CMP R12, #0
  891. BNE C_check_synth_saw
  892. /* modulating pulse wave */
  893. LDRB R6, [R3, #SYNTH_WIDTH_CHANGE_1]
  894. ADD R2, R2, R6, LSL#24
  895. LDRB R6, [R3, #SYNTH_WIDTH_CHANGE_2]
  896. ADDS R6, R2, R6, LSL#24
  897. MVNMI R6, R6
  898. MOV R10, R6, LSR#8
  899. LDRB R1, [R3, #SYNTH_MOD_AMOUNT]
  900. LDRB R0, [R3, #SYNTH_BASE_WAVE_DUTY]
  901. MOV R0, R0, LSL#24
  902. MLA R6, R10, R1, R0 @ calculate the final duty cycle with the offset, and intensity * rotating duty cycle amount
  903. STMFD SP!, {R2, R3, R9, R12}
  904. C_synth_pulse_loop:
  905. LDMIA R5, {R0-R3, R9, R10, R12, LR} @ load 8 samples
  906. CMP R7, R6 @ Block #1
  907. ADDLO R0, R0, R11, LSL#6
  908. SUBHS R0, R0, R11, LSL#6
  909. ADDS R7, R7, R4, LSL#3
  910. CMP R7, R6 @ Block #2
  911. ADDLO R1, R1, R11, LSL#6
  912. SUBHS R1, R1, R11, LSL#6
  913. ADDS R7, R7, R4, LSL#3
  914. CMP R7, R6 @ Block #3
  915. ADDLO R2, R2, R11, LSL#6
  916. SUBHS R2, R2, R11, LSL#6
  917. ADDS R7, R7, R4, LSL#3
  918. CMP R7, R6 @ Block #4
  919. ADDLO R3, R3, R11, LSL#6
  920. SUBHS R3, R3, R11, LSL#6
  921. ADDS R7, R7, R4, LSL#3
  922. CMP R7, R6 @ Block #5
  923. ADDLO R9, R9, R11, LSL#6
  924. SUBHS R9, R9, R11, LSL#6
  925. ADDS R7, R7, R4, LSL#3
  926. CMP R7, R6 @ Block #6
  927. ADDLO R10, R10, R11, LSL#6
  928. SUBHS R10, R10, R11, LSL#6
  929. ADDS R7, R7, R4, LSL#3
  930. CMP R7, R6 @ Block #7
  931. ADDLO R12, R12, R11, LSL#6
  932. SUBHS R12, R12, R11, LSL#6
  933. ADDS R7, R7, R4, LSL#3
  934. CMP R7, R6 @ Block #8
  935. ADDLO LR, LR, R11, LSL#6
  936. SUBHS LR, LR, R11, LSL#6
  937. ADDS R7, R7, R4, LSL#3
  938. STMIA R5!, {R0-R3, R9, R10, R12, LR} @ write 8 samples
  939. SUBS R8, R8, #8
  940. BGT C_synth_pulse_loop
  941. LDMFD SP!, {R2, R3, R9, R12}
  942. B C_end_mixing
  943. C_check_synth_saw:
  944. /*
  945. * This is actually not a true saw wave
  946. * but looks pretty similar
  947. * (has a jump in the middle of the wave)
  948. */
  949. SUBS R12, R12, #1
  950. BNE C_synth_triangle
  951. MOV R6, #0x300
  952. MOV R11, R11, LSR#1
  953. BIC R11, R11, #0xFF00
  954. MOV R12, #0x70
  955. C_synth_saw_loop:
  956. LDMIA R5, {R0, R1, R10, LR} @ load 4 samples from memory
  957. ADDS R7, R7, R4, LSL#3 @ Block #1 (some oscillator type code)
  958. RSB R9, R12, R7, LSR#24
  959. MOV R6, R7, LSL#1
  960. SUB R9, R9, R6, LSR#27
  961. ADDS R2, R9, R2, ASR#1
  962. MLANE R0, R11, R2, R0
  963. ADDS R7, R7, R4, LSL#3 @ Block #2
  964. RSB R9, R12, R7, LSR#24
  965. MOV R6, R7, LSL#1
  966. SUB R9, R9, R6, LSR#27
  967. ADDS R2, R9, R2, ASR#1
  968. MLANE R1, R11, R2, R1
  969. ADDS R7, R7, R4, LSL#3 @ Block #3
  970. RSB R9, R12, R7, LSR#24
  971. MOV R6, R7, LSL#1
  972. SUB R9, R9, R6, LSR#27
  973. ADDS R2, R9, R2, ASR#1
  974. MLANE R10, R11, R2, R10
  975. ADDS R7, R7, R4, LSL#3 @ Block #4
  976. RSB R9, R12, R7, LSR#24
  977. MOV R6, R7, LSL#1
  978. SUB R9, R9, R6, LSR#27
  979. ADDS R2, R9, R2, ASR#1
  980. MLANE LR, R11, R2, LR
  981. STMIA R5!, {R0, R1, R10, LR}
  982. SUBS R8, R8, #4
  983. BGT C_synth_saw_loop
  984. B C_end_mixing
  985. C_synth_triangle:
  986. MOV R6, #0x80
  987. MOV R12, #0x180
  988. C_synth_triangle_loop:
  989. LDMIA R5, {R0, R1, R10, LR} @ load samples from work buffer
  990. ADDS R7, R7, R4, LSL#3 @ Block #1
  991. RSBPL R9, R6, R7, ASR#23
  992. SUBMI R9, R12, R7, LSR#23
  993. MLA R0, R11, R9, R0
  994. ADDS R7, R7, R4, LSL#3 @ Block #2
  995. RSBPL R9, R6, R7, ASR#23
  996. SUBMI R9, R12, R7, LSR#23
  997. MLA R1, R11, R9, R1
  998. ADDS R7, R7, R4, LSL#3 @ Block #3
  999. RSBPL R9, R6, R7, ASR#23
  1000. SUBMI R9, R12, R7, LSR#23
  1001. MLA R10, R11, R9, R10
  1002. ADDS R7, R7, R4, LSL#3 @ Block #4
  1003. RSBPL R9, R6, R7, ASR#23
  1004. SUBMI R9, R12, R7, LSR#23
  1005. MLA LR, R11, R9, LR
  1006. STMIA R5!, {R0, R1, R10, LR}
  1007. SUBS R8, R8, #4 @ subtract #4 from the remainging samples
  1008. BGT C_synth_triangle_loop
  1009. B C_end_mixing
  1010. .if ENABLE_DECOMPRESSION==1
  1011. C_setup_special_mixing:
  1012. LDR R6, [R4, #CHN_WAVE_OFFSET]
  1013. LDRB R0, [R4]
  1014. TST R0, #FLAG_CHN_COMP
  1015. BNE C_setup_special_mixing_freq @ skip the setup procedure if it's running in compressed mode already
  1016. ORR R0, #FLAG_CHN_COMP
  1017. STRB R0, [R4]
  1018. LDRB R0, [R4, #CHN_MODE]
  1019. TST R0, #MODE_REVERSE
  1020. BEQ C_check_compression @ reversed mode not enabled?
  1021. LDR R1, [R6, #WAVE_LENGTH] @ calculate seek position for reverse playback
  1022. ADD R1, R1, R6, LSL#1 @ sorry, I don't actually understand that piece of code myself
  1023. ADD R1, R1, #0x20
  1024. SUB R3, R1, R3
  1025. STR R3, [R4, #CHN_POSITION_ABS]
  1026. C_check_compression:
  1027. LDRH R0, [R6]
  1028. CMP R0, #0
  1029. BEQ C_setup_special_mixing_freq
  1030. SUB R3, R3, R6
  1031. SUB R3, R3, #0x10
  1032. STR R3, [R4, #CHN_POSITION_ABS]
  1033. C_setup_special_mixing_freq:
  1034. LDR R0, [R6, #WAVE_LOOP_START]
  1035. STR R0, [SP, #ARG_LOOP_START_POS]
  1036. STMFD SP!, {R4, R9, R12}
  1037. MOVS R11, R11, LSR#1
  1038. ADC R11, R11, #0x8000
  1039. BIC R11, R11, #0xFF00
  1040. LDR R7, [R4, #CHN_FINE_POSITION]
  1041. LDR R1, [R4, #CHN_FREQUENCY]
  1042. LDRB R0, [R4, #CHN_MODE]
  1043. TST R0, #MODE_FIXED_FREQ
  1044. MOVNE R1, #0x800000
  1045. MULEQ R1, R12, R1 @ default rate factor * frequency = sample steps
  1046. ADD R5, R5, R8, LSL#2 @ set the buffer pointer to the end of the channel, same as slow mixing mode
  1047. LDRH R0, [R6]
  1048. CMP R0, #0
  1049. BEQ C_uncompressed_reverse_mixing_check
  1050. MOV R0, #0xFF000000 @ --> invalid channel mod
  1051. STR R0, [R4, #CHN_BLOCK_COUNT]
  1052. LDRB R0, [R4, #CHN_MODE]
  1053. TST R0, #MODE_REVERSE
  1054. BNE C_setup_compressed_reverse_mixing @ check again of reverse mixing is enabled
  1055. /* forward compressed mixing */
  1056. BL F_bdpcm_decoder
  1057. MOV R6, R12
  1058. ADD R3, R3, #1
  1059. BL F_bdpcm_decoder
  1060. SUB R12, R12, R6
  1061. @***** MIXING LOOP REGISTER USAGE ***********@
  1062. @ R0: Sample to modify from buffer
  1063. @ R1: sample steps (MOVED FROM R4)
  1064. @ R2: remaining samples before loop/end
  1065. @ R3: sample position
  1066. @ R4: channel pointer
  1067. @ R5: pointer to the end of buffer
  1068. @ R6: Base sample
  1069. @ R7: fine position
  1070. @ R8: remaining samples for current buffer
  1071. @ R9: interpolated sample
  1072. @ R10: not used
  1073. @ R11: volume
  1074. @ R12: Delta Sample
  1075. @ LR: not used
  1076. @********************************************@
  1077. C_compressed_mixing_loop:
  1078. MUL R9, R7, R12 @ check slow mixing for details, same procedure here
  1079. MOV R9, R9, ASR#22
  1080. ADDS R9, R9, R6, LSL#1
  1081. LDRNE R0, [R5, -R8, LSL#2]
  1082. MLANE R0, R11, R9, R0
  1083. STRNE R0, [R5, -R8, LSL#2]
  1084. ADD R7, R7, R1 @ ### changed from R4 to R1
  1085. MOVS R9, R7, LSR#23
  1086. BEQ C_compressed_mixing_skip_load
  1087. SUBS R2, R2, R7, LSR#23
  1088. BLLE C_mixing_loop_or_end
  1089. SUBS R9, R9, #1
  1090. ADDEQ R6, R12, R6
  1091. BEQ C_compressed_mixing_skip_base_load
  1092. ADD R3, R3, R9 @ equivalent to LDRNESB R6, [R3, R9]!
  1093. BL F_bdpcm_decoder
  1094. MOV R6, R12
  1095. C_compressed_mixing_skip_base_load:
  1096. ADD R3, R3, #1 @ equivalent to LDRSB R12, [R3, #1]!
  1097. BL F_bdpcm_decoder
  1098. SUB R12, R12, R6
  1099. BIC R7, R7, #0x3F800000
  1100. C_compressed_mixing_skip_load:
  1101. SUBS R8, R8, #1
  1102. BGT C_compressed_mixing_loop
  1103. B C_end_mixing
  1104. C_setup_compressed_reverse_mixing:
  1105. SUB R3, R3, #1
  1106. BL F_bdpcm_decoder
  1107. MOV R6, R12
  1108. SUB R3, R3, #1
  1109. BL F_bdpcm_decoder
  1110. SUB R12, R12, R6
  1111. C_compressed_reverse_mixing_loop:
  1112. MUL R9, R7, R12
  1113. MOV R9, R9, ASR#22
  1114. ADDS R9, R9, R6, LSL#1
  1115. LDRNE R0, [R5, -R8, LSL#2]
  1116. MLANE R0, R11, R9, R0
  1117. STRNE R0, [R5, -R8, LSL#2]
  1118. ADD R7, R7, R1 @ ### changed from R4 to R1
  1119. MOVS R9, R7, LSR#23
  1120. BEQ C_compressed_reverse_mixing_skip_load
  1121. SUBS R2, R2, R7, LSR#23
  1122. BLLE C_mixing_loop_or_end
  1123. SUBS R9, R9, #1
  1124. ADDEQ R6, R12, R6
  1125. BEQ C_compressed_reverse_mixing_skip_base_load
  1126. SUB R3, R3, R9
  1127. BL F_bdpcm_decoder
  1128. MOV R6, R12
  1129. C_compressed_reverse_mixing_skip_base_load:
  1130. SUB R3, R3, #1
  1131. BL F_bdpcm_decoder
  1132. SUB R12, R12, R6
  1133. BIC R7, R7, #0x3F800000
  1134. C_compressed_reverse_mixing_skip_load:
  1135. SUBS R8, R8, #1
  1136. BGT C_compressed_reverse_mixing_loop
  1137. ADD R3, R3, #3
  1138. B C_end_mixing
  1139. C_uncompressed_reverse_mixing_check:
  1140. LDRB R0, [R4, #1]
  1141. TST R0, #MODE_REVERSE @ check if reverse mode is even enabled (consistency)
  1142. BEQ C_end_mixing
  1143. LDRSB R6, [R3, #-1]!
  1144. LDRSB R12, [R3, #-1]
  1145. SUB R12, R12, R6
  1146. C_uncompressed_reverse_mixing_loop:
  1147. MUL R9, R7, R12
  1148. MOV R9, R9, ASR#22
  1149. ADDS R9, R9, R6, LSL#1
  1150. LDRNE R0, [R5, -R8, LSL#2]
  1151. MLANE R0, R11, R9, R0
  1152. STRNE R0, [R5, -R8, LSL#2]
  1153. ADD R7, R7, R1 @ ### changed from R4 to R1
  1154. MOVS R9, R7, LSR#23
  1155. BEQ C_uncompressed_reverse_mixing_load_skip
  1156. SUBS R2, R2, R7, LSR#23
  1157. BLLE C_mixing_loop_or_end
  1158. MOVS R9, R9
  1159. ADDEQ R6, R12, R6
  1160. LDRNESB R6, [R3, -R9]!
  1161. LDRSB R12, [R3, #-1]
  1162. SUB R12, R12, R6
  1163. BIC R7, R7, #0x3F800000
  1164. C_uncompressed_reverse_mixing_load_skip:
  1165. SUBS R8, R8, #1
  1166. BGT C_uncompressed_reverse_mixing_loop
  1167. ADD R3, R3, #2
  1168. B C_end_mixing
  1169. /*
  1170. * This is the main BDPCM Decoder
  1171. * It decodes and caches a block of PCM data
  1172. * and returns them in R12
  1173. */
  1174. F_bdpcm_decoder:
  1175. STMFD SP!, {R0, LR}
  1176. MOV R0, R3, LSR#6 @ clip off everything but the block offset, each block is 0x40 samples long
  1177. LDR R12, [R4, #CHN_BLOCK_COUNT]
  1178. CMP R0, R12
  1179. BEQ C_bdpcm_decoder_return @ block already decoded -> skip
  1180. STMFD SP!, {R2, R5-R7}
  1181. STR R0, [R4, #CHN_BLOCK_COUNT]
  1182. MOV R12, #0x21 @ 1 Block = 0x21 Bytes, 0x40 decoded samples
  1183. MUL R2, R12, R0
  1184. LDR R12, [R4, #CHN_WAVE_OFFSET]
  1185. ADD R2, R2, R12 @ calc block ROM position
  1186. ADD R2, R2, #0x10
  1187. LDR R5, decoder_buffer
  1188. ADR R6, delta_lookup_table
  1189. MOV R7, #0x40 @ 1 block = 0x40 samples
  1190. LDRB LR, [R2], #1
  1191. STRB LR, [R5], #1
  1192. LDRB R12, [R2], #1
  1193. B C_bdpcm_decoder_lsb
  1194. C_bdpcm_decoder_msb:
  1195. LDRB R12, [R2], #1
  1196. MOV R0, R12, LSR#4
  1197. LDRSB R0, [R6, R0]
  1198. ADD LR, LR, R0
  1199. STRB LR, [R5], #1
  1200. C_bdpcm_decoder_lsb:
  1201. AND R0, R12, #0xF
  1202. LDRSB R0, [R6, R0]
  1203. ADD LR, LR, R0
  1204. STRB LR, [R5], #1
  1205. SUBS R7, R7, #2
  1206. BGT C_bdpcm_decoder_msb
  1207. LDMFD SP!, {R2, R5-R7}
  1208. C_bdpcm_decoder_return:
  1209. LDR R12, decoder_buffer
  1210. AND R0, R3, #0x3F
  1211. LDRSB R12, [R12, R0]
  1212. LDMFD SP!, {R0, PC}
  1213. .align 2
  1214. decoder_buffer:
  1215. .word decoder_buffer_target
  1216. delta_lookup_table:
  1217. .byte 0x0, 0x1, 0x4, 0x9, 0x10, 0x19, 0x24, 0x31, 0xC0, 0xCF, 0xDC, 0xE7, 0xF0, 0xF7, 0xFC, 0xFF
  1218. .endif /* ENABLE_DECOMPRESSION*/
  1219. main_mixer_end:
  1220. .end