暂无描述

main_2_advanced.s 47KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460
  1. @ created by ~ipatix~
  2. @ revision 2.1
  3. /* globals */
  4. .global main_mixer
  5. .global main_mixer_end
  6. /* game code definitions */
  7. .equ GAME_BPED, 0
  8. .equ GAME_BPEE, 1
  9. .equ GAME_BPRE, 2
  10. .equ GAME_KWJ6, 3
  11. .equ GAME_AE7E, 4
  12. .equ GAME_BPRD, 5
  13. /* SELECT USED GAME HERE */
  14. .equ USED_GAME, GAME_BPRE @ CHOOSE YOUR GAME
  15. .equ FRAME_LENGTH_5734, 0x60
  16. .equ FRAME_LENGTH_7884, 0x84 @ THIS MODE IS NOT SUPPORTED BY THIS ENGINE BECAUSE IT DOESN'T USE AN 8 ALIGNED BUFFER LENGTH
  17. .equ FRAME_LENGTH_10512, 0xB0
  18. .equ FRAME_LENGTH_13379, 0xE0 @ DEFAULT
  19. .equ FRAME_LENGTH_15768, 0x108
  20. .equ FRAME_LENGTH_18157, 0x130
  21. .equ FRAME_LENGTH_21024, 0x160
  22. .equ FRAME_LENGTH_26758, 0x1C0
  23. .equ FRAME_LENGTH_31536, 0x210
  24. .equ FRAME_LENGTH_36314, 0x260
  25. .equ FRAME_LENGTH_40137, 0x2A0
  26. .equ FRAME_LENGTH_42048, 0x2C0
  27. .equ DECODER_BUFFER_BPE, 0x03001300
  28. .equ DECODER_BUFFER_BPR, 0x03002088
  29. .equ DECODER_BUFFER_KWJ, 0x03005800
  30. .equ BUFFER_IRAM_BPE, 0x03001AA8
  31. .equ BUFFER_IRAM_BPR, 0x030028E0
  32. .equ BUFFER_IRAM_KWJ, 0x03005840
  33. .equ BUFFER_IRAM_AE7, 0x03006D60 @ PUT THE WORKBUFFER ADDRESS FOR FIRE EMBLEM HERE!!!
  34. /* stack variables */
  35. .equ ARG_FRAME_LENGTH, 0x0 @ TODO actually use this variable
  36. .equ ARG_REMAIN_CHN, 0x4 @ This is the channel count variable
  37. .equ ARG_BUFFER_POS, 0x8 @ stores the current output buffer pointer
  38. .equ ARG_LOOP_START_POS, 0xC @ stores wave loop start position in channel loop
  39. .equ ARG_LOOP_LENGTH, 0x10 @ '' '' '' end position
  40. @ .equ ARG_UKNOWN, 0x14
  41. .equ ARG_VAR_AREA, 0x18 @ pointer to engine the main work area
  42. /* channel struct */
  43. .equ CHN_STATUS, 0x0 @ [byte] channel status bitfield
  44. .equ CHN_MODE, 0x1 @ [byte] channel mode bitfield
  45. .equ CHN_VOL_1, 0x2 @ [byte] volume right
  46. .equ CHN_VOL_2, 0x3 @ [byte] volume left
  47. .equ CHN_ATTACK, 0x4 @ [byte] wave attack summand
  48. .equ CHN_DECAY, 0x5 @ [byte] wave decay factor
  49. .equ CHN_SUSTAIN, 0x6 @ [byte] wave sustain level
  50. .equ CHN_RELEASE, 0x7 @ [byte] wave release factor
  51. .equ CHN_ADSR_LEVEL, 0x9 @ [byte] current envelope level
  52. .equ CHN_FINAL_VOL_1, 0xA @ [byte] not used anymore!
  53. .equ CHN_FINAL_VOL_2, 0xB @ [byte] not used anymore!
  54. .equ CHN_ECHO_VOL, 0xC @ [byte] pseudo echo volume
  55. .equ CHN_ECHO_REMAIN, 0xD @ [byte] pseudo echo length
  56. .equ CHN_POSITION_REL, 0x18 @ [word] sample countdown in mixing loop
  57. .equ CHN_FINE_POSITION, 0x1C @ [word] inter sample position (23 bits)
  58. .equ CHN_FREQUENCY, 0x20 @ [word] sample rate (in Hz)
  59. .equ CHN_WAVE_OFFSET, 0x24 @ [word] wave header pointer
  60. .equ CHN_POSITION_ABS, 0x28 @ [word] points to the current position in the wave data (relative offset for compressed samples)
  61. .equ CHN_BLOCK_COUNT, 0x3C @ [word] only used for compressed samples: contains the value of the block that is currently decoded
  62. /* wave header struct */
  63. .equ WAVE_LOOP_FLAG, 0x3 @ [byte] 0x0 = oneshot; 0x40 = looped
  64. .equ WAVE_FREQ, 0x4 @ [word] pitch adjustment value = mid-C samplerate * 1024
  65. .equ WAVE_LOOP_START, 0x8 @ [word] loop start position
  66. .equ WAVE_LENGTH, 0xC @ [word] loop end / wave end position
  67. .equ WAVE_DATA, 0x10 @ [byte array] actual wave data
  68. /* pulse wave synth configuration offset */
  69. .equ SYNTH_BASE_WAVE_DUTY, 0x1 @ [byte]
  70. .equ SYNTH_WIDTH_CHANGE_1, 0x2 @ [byte]
  71. .equ SYNTH_MOD_AMOUNT, 0x3 @ [byte]
  72. .equ SYNTH_WIDTH_CHANGE_2, 0x4 @ [byte]
  73. /* CHN_STATUS flags - 0x0 = OFF */
  74. .equ FLAG_CHN_INIT, 0x80 @ [bit] write this value to init a channel
  75. .equ FLAG_CHN_RELEASE, 0x40 @ [bit] write this value to release (fade out) the channel
  76. .equ FLAG_CHN_COMP, 0x20 @ [bit] is wave being played compressed (yes/no)
  77. .equ FLAG_CHN_LOOP, 0x10 @ [bit] loop (yes/no)
  78. .equ FLAG_CHN_ECHO, 0x4 @ [bit] echo phase
  79. .equ FLAG_CHN_ATTACK, 0x3 @ [bit] attack phase
  80. .equ FLAG_CHN_DECAY, 0x2 @ [bit] decay phase
  81. .equ FLAG_CHN_SUSTAIN, 0x1 @ [bit] sustain phase
  82. /* CHN_MODE flags */
  83. .equ MODE_FIXED_FREQ, 0x8 @ [bit] set to disable resampling (i.e. playback with output rate)
  84. .equ MODE_REVERSE, 0x10 @ [bit] set to reverse sample playback
  85. .equ MODE_COMP, 0x30 @ [bit] is wave being played compressed or reversed (TODO: rename flag)
  86. .equ MODE_SYNTH, 0x40 @ [bit] READ ONLY, indicates synthzied output
  87. /* variables of the engine work area */
  88. .equ VAR_REVERB, 0x5 @ [byte] 0-127 = reverb level
  89. .equ VAR_MAX_CHN, 0x6 @ [byte] maximum channels to process
  90. .equ VAR_MASTER_VOL, 0x7 @ [byte] PCM master volume
  91. .equ VAR_DEF_PITCH_FAC, 0x18 @ [word] this value get's multiplied with the samplerate for the inter sample distance
  92. .equ VAR_FIRST_CHN, 0x50 @ [CHN struct] relative offset to channel array
  93. /* just some more defines */
  94. .equ REG_DMA3_SRC, 0x040000D4
  95. .equ ARM_OP_LEN, 0x4
  96. @#######################################
  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, BUFFER_IRAM_BPE
  103. .equ decoder_buffer_target, DECODER_BUFFER_BPE
  104. .equ ALLOW_PAUSE, 1
  105. .equ DMA_FIX, 1
  106. .equ ENABLE_DECOMPRESSION, 1
  107. .equ PREVENT_CLIP, 1
  108. .endif
  109. @*********** IF ENGLISH POKEMON FIRE RED
  110. .if USED_GAME==GAME_BPRD
  111. .equ hq_buffer, 0x03002830
  112. .equ decoder_buffer_target, DECODER_BUFFER_BPR
  113. .equ ALLOW_PAUSE, 1
  114. .equ DMA_FIX, 1
  115. .equ ENABLE_DECOMPRESSION, 1
  116. .equ PREVENT_CLIP, 1
  117. .endif
  118. @*********** IF ENGLISH POKEMON EMERALD
  119. .if USED_GAME==GAME_BPEE
  120. .equ hq_buffer, BUFFER_IRAM_BPE
  121. .equ decoder_buffer_target, DECODER_BUFFER_BPE
  122. .equ ALLOW_PAUSE, 1
  123. .equ DMA_FIX, 1
  124. .equ ENABLE_DECOMPRESSION, 1
  125. .equ PREVENT_CLIP, 1
  126. .endif
  127. @*********** IF ENGLISH POKEMON FIRE RED
  128. .if USED_GAME==GAME_BPRE
  129. .equ hq_buffer, BUFFER_IRAM_BPR
  130. .equ decoder_buffer_target, DECODER_BUFFER_BPR
  131. .equ ALLOW_PAUSE, 1
  132. .equ DMA_FIX, 1
  133. .equ ENABLE_DECOMPRESSION, 1
  134. .equ PREVENT_CLIP, 1
  135. .endif
  136. @*********** IF KAWAs JUKEBOX 2006
  137. .if USED_GAME==GAME_KWJ6
  138. .equ hq_buffer, BUFFER_IRAM_KWJ
  139. .equ decoder_buffer_target, DECODER_BUFFER_KWJ
  140. .equ ALLOW_PAUSE, 0
  141. .equ DMA_FIX, 0
  142. .equ ENABLE_DECOMPRESSION, 0
  143. .equ PREVENT_CLIP, 1
  144. .endif
  145. @*********** IF US FIRE EMBLEM
  146. .if USED_GAME==GAME_AE7E
  147. .equ hq_buffer, BUFFER_IRAM_AE7
  148. .equ ALLOW_PAUSE, 0
  149. .equ DMA_FIX, 0
  150. .equ ENABLE_DECOMPRESSION, 0
  151. .equ PREVENT_CLIP, 0
  152. .endif
  153. @***********
  154. .thumb
  155. main_mixer:
  156. /* load Reverb level and check if we need to apply it */
  157. LDRB R3, [R0, #VAR_REVERB]
  158. LSR R3, R3, #2
  159. BEQ clear_buffer
  160. ADR R1, do_reverb
  161. BX R1
  162. .align 2
  163. .arm
  164. do_reverb:
  165. /*
  166. * reverb is calculated by the following: new_sample = old_sample * reverb_level / 127
  167. * note that reverb is mono (both sides get mixed together)
  168. *
  169. * reverb get's applied to the frame we are currently looking at and the one after that
  170. * the magic below simply calculateds the pointer for the one after the current one
  171. */
  172. CMP R4, #2
  173. ADDEQ R7, R0, #0x350
  174. ADDNE R7, R5, R8
  175. MOV R4, R8
  176. ORR R3, R3, R3, LSL#16
  177. STMFD SP!, {R8, LR}
  178. LDR LR, hq_buffer_label
  179. reverb_loop:
  180. /* This loop does the reverb processing */
  181. LDRSB R0, [R5, R6]
  182. LDRSB R1, [R5], #1
  183. LDRSB R2, [R7, R6]
  184. LDRSB R8, [R7], #1
  185. LDRSB R9, [R5, R6]
  186. LDRSB R10, [R5], #1
  187. LDRSB R11, [R7, R6]
  188. LDRSB R12, [R7], #1
  189. ADD R0, R0, R1
  190. ADD R0, R0, R2
  191. ADDS R0, R0, R8
  192. ADDMI R0, R0, #0x4
  193. ADD R1, R9, R10
  194. ADD R1, R1, R11
  195. ADDS R1, R1, R12
  196. ADDMI R1, R1, #0x4
  197. MUL R0, R3, R0
  198. MUL R1, R3, R1
  199. STMIA LR!, {R0, R1}
  200. SUBS R4, R4, #2
  201. BGT reverb_loop
  202. /* end of loop */
  203. LDMFD SP!, {R8, LR}
  204. ADR R0, (adsr_setup+1)
  205. BX R0
  206. .thumb
  207. clear_buffer:
  208. /* Incase reverb is disabled the buffer get's set to zero */
  209. LDR R3, hq_buffer_label
  210. MOV R1, R8
  211. MOV R4, #0
  212. MOV R5, #0
  213. MOV R6, #0
  214. MOV R7, #0
  215. /*
  216. * Setting the buffer to zero happens in a very efficient loop
  217. * Depending on the alignment of the buffer length, twice or quadruple the amount of bytes
  218. * get cleared at once
  219. */
  220. LSR R1, #3
  221. BCC clear_buffer_align_8
  222. STMIA R3!, {R4, R5, R6, R7}
  223. clear_buffer_align_8:
  224. LSR R1, #1
  225. BCC clear_buffer_align_16
  226. STMIA R3!, {R4, R5, R6, R7}
  227. STMIA R3!, {R4, R5, R6, R7}
  228. clear_buffer_align_16:
  229. /* This repeats until the buffer has been cleared */
  230. STMIA R3!, {R4, R5, R6, R7}
  231. STMIA R3!, {R4, R5, R6, R7}
  232. STMIA R3!, {R4, R5, R6, R7}
  233. STMIA R3!, {R4, R5, R6, R7}
  234. SUB R1, #1
  235. BGT clear_buffer_align_16
  236. /* loop end */
  237. adsr_setup:
  238. /*
  239. * okay, before the actual mixing starts
  240. * the volume and envelope calculation happens
  241. */
  242. MOV R4, R8 @ R4 = buffer length
  243. /* this buffers the buffer length to a backup location
  244. * TODO: Move this variable to stack
  245. */
  246. ADR R0, hq_buffer_length_label
  247. STR R4, [R0]
  248. /* init channel loop */
  249. LDR R4, [SP, #ARG_VAR_AREA] @ R4 = main work area pointer
  250. LDR R0, [R4, #VAR_DEF_PITCH_FAC] @ R0 = samplingrate pitch factor
  251. MOV R12, R0 @ --> R12
  252. LDRB R0, [R4, #VAR_MAX_CHN] @ load MAX channels to R0
  253. ADD R4, #VAR_FIRST_CHN @ R4 = Base channel Offset (Channel #0)
  254. mixer_entry:
  255. /* this is the main channel processing loop */
  256. STR R0, [SP, #ARG_REMAIN_CHN]
  257. LDR R3, [R4, #CHN_WAVE_OFFSET]
  258. LDRB R6, [R4, #CHN_STATUS]
  259. MOVS R0, #0xC7 @ check if any of the channel status flags is set
  260. TST R0, R6 @ check if none of the flags is set
  261. BEQ return_channel_null @ skip channel
  262. /* check channel flags */
  263. LSL R0, R6, #25 @ shift over the FLAG_CHN_INIT to CARRY
  264. BCC adsr_echo_check @ continue with normal channel procedure
  265. /* check leftmost bit */
  266. BMI stop_channel_handler @ if the channel is initiated but on release it gets turned off immediatley
  267. /* channel init procedure */
  268. MOVS R6, #FLAG_CHN_ATTACK @ set the channel status to ATTACK
  269. MOVS R0, R3 @ R0 = CHN_WAVE_OFFSET
  270. ADD R0, #WAVE_DATA @ R0 = wave data offset
  271. /* Pokemon games seem to init channels differently than other m4a games */
  272. .if ALLOW_PAUSE==0
  273. STR R0, [R4, #CHN_POSITION_ABS]
  274. LDR R0, [R3, #WAVE_LENGTH]
  275. STR R0, [R4, #CHN_POSITION_REL]
  276. .else
  277. LDR R1, [R4, #CHN_POSITION_REL]
  278. ADD R0, R0, R1
  279. STR R0, [R4, #CHN_POSITION_ABS]
  280. LDR R0, [R3, #WAVE_LENGTH]
  281. SUB R0, R0, R1
  282. STR R0, [R4, #CHN_POSITION_REL]
  283. .endif
  284. MOVS R5, #0 @ initial envelope = #0
  285. STRB R5, [R4, #CHN_ADSR_LEVEL]
  286. STR R5, [R4, #CHN_FINE_POSITION]
  287. LDRB R2, [R3, #WAVE_LOOP_FLAG]
  288. LSR R0, R2, #6
  289. BEQ adsr_attack_handler @ if loop disabled --> branch
  290. /* loop enabled here */
  291. MOVS R0, #FLAG_CHN_LOOP
  292. ORR R6, R0 @ update channel status
  293. B adsr_attack_handler
  294. adsr_echo_check:
  295. /* this is the normal ADSR procedure without init */
  296. LDRB R5, [R4, #CHN_ADSR_LEVEL]
  297. LSL R0, R6, #29 @ echo flag --> bit 31
  298. BPL adsr_release_check @ PL == false
  299. /* pseudo echo handler */
  300. LDRB R0, [R4, #CHN_ECHO_REMAIN]
  301. SUB R0, #1
  302. STRB R0, [R4, #CHN_ECHO_REMAIN]
  303. BHI channel_vol_calc @ if echo still on --> branch
  304. stop_channel_handler:
  305. MOVS R0, #0
  306. STRB R0, [R4, #CHN_STATUS]
  307. return_channel_null:
  308. /* go to end of the channel loop */
  309. B check_remain_channels
  310. adsr_release_check:
  311. LSL R0, R6, #25 @ bit 31 = release bit
  312. BPL adsr_decay_check @ if release == 0 --> branch
  313. /* release handler */
  314. LDRB R0, [R4, #CHN_RELEASE]
  315. @SUB R0, #0xFF @ linear decay; TODO make option for triggering it
  316. @SUB R0, #1
  317. @ADD R5, R5, R0
  318. MUL R5, R5, R0 @ default release algorithm
  319. LSR R5, R5, #8
  320. @BMI adsr_released_handler @ part of linear decay
  321. BEQ adsr_released_handler @ release gone down to #0 --> branch
  322. /* pseudo echo init handler */
  323. LDRB R0, [R4, #CHN_ECHO_VOL]
  324. CMP R5, R0
  325. BHI channel_vol_calc @ if release still above echo level --> branch
  326. adsr_released_handler:
  327. /* if volume released to #0 */
  328. LDRB R5, [R4, #CHN_ECHO_VOL] @ TODO: replace with MOV R5, R0
  329. CMP R5, #0
  330. BEQ stop_channel_handler @ if pseudo echo vol = 0 --> branch
  331. /* pseudo echo volume handler */
  332. MOVS R0, #FLAG_CHN_ECHO
  333. ORR R6, R0 @ set the echo flag
  334. B adsr_update_status
  335. adsr_decay_check:
  336. /* check if decay is active */
  337. MOVS R2, #3
  338. AND R2, R6 @ seperate phase status bits
  339. CMP R2, #FLAG_CHN_DECAY
  340. BNE adsr_attack_check @ decay not active --> branch
  341. /* decay handler */
  342. LDRB R0, [R4, #CHN_DECAY]
  343. MUL R5, R0
  344. LSR R5, R5, #8
  345. LDRB R0, [R4, #CHN_SUSTAIN]
  346. CMP R5, R0
  347. BHI channel_vol_calc @ sample didn't decay yet --> branch
  348. /* sustain handler */
  349. MOVS R5, R0 @ current level = sustain level
  350. BEQ adsr_released_handler @ sustain level #0 --> branch
  351. /* step to next phase otherweise */
  352. B adsr_switchto_next
  353. adsr_attack_check:
  354. /* attack handler */
  355. CMP R2, #FLAG_CHN_ATTACK
  356. BNE channel_vol_calc @ if it isn't in attack attack phase, it has to be in sustain (no adsr change needed) --> branch
  357. adsr_attack_handler:
  358. /* apply attack summand */
  359. LDRB R0, [R4, #CHN_ATTACK]
  360. ADD R5, R5, R0
  361. CMP R5, #0xFF
  362. BCC adsr_update_status
  363. /* cap attack at 0xFF */
  364. MOVS R5, #0xFF
  365. adsr_switchto_next:
  366. /* switch to next adsr phase */
  367. SUB R6, #1
  368. adsr_update_status:
  369. /* store channel status */
  370. STRB R6, [R4, #CHN_STATUS]
  371. channel_vol_calc:
  372. /* store the calculated ADSR level */
  373. STRB R5, [R4, #CHN_ADSR_LEVEL]
  374. /* apply master volume */
  375. LDR R0, [SP, #ARG_VAR_AREA]
  376. LDRB R0, [R0, #VAR_MASTER_VOL]
  377. ADD R0, #1
  378. MUL R5, R0, R5
  379. /* left side volume */
  380. LDRB R0, [R4, #CHN_VOL_2]
  381. MUL R0, R5
  382. LSR R0, R0, #13
  383. MOV R10, R0 @ R10 = left volume
  384. /* right side volume */
  385. LDRB R0, [R4, #CHN_VOL_1]
  386. MUL R0, R5
  387. LSR R0, R0, #13
  388. MOV R11, R0 @ R11 = right volume
  389. /*
  390. * Now we get closer to actual mixing:
  391. * For looped samples some additional operations are required
  392. */
  393. MOVS R0, #FLAG_CHN_LOOP
  394. AND R0, R6
  395. BEQ mixing_loop_setup @ TODO: This label should rather be called "skip_loop_setup"
  396. /* loop setup handler */
  397. ADD R3, #WAVE_LOOP_START
  398. LDMIA R3!, {R0, R1} @ R0 = loop start, R1 = loop end
  399. ADD R3, R0, R3 @ R3 = loop start position (absolute)
  400. STR R3, [SP, #ARG_LOOP_START_POS] @ backup loop start
  401. SUB R0, R1, R0
  402. mixing_loop_setup:
  403. /* do the rest of the setup */
  404. STR R0, [SP, #ARG_LOOP_LENGTH] @ if loop is off --> R0 = 0x0
  405. LDR R5, hq_buffer_label
  406. LDR R2, [R4, #CHN_POSITION_REL] @ remaining samples for channel
  407. LDR R3, [R4, #CHN_POSITION_ABS] @ current stream position (abs)
  408. LDRB R0, [R4, #CHN_MODE]
  409. ADR R1, mixing_arm_setup
  410. BX R1
  411. .align 2
  412. hq_buffer_label:
  413. .word hq_buffer
  414. hq_buffer_length_label: @ TODO: Replace with variable on stack
  415. .word 0xFFFFFFFF
  416. .arm
  417. mixing_arm_setup:
  418. /* frequency and mixing loading routine */
  419. LDR R8, hq_buffer_length_label
  420. ORRS R11, R10, R11, LSL#16 @ R11 = 00RR00LL
  421. BEQ switchto_thumb @ volume #0 --> branch and skip channel processing
  422. /* normal processing otherwise */
  423. TST R0, #MODE_FIXED_FREQ
  424. BNE fixed_mixing_setup
  425. TST R0, #MODE_COMP
  426. BNE special_mixing @ compressed? --> branch
  427. /* same here */
  428. STMFD SP!, {R4, R9, R12}
  429. /*
  430. * This mixer supports 4 different kind of synthesized sounds
  431. * They are triggered when the loop end = 0
  432. * This get's checked below
  433. */
  434. MOVS R2, R2
  435. ORREQ R0, R0, #MODE_SYNTH
  436. STREQB R0, [R4, #CHN_MODE]
  437. ADD R4, R4, #CHN_FINE_POSITION
  438. LDMIA R4, {R7, LR} @ R7 = Fine Position, LR = Frequency
  439. MUL R4, R12, LR @ R4 = inter sample steps = output rate factor * samplerate
  440. /* now the first samples get loaded */
  441. LDRSB R6, [R3], #1
  442. LDRSB R12, [R3]
  443. TST R0, #MODE_SYNTH
  444. BNE init_synth
  445. /* incase no synth mode should be used, code contiues here */
  446. SUB R12, R12, R6 @ R12 = DELTA
  447. /*
  448. * Mixing goes with volume ranges 0-127
  449. * They come in 0-255 --> divide by 2
  450. */
  451. MOVS R11, R11, LSR#1
  452. ADC R11, R11, #0x8000
  453. BIC R11, R11, #0xFF00
  454. MOV R1, R7 @ R1 = inter sample position
  455. /*
  456. * There is 2 different mixing codepaths for uncompressed data
  457. * path 1: fast mixing, but doesn't supports loop or stop
  458. * path 2: not so fast but supports sample loops / stop
  459. * This checks if there is enough samples aviable for path 1.
  460. * important: R0 is expected to be #0
  461. */
  462. UMLAL R1, R0, R4, R8
  463. MOV R1, R1, LSR#23
  464. ORR R0, R1, R0, LSL#9
  465. CMP R2, R0 @ actual comparison
  466. BLE split_sample_loading @ if not enough samples are available for path 1 --> branch
  467. /*
  468. * This is the mixer path 1.
  469. * The interesting thing here is that the code will
  470. * buffer enough samples on stack if enough space
  471. * on stack is available (or goes over the limit of 0x400 bytes)
  472. */
  473. SUB R2, R2, R0
  474. LDR R10, stack_capacity
  475. ADD R10, R10, R0
  476. CMP R10, SP
  477. ADD R10, R3, R0
  478. ADR R9, custom_stack_3
  479. /*
  480. * R2 = remaining samples
  481. * R10 = final sample position
  482. * SP = original stack location
  483. * These values will get reloaded after channel processing
  484. * due to the lack of registers.
  485. */
  486. STMIA R9, {R2, R10, SP}
  487. CMPCC R0, #0x400 @ > 0x400 bytes --> read directly from ROM rather than buffered
  488. BCS select_mixing_mode @ TODO rename
  489. /*
  490. * The code below inits the DMA to read word aligned
  491. * samples from ROM to stack
  492. */
  493. BIC R1, R3, #3
  494. MOV R9, #0x04000000
  495. ADD R9, R9, #0xD4
  496. ADD R0, R0, #7
  497. MOV R0, R0, LSR#2
  498. SUB SP, SP, R0, LSL#2
  499. AND R3, R3, #3
  500. ADD R3, R3, SP
  501. ORR LR, R0, #0x84000000
  502. STMIA R9, {R1, SP, LR} @ actually starts the DMA
  503. /* Somehow is neccesary for some games not to break */
  504. .if DMA_FIX==1
  505. MOV R0, #0
  506. MOV R1, R0
  507. MOV R2, R1
  508. STMIA R9, {R0, R1, R2}
  509. .endif
  510. select_mixing_mode:
  511. /*
  512. * This code decides which piece of code to load
  513. * depending on playback-rate / default-rate ratio.
  514. * Modes > 1.0 run with different volume levels.
  515. */
  516. SUBS R4, R4, #0x800000
  517. MOVPL R11, R11, LSL#1
  518. ADR R0, math_resources @ loads the base pointer of the code
  519. ADDPL R0, R0, #(ARM_OP_LEN*6) @ 6 instructions further
  520. SUBPLS R4, R4, #0x800000
  521. ADDPL R0, R0, #(ARM_OP_LEN*6)
  522. ADDPL R4, R4, #0x800000 @ TODO how does restoring for > 2.0 ratios work?
  523. LDR R2, function_pointer
  524. CMP R0, R2 @ code doesn't need to be reloaded if it's already in place
  525. BEQ mixing_init
  526. /* This loads the needed code to RAM */
  527. STR R0, function_pointer
  528. LDMIA R0, {R0-R2, R8-R10} @ load 6 opcodes
  529. ADR LR, runtime_created_routine
  530. create_routine_loop:
  531. /* paste code to destination, see below for patterns */
  532. STMIA LR, {R0, R1}
  533. ADD LR, LR, #0x98
  534. STMIA LR, {R0, R1}
  535. SUB LR, LR, #0x8C
  536. STMIA LR, {R2, R8-R10}
  537. ADD LR, LR, #0x98
  538. STMIA LR, {R2, R8-R10}
  539. SUB LR, LR, #0x80
  540. ADDS R5, R5, #0x40000000 @ do that for 4 blocks
  541. BCC create_routine_loop
  542. LDR R8, hq_buffer_length_label
  543. mixing_init:
  544. MOV R2, #0xFF000000 @ load the fine position overflow bitmask
  545. mixing_loop:
  546. /* This is the actual processing and interpolation code loop; NOPs will be replaced by the code above */
  547. LDMIA R5, {R0, R1, R10, LR} @ load 4 stereo samples to Registers
  548. MUL R9, R7, R12
  549. runtime_created_routine:
  550. NOP @ Block #1
  551. NOP
  552. MLANE R0, R11, R9, R0
  553. NOP
  554. NOP
  555. NOP
  556. NOP
  557. BIC R7, R7, R2, ASR#1
  558. MULNE R9, R7, R12
  559. NOP @ Block #2
  560. NOP
  561. MLANE R1, R11, R9, R1
  562. NOP
  563. NOP
  564. NOP
  565. NOP
  566. BIC R7, R7, R2, ASR#1
  567. MULNE R9, R7, R12
  568. NOP @ Block #3
  569. NOP
  570. MLANE R10, R11, R9, R10
  571. NOP
  572. NOP
  573. NOP
  574. NOP
  575. BIC R7, R7, R2, ASR#1
  576. MULNE R9, R7, R12
  577. NOP @ Block #4
  578. NOP
  579. MLANE LR, R11, R9, LR
  580. NOP
  581. NOP
  582. NOP
  583. NOP
  584. BIC R7, R7, R2, ASR#1
  585. STMIA R5!, {R0, R1, R10, LR} @ write 4 stereo samples
  586. LDMIA R5, {R0, R1, R10, LR} @ load the next 4 stereo samples
  587. MULNE R9, R7, R12
  588. NOP @ Block #1
  589. NOP
  590. MLANE R0, R11, R9, R0
  591. NOP
  592. NOP
  593. NOP
  594. NOP
  595. BIC R7, R7, R2, ASR#1
  596. MULNE R9, R7, R12
  597. NOP @ Block #2
  598. NOP
  599. MLANE R1, R11, R9, R1
  600. NOP
  601. NOP
  602. NOP
  603. NOP
  604. BIC R7, R7, R2, ASR#1
  605. MULNE R9, R7, R12
  606. NOP @ Block #3
  607. NOP
  608. MLANE R10, R11, R9, R10
  609. NOP
  610. NOP
  611. NOP
  612. NOP
  613. BIC R7, R7, R2, ASR#1
  614. MULNE R9, R7, R12
  615. NOP @ Block #4
  616. NOP
  617. MLANE LR, R11, R9, LR
  618. NOP
  619. NOP
  620. NOP
  621. NOP
  622. BIC R7, R7, R2, ASR#1
  623. STMIA R5!, {R0, R1, R10, LR} @ write 4 stereo samples
  624. SUBS R8, R8, #8 @ subtract 8 from the sample count
  625. BGT mixing_loop
  626. /* restore previously saved values */
  627. ADR R12, custom_stack_3
  628. LDMIA R12, {R2, R3, SP}
  629. B mixing_end_func
  630. @ work variables
  631. .align 2
  632. custom_stack_3:
  633. .word 0x0, 0x0, 0x0
  634. stack_capacity:
  635. .word 0x03007910
  636. function_pointer:
  637. .word 0x0
  638. @ math resources, not directly used
  639. math_resources:
  640. MOV R9, R9, ASR#22 @ Frequency Lower than default Frequency
  641. ADDS R9, R9, R6, LSL#1
  642. ADDS R7, R7, R4
  643. ADDPL R6, R12, R6
  644. LDRPLSB R12, [R3, #1]!
  645. SUBPLS R12, R12, R6
  646. ADDS R9, R6, R9, ASR#23 @ Frequency < 2x && Frequency > default frequency
  647. ADD R6, R12, R6
  648. ADDS R7, R7, R4
  649. LDRPLSB R6, [R3, #1]!
  650. LDRSB R12, [R3, #1]!
  651. SUBS R12, R12, R6
  652. ADDS R9, R6, R9, ASR#23 @ Frequency >= 2x higher than default Frequency
  653. ADD R7, R7, R4
  654. ADD R3, R3, R7, LSR#23
  655. LDRSB R6, [R3]
  656. LDRSB R12, [R3, #1]!
  657. SUBS R12, R12, R6
  658. split_sample_loading:
  659. ADD R5, R5, R8, LSL#2 @ R5 = End of HQ buffer
  660. uncached_mixing_loop:
  661. MUL R9, R7, R12 @ calc interpolated DELTA
  662. MOV R9, R9, ASR#22 @ scale down the DELTA
  663. ADDS R9, R9, R6, LSL#1 @ Add to Base Sample (upscaled to 8 bits again)
  664. LDRNE R0, [R5, -R8, LSL#2] @ load sample from buffer
  665. MLANE R0, R11, R9, R0 @ add it to the buffer sample
  666. STRNE R0, [R5, -R8, LSL#2] @ write the sample
  667. ADD R7, R7, R4 @ add the step size to the fine position
  668. MOVS R9, R7, LSR#23 @ write the overflow amount to R9
  669. BEQ uncached_mixing_load_skip @ skip the mixing load if it isn't required
  670. SUBS R2, R2, R7, LSR#23 @ remove the overflow count from the remaning samples
  671. BLLE loop_end_sub @ if the loop end is reached call the loop handler
  672. SUBS R9, R9, #1 @ remove #1 from the overflow count
  673. ADDEQ R6, R12, R6 @ new base sample is previous sample + DELTA
  674. @RETURN LOCATION FROM LOOP HANDLER
  675. LDRNESB R6, [R3, R9]! @ load new sample
  676. LDRSB R12, [R3, #1]! @ load the delta sample (always required)
  677. SUB R12, R12, R6 @ calc new DELTA
  678. BIC R7, R7, #0x3F800000 @ clear the overflow from the fine position by using the bitmask
  679. uncached_mixing_load_skip:
  680. SUBS R8, R8, #1 @ reduce the sample count for the buffer by #1
  681. BGT uncached_mixing_loop
  682. mixing_end_func:
  683. SUB R3, R3, #1 @ reduce sample pointer by #1 (???)
  684. LDMFD SP!, {R4, R9, R12} @ pop values from stack
  685. STR R7, [R4, #CHN_FINE_POSITION] @ store the fine position
  686. B store_coarse_sample_pos @ jump over to code to store coarse channel position
  687. loop_end_sub:
  688. ADD R3, SP, #ARG_LOOP_START_POS+0xC @ prepare sample loop start loading and lopo length loading (0xC due to the pushed stack pointer)
  689. LDMIA R3, {R3, R6} @ R3 = Loop Start; R6 = Loop Length
  690. CMP R6, #0 @ check if loop is enabled; if Loop is enabled R6 is != 0
  691. RSBNE R9, R2, #0 @ the sample overflow from the resampling needs to get subtracted so the remaining samples is slightly less
  692. ADDNE R2, R6, R2 @ R2 = add the loop length
  693. ADDNE PC, LR, #8 @ return from the subroutine to 2 instructions after the actual return location
  694. LDMFD SP!, {R4, R9, R12} @ restore registers from stack
  695. B update_channel_status
  696. fixed_freq_loop_end_handler:
  697. LDR R2, [SP, #ARG_LOOP_LENGTH+0x8] @ load the loop length value
  698. MOVS R6, R2 @ copy it to R6 and check if loop is disabled
  699. LDRNE R3, [SP, #ARG_LOOP_START_POS+0x8] @ reset the sample pointer to the loop start position
  700. BXNE LR @ if it loops return to mixing function, if it doesn't go on and end mixing
  701. LDMFD SP!, {R4, R9}
  702. update_channel_status:
  703. STRB R6, [R4] @ if loop ist disabled R6 = 0 and we can disable the channel by writing R6 to R4 (channel area)
  704. B switchto_thumb @ switch to thumb
  705. fixed_math_resource: @ not exectued, used to create mixing function
  706. MOVS R6, R10, LSL#24
  707. MOVS R6, R6, ASR#24
  708. MOVS R6, R10, LSL#16
  709. MOVS R6, R6, ASR#24
  710. MOVS R6, R10, LSL#8
  711. MOVS R6, R6, ASR#24
  712. MOVS R6, R10, ASR#24
  713. LDMIA R3!, {R10} @ load chunk of samples
  714. MOVS R6, R10, LSL#24
  715. MOVS R6, R6, ASR#24
  716. MOVS R6, R10, LSL#16
  717. MOVS R6, R6, ASR#24
  718. MOVS R6, R10, LSL#8
  719. MOVS R6, R6, ASR#24
  720. LDMFD SP!, {R4, R9, R12}
  721. fixed_mixing_setup:
  722. STMFD SP!, {R4, R9} @ backup the channel pointer and
  723. fixed_mixing_check_length:
  724. MOV LR, R2 @ move absolute sample position to LR
  725. CMP R2, R8 @
  726. MOVGT LR, R8 @ if there is less samples than the buffer to process write the smaller sample amount to LR
  727. SUB LR, LR, #1 @ shorten samples to process by #1
  728. MOVS LR, LR, LSR#2 @ calculate the amount of words to process (-1/4)
  729. BEQ fixed_mixing_process_unaligned @ process the unaligned samples if there is <= 3 samples to process
  730. SUB R8, R8, LR, LSL#2 @ subtract the amount of samples we need to process from the buffer length
  731. SUB R2, R2, LR, LSL#2 @ subtract the amount of samples we need to process from the remaining samples
  732. ADR R1, fixed_mixing_custom_routine
  733. ADR R0, fixed_math_resource @ load the 2 pointers to create function (@R0) by instructions from R1
  734. MOV R9, R3, LSL#30 @ move sample alignment bits to the leftmost position
  735. ADD R0, R0, R9, LSR#27 @ alignment * 8 + resource offset = new resource offset
  736. LDMIA R0!, {R6, R7, R9, R10} @ load 4 instructions
  737. STMIA R1, {R6, R7} @ write the 1st 2 instructions
  738. ADD R1, R1, #0xC @ move label pointer over to the next slot
  739. STMIA R1, {R9, R10} @ write 2nd block
  740. ADD R1, R1, #0xC @ move label pointer to next block
  741. LDMIA R0, {R6, R7, R9, R10} @ load instructions for block #3 and #4
  742. STMIA R1, {R6, R7} @ write block #3
  743. ADD R1, R1, #0xC @ ...
  744. STMIA R1, {R9, R10} @ write block #4
  745. LDMIA R3!, {R10} @ write read 4 samples from ROM
  746. fixed_mixing_loop:
  747. LDMIA R5, {R0, R1, R7, R9} @ load 4 samples from hq buffer
  748. fixed_mixing_custom_routine:
  749. NOP
  750. NOP
  751. MLANE R0, R11, R6, R0 @ add new sample if neccessary
  752. NOP
  753. NOP
  754. MLANE R1, R11, R6, R1
  755. NOP
  756. NOP
  757. MLANE R7, R11, R6, R7
  758. NOP
  759. NOP
  760. MLANE R9, R11, R6, R9
  761. STMIA R5!, {R0, R1, R7, R9} @ write the samples to the work area buffer
  762. SUBS LR, LR, #1 @ countdown the sample blocks to process
  763. BNE fixed_mixing_loop @ if the end wasn't reached yet, repeat the loop
  764. SUB R3, R3, #4 @ reduce sample position by #4, we'll need to load the samples again
  765. fixed_mixing_process_unaligned:
  766. MOV R1, #4 @ we need to repeat the loop #4 times to completley get rid of alignment errors
  767. fixed_mixing_unaligned_loop:
  768. LDR R0, [R5] @ load sample from buffer
  769. LDRSB R6, [R3], #1 @ load sample from ROM ro R6
  770. MLA R0, R11, R6, R0 @ write the sample to the buffer
  771. STR R0, [R5], #4
  772. SUBS R2, R2, #1 @ reduce alignment error by #1
  773. BLEQ fixed_freq_loop_end_handler
  774. SUBS R1, R1, #1
  775. BGT fixed_mixing_unaligned_loop @ repeat the loop #4 times
  776. SUBS R8, R8, #4 @ reduce the sample amount we wrote to the buffer by #1
  777. BGT fixed_mixing_check_length @ go up to repeat the mixing procedure until the buffer is filled
  778. LDMFD SP!, {R4, R9} @ pop registers from stack
  779. store_coarse_sample_pos:
  780. STR R2, [R4, #CHN_POSITION_REL] @ store relative and absolute sample position
  781. STR R3, [R4, #CHN_POSITION_ABS]
  782. switchto_thumb:
  783. ADR R0, (check_remain_channels+1) @ load the label offset and switch to thumb
  784. BX R0
  785. .thumb
  786. check_remain_channels:
  787. LDR R0, [SP, #ARG_REMAIN_CHN] @ load the remaining channels
  788. SUB R0, #1 @ reduce the amount by #1
  789. BLE mixer_return @ end the mixing when finished processing all channels
  790. ADD R4, #0x40
  791. B mixer_entry
  792. mixer_return:
  793. ADR R0, downsampler
  794. BX R0
  795. downsampler_return:
  796. LDR R0, [SP, #ARG_VAR_AREA] @ load the main var area to R0
  797. LDR R3, mixer_finished_status @ load some status indication value to R3
  798. STR R3, [R0] @ store this value to the main var area
  799. ADD SP, SP, #0x1C
  800. POP {R0-R7}
  801. MOV R8, R0
  802. MOV R9, R1
  803. MOV R10, R2
  804. MOV R11, R3
  805. POP {R3}
  806. BX R3
  807. .align 2
  808. mixer_finished_status:
  809. .word 0x68736D53
  810. .arm
  811. downsampler:
  812. LDR R10, hq_buffer_label
  813. LDR R9, [SP, #ARG_BUFFER_POS]
  814. LDR R8, hq_buffer_length_label
  815. MOV R11, #0xFF
  816. .if PREVENT_CLIP==1
  817. MOV R12, #0xFFFFFFFF
  818. MOV R12, R12, LSL#14
  819. MOV R7, #0x630
  820. downsampler_loop:
  821. LDRSH R2, [R10], #2
  822. LDRSH R0, [R10], #2
  823. LDRSH R3, [R10], #2
  824. LDRSH R1, [R10], #2
  825. CMP R0, #0x4000
  826. MOVGE R0, #0x3F80
  827. CMP R0, #-0x4000
  828. MOVLT R0, R12
  829. CMP R1, #0x4000
  830. MOVGE R1, #0x3F80
  831. CMP R1, #-0x4000
  832. MOVLT R1, R12
  833. CMP R2, #0x4000
  834. MOVGE R2, #0x3F80
  835. CMP R2, #-0x4000
  836. MOVLT R2, R12
  837. CMP R3, #0x4000
  838. MOVGE R3, #0x3F80
  839. CMP R3, #-0x4000
  840. MOVLT R3, R12
  841. AND R0, R11, R0, ASR#7
  842. AND R1, R11, R1, ASR#7
  843. AND R2, R11, R2, ASR#7
  844. AND R3, R11, R3, ASR#7
  845. ORR R2, R2, R3, LSL#8
  846. ORR R0, R0, R1, LSL#8
  847. STRH R2, [R9, R7]
  848. STRH R0, [R9], #2
  849. SUBS R8, #2
  850. BGT downsampler_loop
  851. .else
  852. downsampler_loop:
  853. LDRH R4, [R10], #2
  854. LDRH R0, [R10], #2
  855. LDRH R5, [R10], #2
  856. LDRH R1, [R10], #2
  857. LDRH R6, [R10], #2
  858. LDRH R2, [R10], #2
  859. LDRH R7, [R10], #2
  860. LDRH R3, [R10], #2
  861. AND R0, R11, R0, LSR#7
  862. AND R1, R11, R1, LSR#7
  863. AND R2, R11, R2, LSR#7
  864. AND R3, R11, R3, LSR#7
  865. AND R4, R11, R4, LSR#7
  866. AND R5, R11, R5, LSR#7
  867. AND R6, R11, R6, LSR#7
  868. AND R7, R11, R7, LSR#7
  869. ORR R4, R4, R5, LSL#8
  870. ORR R4, R4, R6, LSL#16
  871. ORR R4, R4, R7, LSL#24
  872. ORR R0, R0, R1, LSL#8
  873. ORR R0, R0, R2, LSL#16
  874. ORR R0, R0, R3, LSL#24
  875. STR R4, [R9, #0x630]
  876. STR R0, [R9], #4
  877. SUBS R8, #4
  878. BGT downsampler_loop
  879. .endif
  880. ADR R0, (downsampler_return+1)
  881. BX R0
  882. .align 2
  883. init_synth:
  884. CMP R12, #0 @ $030057C4
  885. BNE check_synth_type
  886. LDRB R6, [R3, #SYNTH_WIDTH_CHANGE_1] @ for saw wave -> 0xF0 (base duty cycle change)
  887. ADD R2, R2, R6, LSL#24 @ add it to the current synt
  888. LDRB R6, [R3, #SYNTH_WIDTH_CHANGE_2] @ for saw wave -> 0x80 (base duty cycle change #2)
  889. ADDS R6, R2, R6, LSL#24 @ add this to the synth state aswell but keep the old value in R2 and put the new one in R6
  890. MVNMI R6, R6 @ negate if duty cycle is > 50%
  891. MOV R10, R6, LSR#8 @ dividide the final duty cycle by 8 to R10
  892. LDRB R1, [R3, #SYNTH_MOD_AMOUNT] @ for saw wave -> 0xE0
  893. LDRB R0, [R3, #SYNTH_BASE_WAVE_DUTY] @ for saw wave -> 0x10 (base duty cycle offset)
  894. MOV R0, R0, LSL#24 @ convert it to a usable duty cycle
  895. MLA R6, R10, R1, R0 @ calculate the final duty cycle with the offset, and intensity * rotating duty cycle amount
  896. STMFD SP!, {R2, R3, R9, R12}
  897. synth_type_0_loop:
  898. LDMIA R5, {R0-R3, R9, R10, R12, LR} @ load 8 samples
  899. CMP R7, R6 @ Block #1
  900. ADDCC R0, R0, R11, LSL#6
  901. SUBCS R0, R0, R11, LSL#6
  902. ADDS R7, R7, R4, LSL#3
  903. CMP R7, R6 @ Block #2
  904. ADDCC R1, R1, R11, LSL#6
  905. SUBCS R1, R1, R11, LSL#6
  906. ADDS R7, R7, R4, LSL#3
  907. CMP R7, R6 @ Block #3
  908. ADDCC R2, R2, R11, LSL#6
  909. SUBCS R2, R2, R11, LSL#6
  910. ADDS R7, R7, R4, LSL#3
  911. CMP R7, R6 @ Block #4
  912. ADDCC R3, R3, R11, LSL#6
  913. SUBCS R3, R3, R11, LSL#6
  914. ADDS R7, R7, R4, LSL#3
  915. CMP R7, R6 @ Block #5
  916. ADDCC R9, R9, R11, LSL#6
  917. SUBCS R9, R9, R11, LSL#6
  918. ADDS R7, R7, R4, LSL#3
  919. CMP R7, R6 @ Block #6
  920. ADDCC R10, R10, R11, LSL#6
  921. SUBCS R10, R10, R11, LSL#6
  922. ADDS R7, R7, R4, LSL#3
  923. CMP R7, R6 @ Block #7
  924. ADDCC R12, R12, R11, LSL#6
  925. SUBCS R12, R12, R11, LSL#6
  926. ADDS R7, R7, R4, LSL#3
  927. CMP R7, R6 @ Block #8
  928. ADDCC LR, LR, R11, LSL#6
  929. SUBCS LR, LR, R11, LSL#6
  930. ADDS R7, R7, R4, LSL#3
  931. STMIA R5!, {R0-R3, R9, R10, R12, LR} @ write 8 samples
  932. SUBS R8, R8, #8 @ remove #8 from sample count
  933. BGT synth_type_0_loop
  934. LDMFD SP!, {R2, R3, R9, R12}
  935. B mixing_end_func
  936. check_synth_type:
  937. SUBS R12, R12, #1 @ remove #1 from the synth type byte and check if it's #0
  938. BNE synth_type_2 @ if it still isn't it's synth type 2 (smooth pan flute)
  939. MOV R6, #0x300 @ R6 = 0x300
  940. MOV R11, R11, LSR#1 @ halve the volume
  941. BIC R11, R11, #0xFF00 @ clear bad bits from division
  942. MOV R12, #0x70 @ R12 = 0x70
  943. synth_type_1_loop:
  944. LDMIA R5, {R0, R1, R10, LR} @ load 4 samples from memory
  945. ADDS R7, R7, R4, LSL#3 @ Block #1 (some oscillator type code)
  946. RSB R9, R12, R7, LSR#24
  947. MOV R6, R7, LSL#1
  948. SUB R9, R9, R6, LSR#27
  949. ADDS R2, R9, R2, ASR#1
  950. MLANE R0, R11, R2, R0
  951. ADDS R7, R7, R4, LSL#3 @ Block #2
  952. RSB R9, R12, R7, LSR#24
  953. MOV R6, R7, LSL#1
  954. SUB R9, R9, R6, LSR#27
  955. ADDS R2, R9, R2, ASR#1
  956. MLANE R1, R11, R2, R1
  957. ADDS R7, R7, R4, LSL#3 @ Block #3
  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 R10, R11, R2, R10
  963. ADDS R7, R7, R4, LSL#3 @ Block #4
  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 LR, R11, R2, LR
  969. STMIA R5!, {R0, R1, R10, LR}
  970. SUBS R8, R8, #4
  971. BGT synth_type_1_loop
  972. B mixing_end_func @ goto end
  973. synth_type_2:
  974. MOV R6, #0x80 @ write base values to the registers
  975. MOV R12, #0x180
  976. synth_type_2_loop:
  977. LDMIA R5, {R0, R1, R10, LR} @ load samples from work buffer
  978. ADDS R7, R7, R4, LSL#3 @ Block #1
  979. RSBPL R9, R6, R7, ASR#23
  980. SUBMI R9, R12, R7, LSR#23
  981. MLA R0, R11, R9, R0
  982. ADDS R7, R7, R4, LSL#3 @ Block #2
  983. RSBPL R9, R6, R7, ASR#23
  984. SUBMI R9, R12, R7, LSR#23
  985. MLA R1, R11, R9, R1
  986. ADDS R7, R7, R4, LSL#3 @ Block #3
  987. RSBPL R9, R6, R7, ASR#23
  988. SUBMI R9, R12, R7, LSR#23
  989. MLA R10, R11, R9, R10
  990. ADDS R7, R7, R4, LSL#3 @ Block #4
  991. RSBPL R9, R6, R7, ASR#23
  992. SUBMI R9, R12, R7, LSR#23
  993. MLA LR, R11, R9, LR
  994. STMIA R5!, {R0, R1, R10, LR} @ store the samples back to the buffer
  995. SUBS R8, R8, #4 @ subtract #4 from the remainging samples
  996. BGT synth_type_2_loop
  997. B mixing_end_func
  998. @****************** SPECIAL MIXING ******************@
  999. .if ENABLE_DECOMPRESSION==1
  1000. special_mixing: @ $03006BF8
  1001. LDR R6, [R4, #CHN_WAVE_OFFSET] @ load the wave header offset to R6
  1002. LDRB R0, [R4]
  1003. TST R0, #FLAG_CHN_COMP @ check if the channel is initialized
  1004. BNE setup_compressed_mixing_frequency @ skip the setup procedure if it's running in compressed mode already
  1005. ORR R0, R0, #FLAG_CHN_COMP @ enable the flag in the channel status
  1006. STRB R0, [R4] @ store the channel status
  1007. LDRB R0, [R4, #CHN_MODE] @ load the channel mode byte
  1008. TST R0, #MODE_REVERSE @ check if reverse mode is not enabled
  1009. BEQ determine_compression @ if Reverse Mode isn't enabled we can directly check if the sample has to get decoded
  1010. LDR R1, [R6, #WAVE_LENGTH] @ load the amount of samples
  1011. ADD R1, R1, R6, LSL#1 @ do some start position calculation (???)
  1012. ADD R1, R1, #0x20
  1013. SUB R3, R1, R3
  1014. STR R3, [R4, #CHN_POSITION_ABS] @ store the final seek position
  1015. determine_compression:
  1016. LDRH R0, [R6] @ load the compression flag from the sample header
  1017. CMP R0, #0 @ check if the compression is not enabled
  1018. BEQ setup_compressed_mixing_frequency @ skip the compression handler
  1019. SUB R3, R3, R6 @ calc initial position
  1020. SUB R3, R3, #0x10
  1021. STR R3, [R4, #CHN_POSITION_ABS] @ store the inital position (relative, not absolute)
  1022. setup_compressed_mixing_frequency:
  1023. LDR R0, [R6, #WAVE_LOOP_START]
  1024. STR R0, [SP, #ARG_LOOP_START_POS]
  1025. STMFD SP!, {R4, R9, R12}
  1026. MOVS R11, R11, LSR#1 @ divide master volume by 2
  1027. ADC R11, R11, #0x8000
  1028. BIC R11, R11, #0xFF00
  1029. LDR R7, [R4, #CHN_FINE_POSITION] @ load the fine position
  1030. LDR R1, [R4, #CHN_FREQUENCY] @ load the channel frequency
  1031. LDRB R0, [R4, #CHN_MODE] @ load the channel mode again
  1032. TST R0, #MODE_FIXED_FREQ @ check if fixed frequency mode is enabled
  1033. MOVNE R1, #0x800000 @ ### SAMPLE STEP FREQUENCY CHANGED TO R7
  1034. MULEQ R1, R12, R1 @ default rate factor * frequency = sample steps
  1035. ADD R5, R5, R8, LSL#2 @ set the buffer pointer to the end of the channel
  1036. LDRH R0, [R6] @ load the codec type
  1037. CMP R0, #0 @ check if compression is disabled
  1038. BEQ uncompressed_mixing_reverse_check
  1039. MOV R0, #0xFF000000 @ set the current decoding block to "something very high" so that the first block always gets decoded
  1040. STR R0, [R4, #CHN_BLOCK_COUNT] @ write the last decoded block into the channel vars
  1041. LDRB R0, [R4, #CHN_MODE] @ check again if reverse mode is enabled
  1042. TST R0, #MODE_REVERSE @ test if reverse mode is enabled
  1043. BNE compressed_mixing_reverse_init @ check again of reverse mixing is enabled
  1044. BL bdpcm_decoder @ load a sample from the stream to R12
  1045. MOV R6, R12 @ move the base sample to R6
  1046. ADD R3, R3, #1 @ increase stream position by #1
  1047. BL bdpcm_decoder @ load the delta sample and calculate delta value
  1048. SUB R12, R12, R6
  1049. @***** MIXING LOOP REGISTER USAGE ***********@
  1050. @ R0: Sample to modify from buffer
  1051. @ R1: sample steps (MOVED FROM R4)
  1052. @ R2: remaining samples before loop/end
  1053. @ R3: sample position
  1054. @ R4: channel pointer
  1055. @ R5: pointer to the end of buffer
  1056. @ R6: Base sample
  1057. @ R7: fine position
  1058. @ R8: remaining samples for current buffer
  1059. @ R9: interpolated sample
  1060. @ R10: not used
  1061. @ R11: volume
  1062. @ R12: Delta Sample
  1063. @ LR: not used
  1064. @********************************************@
  1065. compressed_mixing_loop:
  1066. MUL R9, R7, R12 @ delta sample * fine position = interpolated DELTA
  1067. MOV R9, R9, ASR#22 @ scale down the sample
  1068. ADDS R9, R9, R6, LSL#1 @ double the base sample and add it to the interpolated downscaled DELTA
  1069. LDRNE R0, [R5, -R8, LSL#2] @ if the sample is NOT 0 load the sample from buffer and store the calulated value
  1070. MLANE R0, R11, R9, R0 @ add the sample to the buffer sample and apply volume
  1071. STRNE R0, [R5, -R8, LSL#2] @ store the sample if it's not Zero
  1072. ADD R7, R7, R1 @ ### changed from R4 to R1
  1073. MOVS R9, R7, LSR#23 @ check if there is new samples to load
  1074. BEQ compressed_mixing_load_skip @ no new samples need to be loaded
  1075. SUBS R2, R2, R7, LSR#23 @ remove the sample overflow from the remaining samples
  1076. BLLE loop_end_sub @ call the loop/ending handler if the countdown reached zero or something negative
  1077. SUBS R9, R9, #1 @ check if only one sample has to get loaded
  1078. ADDEQ R6, R12, R6 @ if this is the case we can calculate the new base sample
  1079. BEQ compressed_mixing_base_load_skip
  1080. ADD R3, R3, R9 @ these opcodes are equivalent to LDRNESB R6, [R3, R9]!
  1081. BL bdpcm_decoder
  1082. MOV R6, R12
  1083. compressed_mixing_base_load_skip:
  1084. ADD R3, R3, #1 @ equivalent to LDRSB R12, [R3, #1]!
  1085. BL bdpcm_decoder
  1086. SUB R12, R12, R6
  1087. BIC R7, R7, #0x3F800000 @ clear the overflow bits by using the according bitmask
  1088. compressed_mixing_load_skip:
  1089. SUBS R8, R8, #1 @ remove #1 from the remaining samples
  1090. BGT compressed_mixing_loop
  1091. @SUB R3, R3, #1 @ sample pointer -1 (???); ALREADY DONE BY mixing_end_func
  1092. B mixing_end_func
  1093. compressed_mixing_reverse_init:
  1094. SUB R3, R3, #1 @ subtract one from the reverse playback location initially
  1095. BL bdpcm_decoder @ fetch a sample from stream
  1096. MOV R6, R12 @ bdpcm_decoder returns base sample in R12 --> R6
  1097. SUB R3, R3, #1 @ seek one sample further backwards
  1098. BL bdpcm_decoder @ detch the DELTA sample
  1099. SUB R12, R12, R6 @ calc the Delta value
  1100. compressed_mixing_reverse_loop:
  1101. MUL R9, R7, R12 @ delta sample * fine position = interpolated DELTA
  1102. MOV R9, R9, ASR#22 @ scale down the sample
  1103. ADDS R9, R9, R6, LSL#1 @ double the base sample and add it to the interpolated downscaled DELTA
  1104. LDRNE R0, [R5, -R8, LSL#2] @ if the sample is NOT 0 load the sample from buffer and store the calulated value
  1105. MLANE R0, R11, R9, R0 @ add the sample to the buffer sample and apply volume
  1106. STRNE R0, [R5, -R8, LSL#2] @ store the sample if it's not Zero
  1107. ADD R7, R7, R1 @ ### changed from R4 to R1
  1108. MOVS R9, R7, LSR#23 @ check if there is new samples to load
  1109. BEQ compressed_mixing_reverse_load_skip @ skip sample loading if we don't need to load new samples from ROM
  1110. SUBS R2, R2, R7, LSR#23 @ remove the overflowed samples from the remaining samples
  1111. BLLE loop_end_sub @ if the sample playback finished go to end handler
  1112. SUBS R9, R9, #1 @ remove sample overflow count by #1
  1113. ADDEQ R6, R12, R6 @ make the previous delta sample the new base sample if only #1 sample needs to get loaded
  1114. BEQ compressed_mixing_reverse_base_load_skip @skip base sample loading
  1115. SUB R3, R3, R9 @
  1116. BL bdpcm_decoder @
  1117. MOV R6, R12 @
  1118. compressed_mixing_reverse_base_load_skip:
  1119. SUB R3, R3, #1
  1120. BL bdpcm_decoder
  1121. SUB R12, R12, R6 @ load next samples???
  1122. BIC R7, R7, #0x3F800000 @ clear overflow bits
  1123. compressed_mixing_reverse_load_skip:
  1124. SUBS R8, R8, #1
  1125. BGT compressed_mixing_reverse_loop
  1126. @ADD R3, R3, #2 @ ???, copied from original code
  1127. ADD R3, R3, #3
  1128. B mixing_end_func
  1129. uncompressed_mixing_reverse_check:
  1130. LDRB R0, [R4, #1] @ load the channel mode =$03006D84
  1131. TST R0, #MODE_REVERSE @ check if reverse mode is even enabled
  1132. BEQ mixing_end_func @ skip the channel if the mode is "akward"
  1133. LDRSB R6, [R3, #-1]! @ load first negative sample
  1134. LDRSB R12, [R3, #-1] @ load the DELTA sample
  1135. SUB R12, R12, R6 @ calculate DELTA
  1136. reverse_mixing_loop:
  1137. MUL R9, R7, R12 @ delta sample * fine position = interpolated DELTA
  1138. MOV R9, R9, ASR#22 @ scale down the sample
  1139. ADDS R9, R9, R6, LSL#1 @ double the base sample and add it to the interpolated downscaled DELTA
  1140. LDRNE R0, [R5, -R8, LSL#2] @ if the sample is NOT 0 load the sample from buffer and store the calulated value
  1141. MLANE R0, R11, R9, R0 @ add the sample to the buffer sample and apply volume
  1142. STRNE R0, [R5, -R8, LSL#2] @ store the sample if it's not Zero
  1143. ADD R7, R7, R1 @ ### changed from R4 to R1
  1144. MOVS R9, R7, LSR#23 @ check if there is new samples to load
  1145. BEQ reverse_mixing_load_skip
  1146. SUBS R2, R2, R7, LSR#23 @ blablabla, all same as above
  1147. BLLE loop_end_sub
  1148. MOVS R9, R9 @ check if sample
  1149. ADDEQ R6, R12, R6
  1150. LDRNESB R6, [R3, -R9]!
  1151. LDRSB R12, [R3, #-1] @ load samples dependent on conditions
  1152. SUB R12, R12, R6
  1153. BIC R7, R7, #0x3F800000 @ cut off overflow count to get new fine position
  1154. reverse_mixing_load_skip:
  1155. SUBS R8, R8, #1 @ remaining samples -1
  1156. BGT reverse_mixing_loop @ continue lopo if there is still samples to process
  1157. @ADD R3, R3, #1 @ copied from original code (???)
  1158. ADD R3, R3, #2 @ =$03006DE8
  1159. B mixing_end_func
  1160. @**************** SPECIAL MIXING END ****************@
  1161. @************** SPECIAL MIXING LOOPING **************@
  1162. compressed_loop_end_sub:
  1163. @************ SPECIAL MIXING LOOPING END ************@
  1164. @****************** BDPCM DEOCODER ******************@
  1165. bdpcm_decoder: @ RETURNS SAMPLE FROM POSITION XXX in R12
  1166. STMFD SP!, {R0, R2, R5-R7, LR} @ push registers to make them free to use: R0, R2, R5, R6, R7, LR
  1167. MOV R0, R3, LSR#6 @ shift the relative position over to clip of every but the block offset
  1168. LDR R12, [R4, #CHN_BLOCK_COUNT] @ check if the current sample position is at the beginning of the current block
  1169. CMP R0, R12
  1170. BEQ bdpcm_decoder_return
  1171. STR R0, [R4, #CHN_BLOCK_COUNT] @ store the block position to Channel Vars
  1172. MOV R12, #0x21 @ load decoding byte count to R1 (1 Block = 0x21 Bytes)
  1173. MUL R2, R12, R0 @ multiply the block count with the block length to calc actual byte position of current block
  1174. LDR R12, [R4, #CHN_WAVE_OFFSET] @ load the wave data offset to R1
  1175. ADD R2, R2, R12 @ add the wave data offset and 0x10 to get the actual position in ROM
  1176. ADD R2, R2, #0x10 @
  1177. LDR R5, decoder_buffer @ load the decoder buffer pointer to R5
  1178. ADR R6, delta_lookup_table @ load the lookup table pointer to R6
  1179. MOV R7, #0x40 @ load the block sample count (0x40) to R7
  1180. LDRB LR, [R2], #1 @ load the first byte & sample from the wave data to LR (each block starts with a signed 8 bit pcm sample) LDRSB not necessary due to the 24 high bits being cut off anyway
  1181. STRB LR, [R5], #1 @ write the sample to the decoder buffer
  1182. LDRB R12, [R2], #1 @ load the next 2 samples to R1 (to get decoded) --- LSBits is decoded first and MSBits last
  1183. B bdpcm_decoder_lsb
  1184. bdpcm_decoder_msb:
  1185. LDRB R12, [R2], #1 @ load the next 2 samples to get decoded
  1186. MOV R0, R12, LSR#4 @ seperate the current samples' bits
  1187. LDRSB R0, [R6, R0] @ load the differential value from the lookup table
  1188. ADD LR, LR, R0 @ add the decoded value to the previous sample value to calc the current samples' level
  1189. STRB LR, [R5], #1 @ write the output sample to the decoder buffer and increment buffer pointer
  1190. bdpcm_decoder_lsb:
  1191. AND R0, R12, #0xF @ seperate the 4 LSBits
  1192. LDRSB R0, [R6, R0] @ but the 4 bit value into the lookup table and save the result to R0
  1193. ADD LR, LR, R0 @ add the value from the lookup table to the previous value to calc the new one
  1194. STRB LR, [R5], #1 @ store the decoded sample to the decoding buffer
  1195. SUBS R7, R7, #2 @ decrease the block sample counter by 2 (2 samples each byte) and check if it is still above 0
  1196. BGT bdpcm_decoder_msb @ if there is still samples to decode jump to the MSBits
  1197. bdpcm_decoder_return:
  1198. LDR R5, decoder_buffer @ reload the decompressor buffer offset to R5
  1199. AND R0, R3, #0x3F @ cut off the main position bits to read data from short buffer
  1200. LDRSB R12, [R5, R0] @ read the decoded sample from buffer
  1201. LDMFD SP!, {R0, R2, R5-R7, PC} @ pop registers and return to the compressed sample mixer
  1202. @**************** END BDPCM DECODER *****************@
  1203. decoder_buffer:
  1204. .word decoder_buffer_target
  1205. delta_lookup_table:
  1206. .byte 0x0, 0x1, 0x4, 0x9, 0x10, 0x19, 0x24, 0x31, 0xC0, 0xCF, 0xDC, 0xE7, 0xF0, 0xF7, 0xFC, 0xFF
  1207. .endif
  1208. main_mixer_end:
  1209. .end