No Description

main_mixer.s 48KB

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