Pokemon Center | 口袋中心 以口袋妖怪为主题并带有其他动漫游戏的讨论

 找回密码
 加入口袋中心
搜索
查看: 1927|回复: 3

【改版基础教程#2】ipatix的高音质混音器

[复制链接]

3333

回帖

551

现金

427

勋章券

超级版主

Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26

积分
20820
QQ

时光印记Lv.3挥金如土勋章水中王者勋章Lv3Omega红宝石发售确认纪念章Alpha蓝宝石发售确认纪念章金银好CP-Ho-oh/LUGIA【里】金银好CP-Ho-oh/LUGIA【真·正常向】异化型LUGIA【M超梦版】

发表于 2017-1-19 18:42:48 | 显示全部楼层 |阅读模式
本帖最后由 jiangzhengwenjz 于 2017-1-19 18:45 编辑

首先告诫大家一下,发帖一定要备份不要在线弄,一不小心之前写完的又都消掉了。

原贴:https://www.pokecommunity.com/showthread.php?t=324673
标题:ipatix' High Quality Sound Mixer
作者:ipatix
本帖不得转载,转载英文原贴务必自觉注明网址!

1. 介绍
    大量GBA游戏中混音系统都是用的sdk中的引擎,但这个引擎的噪音现象较为严重,虽然在火红中体现不明显,不过如果扩充了directsound的音轨数量的话这个缺陷就不容忽视了,所以ipatix自己开发了一个混音器。

2. 如何实现
首先要先编译二楼的源码并写入空位(这个是稍微修改过后的,原先那个说起来比较麻烦,这个可用mixer_size标签)(发在二楼是因为字数限制)

写入完了后,搜索ROM中所有0x3005F50的指针并改为0x203E000的指针,以作为新的PCM工作区。(要用这个空位须先取消帮助系统,在0x13b8c2写入1D E0)

接下来在0x1DD0B4写入编译好的混音器源码的指针,不用+1。

搜索ROM中所有0x30028E0和0x30028E1的指针并分别改为0x3005F50和0x3005F51的指针,这个是利用了已经不被使用的IWRAM空间。

之后在0x1DD0BC写入混音器源码编译后的字节数/4,或者直接用mixer_size的数值。应当为0x2C9(C9 02)

最后在0x1DD0C9写入CC以扩充directsound音轨数量为12。

这样就全部完成了,可进入游戏试听,效果还是比较明显的。下篇教程将会介绍些音乐修改方面的基础,不过想深入原理性的东西短期内应该做不到。

3. 感谢
Sturmvogel整理源码



有任何错误请回帖指出
回复

使用道具 举报

3333

回帖

551

现金

427

勋章券

超级版主

Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26

积分
20820
QQ

时光印记Lv.3挥金如土勋章水中王者勋章Lv3Omega红宝石发售确认纪念章Alpha蓝宝石发售确认纪念章金银好CP-Ho-oh/LUGIA【里】金银好CP-Ho-oh/LUGIA【真·正常向】异化型LUGIA【M超梦版】

 楼主| 发表于 2017-1-19 18:44:28 | 显示全部楼层
  1. @ created by ~ipatix~

  2.         .global mixer_size
  3.         .global        main_mixer
  4.         .global        main_mixer_end
  5.        
  6.         .set mixer_size,(main_mixer_end - main_mixer) / 4

  7.         .equ        GAME_BPED, 0
  8.         .equ        GAME_BPEE, 1
  9.         .equ        GAME_BPRE, 2
  10.         .equ        GAME_KWJ6, 3

  11. @ SELECT USED GAME HERE

  12.         .equ        USED_GAME, GAME_BPRE                                @ CHOOSE YOUR GAME

  13.         .equ        FRAME_LENGTH_5734, 0x60
  14.         .equ        FRAME_LENGTH_7884, 0x84        @ THIS MODE IS NOT SUPPORTED BY THIS ENGINE BECAUSE IT DOESN'T USE AN 8 ALIGNED BUFFER LENGTH
  15.         .equ        FRAME_LENGTH_10512, 0xB0
  16.         .equ        FRAME_LENGTH_13379, 0xE0                        @ DEFAULT
  17.         .equ        FRAME_LENGTH_15768, 0x108
  18.         .equ        FRAME_LENGTH_18157, 0x130
  19.         .equ        FRAME_LENGTH_21024, 0x160
  20.         .equ        FRAME_LENGTH_26758, 0x1C0
  21.         .equ        FRAME_LENGTH_31536, 0x210
  22.         .equ        FRAME_LENGTH_36314, 0x260
  23.         .equ        FRAME_LENGTH_40137, 0x2A0
  24.         .equ        FRAME_LENGTH_42048, 0x2C0

  25.         .equ        DECODER_BUFFER_BPE, 0x03001300
  26.         .equ        DECODER_BUFFER_BPR, 0x03002088
  27.         .equ        DECODER_BUFFER_KWJ, 0x03005800

  28.         .equ        FREE_IRAM_BPE, 0x03001AA8
  29.         .equ        FREE_IRAM_BPR, 0x030028E0
  30.         .equ        FREE_IRAM_KWJ, 0x03005840


  31.         .equ        ARG_FRAME_LENGTH, 0x0
  32.         .equ        ARG_REMAIN_CHN, 0x4
  33.         .equ        ARG_BUFFER_POS, 0x8
  34.         .equ        ARG_LOOP_START_POS, 0xC
  35.         .equ        ARG_LOOP_LENGTH, 0x10
  36.         .equ        ARG_VAR_AREA, 0x18

  37.         .equ        CHN_STATUS, 0x0
  38.         .equ        CHN_MODE, 0x1
  39.         .equ        CHN_VOL_1, 0x2
  40.         .equ        CHN_VOL_2, 0x3
  41.         .equ        CHN_ATTACK, 0x4
  42.         .equ        CHN_DECAY, 0x5
  43.         .equ        CHN_SUSTAIN, 0x6
  44.         .equ        CHN_RELEASE, 0x7
  45.         .equ        CHN_ADSR_LEVEL, 0x9
  46.         .equ        CHN_FINAL_VOL_1, 0xA                                @ not used anymore
  47.         .equ        CHN_FINAL_VOL_2, 0xB                                @ not used anymore
  48.         .equ        CHN_ECHO_VOL, 0xC
  49.         .equ        CHN_ECHO_REMAIN, 0xD
  50.         .equ        CHN_POSITION_REL, 0x18                                @ RELATIVE FOR COMPRESSED SAMPLES (decrementing)
  51.         .equ        CHN_FINE_POSITION, 0x1C
  52.         .equ        CHN_FREQUENCY, 0x20
  53.         .equ        CHN_WAVE_OFFSET, 0x24
  54.         .equ        CHN_POSITION_ABS, 0x28                                @ RELATIVE FOR COMPRESSED SAMPLES (incrementing)
  55.         .equ        CHN_BLOCK_COUNT, 0x3C

  56.         .equ        WAVE_LOOP_FLAG, 0x3
  57.         .equ        WAVE_FREQ, 0x4
  58.         .equ        WAVE_LOOP_START, 0x8
  59.         .equ        WAVE_LENGTH, 0xC

  60.         .equ        SYNTH_BASE_WAVE_DUTY, 0x1
  61.         .equ        SYNTH_WIDTH_CHANGE_1, 0x2
  62.         .equ        SYNTH_MOD_AMOUNT, 0x3
  63.         .equ        SYNTH_WIDTH_CHANGE_2, 0x4

  64.         .equ        FLAG_CHN_INIT, 0x80
  65.         .equ        FLAG_CHN_RELEASE, 0x40
  66.         .equ        FLAG_CHN_COMP, 0x20
  67.         .equ        FLAG_CHN_LOOP, 0x10
  68.         .equ        FLAG_CHN_ECHO, 0x4
  69.         .equ        FLAG_CHN_ATTACK, 0x3
  70.         .equ        FLAG_CHN_DECAY, 0x2
  71.         .equ        FLAG_CHN_SUSTAIN, 0x1

  72.         .equ        MODE_FIXED_FREQ, 0x8
  73.         .equ        MODE_REVERSE, 0x10
  74.         .equ        MODE_COMP, 0x30
  75.         .equ        MODE_SYNTH, 0x40

  76.         .equ        VAR_REVERB, 0x5
  77.         .equ        VAR_MAX_CHN, 0x6
  78.         .equ        VAR_MASTER_VOL, 0x7
  79.         .equ        VAR_DEF_PITCH_FAC, 0x18
  80.         .equ        VAR_FIRST_CHN, 0x50

  81.         .equ        REG_DMA3_SRC, 0x040000D4

  82. @#######################################
  83. @*********** GAME CONFIGS **************
  84. @ add the game's name above to the ASM .equ-s before creating new configs
  85. @#######################################


  86. @*********** IF BPED
  87. .if USED_GAME==GAME_BPED

  88.         .equ        hq_buffer, FREE_IRAM_BPE
  89.         .equ        decoder_buffer_target, DECODER_BUFFER_BPE
  90.         .equ        ALLOW_PAUSE, 1
  91.         .equ        DMA_FIX, 1
  92.         .equ        ENABLE_DECOMPRESSION, 1
  93.         .equ        ENABLE_FM, 0
  94.         .equ        PREVENT_CLIP, 0

  95. .endif
  96. @*********** IF BPEE
  97. .if USED_GAME==GAME_BPEE

  98.         .equ        hq_buffer, FREE_IRAM_BPE
  99.         .equ        decoder_buffer_target, DECODER_BUFFER_BPE
  100.         .equ        ALLOW_PAUSE, 1
  101.         .equ        DMA_FIX, 1
  102.         .equ        ENABLE_DECOMPRESSION, 1
  103.         .equ        ENABLE_FM, 0
  104.         .equ        PREVENT_CLIP, 1

  105. .endif
  106. @*********** IF BPRE
  107. .if USED_GAME==GAME_BPRE

  108.         .equ        hq_buffer, FREE_IRAM_BPR
  109.         .equ        decoder_buffer_target, DECODER_BUFFER_BPR
  110.         .equ        ALLOW_PAUSE, 1
  111.         .equ        DMA_FIX, 1
  112.         .equ        ENABLE_DECOMPRESSION, 1
  113.         .equ        ENABLE_FM, 0
  114.         .equ        PREVENT_CLIP, 1

  115. .endif
  116. @*********** IF KWJ6
  117. .if USED_GAME==GAME_KWJ6

  118.         .equ        hq_buffer, FREE_IRAM_KWJ
  119.         .equ        decoder_buffer_target, DECODER_BUFFER_KWJ
  120.         .equ        ALLOW_PAUSE, 0
  121.         .equ        DMA_FIX, 0
  122.         .equ        ENABLE_DECOMPRESSION, 0
  123.         .equ        ENABLE_FM, 0
  124.         .equ        PREVENT_CLIP, 1

  125. .endif
  126. @***********

  127.         .thumb

  128. main_mixer:

  129. LDRB        R3, [R0, #VAR_REVERB]
  130. LSR        R3, R3, #2
  131. @CMP        R3, #0
  132. BEQ        clear_buffer

  133. ADR        R1, do_reverb
  134. BX        R1

  135.         .align        2
  136.         .arm

  137. do_reverb:

  138. CMP        R4, #2
  139. ADDEQ        R7, R0, #0x350
  140. ADDNE        R7, R5, R8
  141. MOV        R4, R8

  142. ORR        R3, R3, R3, LSL#16                        @ turn on reverb for both s

  143. STMFD        SP!, {R8, LR}

  144. LDR        LR, hq_buffer_label

  145. @ R00:        VAR AREA (not used) ... OK
  146. @ R01:        Function Pointer (not used) ... OK
  147. @ R02:        not consistent (not used) ... OK
  148. @ R03:        Reverb ;NEEDED!!!
  149. @ R04:        Countdown Sample ;NEEDED!!!
  150. @ R05:        Sample Pointer, low Res Buffer ;NEEDED!!!
  151. @ R06:        Buffer Spacing; not needed ; NEEDED!!!
  152. @ R07:        previous buffer pointer, low Res Buffer ;NEEDED!!!
  153. @ R08:        Frame Length (not used) (PUSH) ... OK
  154. @ R09:        not used ... OK
  155. @ R10:        not used ... OK
  156. @ R11:        not used ... OK
  157. @ R12:        not used ... OK
  158. @ LR:        not needed ... OK


  159. reverb_loop:

  160. LDRSB        R0, [R5, R6]
  161. LDRSB        R1, [R5], #1
  162. LDRSB        R2, [R7, R6]
  163. LDRSB        R8, [R7], #1
  164. LDRSB        R9, [R5, R6]
  165. LDRSB        R10, [R5], #1
  166. LDRSB        R11, [R7, R6]
  167. LDRSB        R12, [R7], #1
  168. ADD        R0, R0, R1
  169. ADD        R0, R0, R2
  170. ADDS        R0, R0, R8
  171. ADDMI        R0, R0, #0x4
  172. ADD        R1, R9, R10
  173. ADD        R1, R1, R11
  174. ADDS        R1, R1, R12
  175. ADDMI        R1, R1, #0x4
  176. MUL        R0, R3, R0
  177. MUL        R1, R3, R1
  178. STMIA        LR!, {R0, R1}
  179. SUBS        R4, R4, #2

  180. BGT        reverb_loop

  181. LDMFD        SP!, {R8, LR}

  182. ADR        R0, (adsr_setup+1)
  183. BX        R0

  184.         .thumb

  185. clear_buffer:

  186. LDR        R3, hq_buffer_label
  187. MOV        R1, R8
  188. MOV        R4, #0
  189. MOV        R5, #0
  190. MOV        R6, #0
  191. MOV        R7, #0

  192. LSR        R1, #3
  193. BCC        clear_buffer_align_8

  194. STMIA        R3!, {R4, R5, R6, R7}

  195. clear_buffer_align_8:

  196. LSR        R1, #1
  197. BCC        clear_buffer_align_16

  198. STMIA        R3!, {R4, R5, R6, R7}
  199. STMIA        R3!, {R4, R5, R6, R7}

  200. clear_buffer_align_16:

  201. STMIA        R3!, {R4, R5, R6, R7}
  202. STMIA        R3!, {R4, R5, R6, R7}
  203. STMIA        R3!, {R4, R5, R6, R7}
  204. STMIA        R3!, {R4, R5, R6, R7}

  205. SUB        R1, #1
  206. BGT        clear_buffer_align_16

  207. adsr_setup:

  208. MOV        R4, R8
  209. ADR        R0, hq_buffer_length_label
  210. STR        R4, [R0]

  211. @adsr_setup:

  212. LDR        R4, [SP, #ARG_VAR_AREA]                        @ load ARG_0x18 (main var area) to R4
  213. LDR        R0, [R4, #VAR_DEF_PITCH_FAC]                @ load samplingrate pitch factor value to R0
  214. MOV        R12, R0                                        @ copy factor to R12
  215. LDRB        R0, [R4, #VAR_MAX_CHN]                        @ load MAX channels to R0
  216. ADD        R4, #VAR_FIRST_CHN                        @ R4 == Base channel Offset (Channel 0)

  217. mixer_entry:
  218. STR        R0, [SP, #ARG_REMAIN_CHN]                        @ store the channels to work with on stack (probably given by calling function)
  219. LDR        R3, [R4, #CHN_WAVE_OFFSET]                        @ load the Wave Data Offset to R3
  220. LDRB        R6, [R4]                                        @ get the channel status indicator to R6
  221. MOVS        R0, #0xC7                                        @ check if any of the channel status flags is set
  222. TST        R0, R6                                                @ check if none of the flags is set
  223. BEQ        return_channel_null                                @ end the channel loop and disable the channel

  224. LSL        R0, R6, #0x19                                        @ shift over the channel status by 0x19/25 Bits
  225. BCC        adsr_echo_check                                        @ continue with normal channel procedure

  226. BMI        stop_channel_handler                                @ if the channel is initiated but on release it gets turned off immediatley

  227. MOVS        R6, #FLAG_CHN_ATTACK                                @ set the channel status to ATTACK
  228. MOVS        R0, R3                                                @ copy the wave offset to R0
  229. ADD        R0, #0x10                                        @ Add 0x10 to result the actual beginning of the wave data

  230. @**************** Other Games ******************@
  231. .if ALLOW_PAUSE==0
  232. STR        R0, [R4, #CHN_POSITION_ABS]                        @ store the absolute channel position to the CHN Vars
  233. LDR        R0, [R3, #WAVE_LENGTH]                                @ load the wave length to R0
  234. STR        R0, [R4, #CHN_POSITION_REL]                        @ store it as the remaining samples in the CHN Vars
  235. .endif
  236. @************** End Other Games ****************@

  237. @*************** Pokemon Games *****************@
  238. .if ALLOW_PAUSE==1
  239. LDR        R1, [R4, #CHN_POSITION_REL]                @ load sample position into R1
  240. ADD        R0, R0, R1                                @ add it to the base offset
  241. STR        R0, [R4, #CHN_POSITION_ABS]                @ write the current sample position to 0x28 of channel in array
  242. LDR        R0, [R3, #WAVE_LENGTH]                        @ load sample length into R0
  243. SUB        R0, R0, R1                                @ R0 = Samples left (if it's 0 the end of sample is reached)
  244. STR        R0, [R4, #CHN_POSITION_REL]                @ Write samples left into Relative Channel Position Variable in Channel
  245. .endif
  246. @************* End Pokemon Games ***************@

  247. MOVS        R5, #0                                                @ set the initial envelope to #0
  248. STRB        R5, [R4, #CHN_ADSR_LEVEL]                        @ write it to the adsr level slot
  249. STR        R5, [R4, #CHN_FINE_POSITION]                        @ set the fine position to #0 aswell
  250. LDRB        R2, [R3, #WAVE_LOOP_FLAG]                        @ load the loop indicator to R2
  251. LSR        R0, R2, #6                                        @ if loop is disabled result is EQ
  252. BEQ        adsr_attack_handler

  253. MOVS        R0, #FLAG_CHN_LOOP                                @ load the channel loop flag to R0
  254. ORR        R6, R0                                                @ set the Loop Flag in the channel status
  255. B        adsr_attack_handler

  256. adsr_echo_check:

  257. LDRB        R5, [R4, #CHN_ADSR_LEVEL]                        @ load the current ADSR Level
  258. LSL        R0, R6, #0x1D                                        @ shift the echo flag to the leftmost bit
  259. BPL        adsr_release_check                                        @ if the echo bit is NOT set go to label

  260. LDRB        R0, [R4, #CHN_ECHO_REMAIN]                        @ load the remaining echo to R0
  261. SUB        R0, #1                                                        @ reduce the remaining echo by #1
  262. STRB        R0, [R4, #CHN_ECHO_REMAIN]                        @ store it again
  263. BHI        channel_vol_calc                                @ if the echo has not gone to #0 go over to vol calc

  264. stop_channel_handler:

  265. MOVS        R0, #0                                                @ load NULL channel status to R0
  266. STRB        R0, [R4]                                        @ store it to the channel status

  267. return_channel_null:

  268. B        check_remain_channels

  269. adsr_release_check:
  270. LSL        R0, R6, #0x19                                        @ move the release flag bit over to the leftmost bit
  271. BPL        adsr_decay_check                                @ if the bit is NOT set go over to regular envelope handler

  272. LDRB        R0, [R4, #CHN_RELEASE]                                @ load the release value
  273. @SUB        R0, #0xFF
  274. @SUB        R0, #1                                                @ reduce the release value by 256
  275. @ADD        R5, R5, R0                                        @ add the result to the adsr level (linear decay)
  276. MUL        R5, R5, R0                @ default release algorithm
  277. LSR        R5, R5, #8
  278. @BMI        adsr_released_handler
  279. BEQ        adsr_released_handler        @ neccessary for the other release algorithm

  280. LDRB        R0, [R4, #CHN_ECHO_VOL]                                @ load echo vol to R0
  281. CMP        R5, R0                                                @ check if the adsr level has fallen below the echo vol
  282. BHI        channel_vol_calc

  283. adsr_released_handler:

  284. LDRB        R5, [R4, #CHN_ECHO_VOL]                                @ load the echo vol again
  285. CMP        R5, #0                                                @ check if it's zero
  286. BEQ        stop_channel_handler                                @ stop the channel if it isn't used

  287. MOVS        R0, #FLAG_CHN_ECHO                                @ load the echo flag to R0
  288. ORR        R6, R0                                                @ set the echo flag
  289. B        adsr_update_status

  290. adsr_decay_check:

  291. MOVS        R2, #3                                                @ seperate phase bits
  292. AND        R2, R6                                                @
  293. CMP        R2, #FLAG_CHN_DECAY                                @ check if channel NOT in decay state
  294. BNE        adsr_attack_check                                @ goto if decay NOT active

  295. LDRB        R0, [R4, #CHN_DECAY]                                @ load the decay value to R0
  296. MUL        R5, R0                                                @ apply the decay
  297. LSR        R5, R5, #8
  298. LDRB        R0, [R4, #CHN_SUSTAIN]                                @ load the sutain level
  299. CMP        R5, R0                                                @ has the sample not fully decayed yet?
  300. BHI        channel_vol_calc                                @ if it didn't decay yet goto

  301. MOVS        R5, R0                                                @ move the sustin level on underflow to adsr level and check if the result is #0 (i.e. channel = off)
  302. BEQ        adsr_released_handler

  303. B        adsr_switchto_next

  304. adsr_attack_check:

  305. CMP        R2, #FLAG_CHN_ATTACK                                @ check if attack is enabled
  306. BNE        channel_vol_calc                                @ if it isn't in attack attack phase, it has to be in sustain (no adsr change needed) -> go over to vol calc

  307. adsr_attack_handler:

  308. LDRB        R0, [R4, #CHN_ATTACK]                                @ load the attack value to R0
  309. ADD        R5, R5, R0                                        @ add the attack value to the adsr value
  310. CMP        R5, #0xFF                                        @ check if the adsr level is below 0xFF
  311. BCC        adsr_update_status                                @ store the value if it hasn't overflowed

  312. MOVS        R5, #0xFF                                        @ write MAX level to adsr level if it did overflow

  313. adsr_switchto_next:

  314. SUB        R6, #1                                                @ switch to the next adsr state

  315. adsr_update_status:

  316. STRB        R6, [R4]                                        @ store the channel state

  317. channel_vol_calc:

  318. STRB        R5, [R4, #CHN_ADSR_LEVEL]                        @ store the adsr level

  319. LDR        R0, [SP, #ARG_VAR_AREA]                                @ apply master volume
  320. LDRB        R0, [R0, #VAR_MASTER_VOL]
  321. ADD        R0, #1
  322. MUL        R5, R0, R5

  323. LDRB        R0, [R4, #CHN_VOL_2]                                @ load volume #1 to R0
  324. MUL        R0, R5                                                @ mutiply it with the adsr level
  325. LSR        R0, R0, #13                                        @ convert it to an 8 bit volume level
  326. MOV        R10, R0                                                @ store vol #1 to R10

  327. LDRB        R0, [R4, #CHN_VOL_1]                                @ load volume #2 to R0
  328. MUL        R0, R5                                                @ apply adsr to vol #2
  329. LSR        R0, R0, #13                                        @ scale it down to an 8bit value
  330. MOV        R11, R0                                                @ store it into R11 (vol#2)

  331. MOVS        R0, #FLAG_CHN_LOOP                                @ ist loop enabled?
  332. AND        R0, R6                                                @
  333. BEQ        mixing_loop_setup                                @ skip the loop setup procedure if it's disabled

  334. ADD        R3, #8                                                @ add 8 to the sample pointer (loop start)
  335. LDMIA        R3!, {R0, R1}                                        @ load loop start position to R0 and sample end to R1
  336. ADD        R3, R0, R3                                        @ R3 = loop start position (absolute)
  337. STR        R3, [SP, #ARG_LOOP_START_POS]                        @ store loop start position
  338. SUB        R0, R1, R0

  339. mixing_loop_setup:

  340. STR        R0, [SP, #ARG_LOOP_LENGTH]                        @ store the loop length (if loop is off ==> = 0x0)
  341. LDR        R5, hq_buffer_label                                        @ load the hq_buffer offset
  342. LDR        R2, [R4, #CHN_POSITION_REL]                        @ load the remaining samples for channel
  343. LDR        R3, [R4, #CHN_POSITION_ABS]                        @ load current stream position (abs)
  344. LDRB        R0, [R4, #CHN_MODE]                                @ load channel mode to R0
  345. ADR        R1, mixing_arm_setup
  346. BX        R1                                                @ jump to the arm procedure

  347.         .align        2
  348. hq_buffer_label:
  349.         .word        hq_buffer
  350. hq_buffer_length_label:
  351.         .word        0xFFFFFFFF

  352.         .arm

  353. mixing_arm_setup:

  354. LDR        R8, hq_buffer_length_label                                @ write MAX samples per frame to R8
  355. ORRS        R11, R10, R11, LSL#16                                @ write Vol #2 to the high 16 bits and combine them in one word
  356. BEQ        switchto_thumb                                        @ if volume is #0 for both channels we don't need to do any mixing and skip the mixing loop

  357. TST        R0, #MODE_FIXED_FREQ                                @ check if fixed freq mode is enabled
  358. BNE        fixed_mixing_setup                                @ if the flag is set enter the fixed freq mixing mode
  359. TST        R0, #MODE_COMP                                        @ ### added compression check
  360. BNE        special_mixing                                        @ goto the special mixing handler if reverse playback ir compression is enabled

  361. STMFD        SP!, {R4, R9, R12}                                @ free up some registers
  362. MOVS        R2, R2                                                @ if remaining samples == 2
  363. ORREQ        R0, R0, #MODE_SYNTH                                @ set the SYNTH flag if sample header is both 0
  364. STREQB        R0, [R4, #CHN_MODE]                                @ store the channel mode again
  365. ADD        R4, R4, #0x1C                                        @ add 0x1C to channel pointer
  366. LDMIA        R4, {R7, LR}                                        @ R7 = Fine Position, LR = Frequency
  367. MUL        R4, R12, LR                                        @ calc final frequency steps by multiplying the Default Frequency Facotr from R12 with the actual frequency
  368. LDRSB        R6, [R3], #1                                        @ load the first sample and increment the sample pointer
  369. LDRSB        R12, [R3]                                        @ load the next sample for interpolation
  370. TST        R0, #MODE_SYNTH                                        @ is the Synth Mode enabled?
  371. BNE        init_synth

  372. SUB        R12, R12, R6                                        @ R12 = DELTA
  373. MOVS        R11, R11, LSR#1                                        @ move the volume level over one bit to the right
  374. ADC        R11, R11, #0x8000                                @ halve both volume levels
  375. BIC        R11, R11, #0xFF00                                @ remove bit 15 if it is set
  376. MOV        R1, R7                                                @ save the fine position in R1
  377. UMLAL        R1, R0, R4, R8                                        @ multiply the sample amount per frame with the step frequency
  378. MOV        R1, R1, LSR#23                                        @ divide the result by 0x800000 LONG DIVISION
  379. ORR        R0, R1, R0, LSL#9                                @ Are less samples needed than there is actually needed to fill the buffer
  380. CMP        R2, R0                                                @ can we load a chunk of data without interruption to fill the buffer?
  381. BLE        split_sample_loading                                @ always jump

  382. SUB        R2, R2, R0                                        @ calculate remaining samples after this channel processing (to write it back to memory)
  383. LDR        R10, stack_capacity                                @ load some work area address to R10
  384. ADD        R10, R10, R0                                        @ place the work area pointer at the actual staart position
  385. CMP        R10, SP                                                @ check if R10 is within the stack
  386. ADD        R10, R3, R0                                        @ place the sample pointer end in R10
  387. ADR        R9, custom_stack_3                                @ load the custom stack to R9
  388. STMIA        R9, {R2, R10, SP}                                @ backup the sample block length, the end of sample and SP
  389. CMPCC        R0, #0x400                                        @ check if the block length is above #0x400 (too long)
  390. BCS        select_mixing_mode

  391. BIC        R1, R3, #3                                        @ write a word aligned address to R1
  392. MOV        R9, #0x04000000                                        @ write the DMA3 Sourceaddress
  393. ADD        R9, R9, #0xD4                                        @

  394. ADD        R0, R0, #7                                        @ add #7 to block length
  395. MOV        R0, R0, LSR#2                                        @ do a word alignment ont R0
  396. SUB         SP, SP, R0, LSL#2                                @ calculate the final destination location for the DMA
  397. AND        R3, R3, #3                                        @ restore the alignment error to R3
  398. ADD        R3, R3, SP                                        @ store the sample start position from the dma buffer in R3
  399. ORR        LR, R0, #0x84000000                                @ add the block length + #0x84000000 (DMA INIT Value) to LR
  400. STMIA        R9, {R1, SP, LR}                                @ write the DMA values to the IO registers and copy data


  401. .if DMA_FIX==1                                                        @ ### DMA Fix
  402. MOV        R0, #0
  403. MOV        R1, R0
  404. MOV        R2, R1
  405. STMIA        R9, {R0, R1, R2}
  406. .endif

  407. select_mixing_mode:

  408. SUBS        R4, R4, #0x800000                                @ check if sampling factor is lower than default rate
  409. MOVPL        R11, R11, LSL#1                                        @ multiply volume levels by #2 if condition is ture
  410. ADR        R0, math_resources                                @ load a functiom pointer
  411. ADDPL        R0, R0, #0x18                                        @ add 0x18 if we need to load more than 1 sample per step
  412. SUBPLS        R4, R4, #0x800000                                @ do we need to always load 2 samples?
  413. ADDPL        R0, R0, #0x18                                        @ extend the pointer even further
  414. ADDPL        R4, R4, #0x800000                                @ restore the original value
  415. LDR        R2, function_pointer                                @ load the function pointer variable
  416. CMP        R0, R2                                                @ check if the pointer is the same as in the variable
  417. BEQ        mixing_init                                        @ if the user created routine already contains the right function we can skip the setup process

  418. STR        R0, function_pointer                                @ store the pointer to VAR
  419. LDMIA        R0, {R0-R2, R8-R10}                                @ load 6 opcodes from R0 to Registers
  420. ADR        LR, runtime_created_routine                        @ load the routine offset that is gonna be custom made in real time

  421. create_routine_loop:
  422. STMIA        LR, {R0, R1}                                        @ write the first 2 instructions
  423. ADD        LR, LR, #0x98                                        @ extend the function pointer to Instr #38
  424. STMIA        LR, {R0, R1}                                        @ write the same instruction here
  425. SUB        LR, LR, #0x8C                                        @ go to Instr #3
  426. STMIA        LR, {R2, R8-R10}                                @ write #4 more instructions
  427. ADD        LR, LR, #0x98                                        @ jump to Instr #41
  428. STMIA        LR, {R2, R8-R10}                                @ write those instructions aswell
  429. SUB        LR, LR, #0x80                                        @ jump to next instruction block
  430. ADDS        R5, R5, #0x40000000                                @ do a loop until all 4 blocks are written to instruction block
  431. BCC        create_routine_loop

  432. LDR        R8, hq_buffer_length_label                        @ load buffer length ins samples to R8

  433. mixing_init:

  434. MOV        R2, #0xFF000000                                        @ load the fine position overflow bitmask

  435. mixing_loop:

  436. LDMIA        R5, {R0, R1, R10, LR}                                @ load 4 stereo samples to Registers
  437. MUL        R9, R7, R12                                        @ multiply DELTA with fine position

  438. runtime_created_routine:

  439. NOP                                                        @ Block #1
  440. NOP
  441. MLANE        R0, R11, R9, R0
  442. NOP
  443. NOP
  444. NOP
  445. NOP
  446. BIC        R7, R7, R2, ASR#1
  447. MULNE        R9, R7, R12
  448. NOP                                                        @ Block #2
  449. NOP
  450. MLANE        R1, R11, R9, R1
  451. NOP
  452. NOP
  453. NOP
  454. NOP
  455. BIC        R7, R7, R2, ASR#1
  456. MULNE        R9, R7, R12
  457. NOP                                                        @ Block #3
  458. NOP
  459. MLANE        R10, R11, R9, R10
  460. NOP
  461. NOP
  462. NOP
  463. NOP
  464. BIC        R7, R7, R2, ASR#1
  465. MULNE        R9, R7, R12
  466. NOP                                                        @ Block #4
  467. NOP
  468. MLANE        LR, R11, R9, LR
  469. NOP
  470. NOP
  471. NOP
  472. NOP
  473. BIC        R7, R7, R2, ASR#1
  474. STMIA        R5!, {R0, R1, R10, LR}                                @ write 4 stereo samples

  475. LDMIA        R5, {R0, R1, R10, LR}                                @ load the next 4 stereo samples
  476. MULNE        R9, R7, R12                                        @ calc next DELTA
  477. NOP                                                        @ Block #1
  478. NOP
  479. MLANE        R0, R11, R9, R0
  480. NOP
  481. NOP
  482. NOP
  483. NOP
  484. BIC        R7, R7, R2, ASR#1
  485. MULNE        R9, R7, R12
  486. NOP                                                        @ Block #2
  487. NOP
  488. MLANE        R1, R11, R9, R1
  489. NOP
  490. NOP
  491. NOP
  492. NOP
  493. BIC        R7, R7, R2, ASR#1
  494. MULNE        R9, R7, R12
  495. NOP                                                        @ Block #3
  496. NOP
  497. MLANE        R10, R11, R9, R10
  498. NOP
  499. NOP
  500. NOP
  501. NOP
  502. BIC        R7, R7, R2, ASR#1
  503. MULNE        R9, R7, R12
  504. NOP                                                        @ Block #4
  505. NOP
  506. MLANE        LR, R11, R9, LR
  507. NOP
  508. NOP
  509. NOP
  510. NOP
  511. BIC        R7, R7, R2, ASR#1
  512. STMIA        R5!, {R0, R1, R10, LR}                                @ write 4 stereo samples
  513. SUBS        R8, R8, #8                                        @ subtract 8 from the sample count
  514. BGT        mixing_loop

  515. ADR        R12, custom_stack_3                                @ reload saved values
  516. LDMIA        R12, {R2, R3, SP}
  517. B        mixing_end_func


  518. @ work variables

  519.         .align        2
  520. custom_stack_3:
  521.         .word        0x0, 0x0, 0x0
  522. stack_capacity:
  523.         .word        0x03007910
  524. function_pointer:
  525.         .word        0x0

  526. @ math resources, not directly used

  527. math_resources:

  528. MOV        R9, R9, ASR#22                                        @ Frequency Lower than default Frequency
  529. ADDS        R9, R9, R6, LSL#1
  530. ADDS        R7, R7, R4
  531. ADDPL        R6, R12, R6
  532. LDRPLSB        R12, [R3, #1]!
  533. SUBPLS        R12, R12, R6

  534. ADDS        R9, R6, R9, ASR#23                                @ Frequency < 2x && Frequency > default frequency
  535. ADD        R6, R12, R6
  536. ADDS        R7, R7, R4
  537. LDRPLSB        R6, [R3, #1]!
  538. LDRSB        R12, [R3, #1]!
  539. SUBS        R12, R12, R6

  540. ADDS        R9, R6, R9, ASR#23                                @ Frequency >= 2x higher than default Frequency
  541. ADD        R7, R7, R4
  542. ADD        R3, R3, R7, LSR#23
  543. LDRSB        R6, [R3]
  544. LDRSB        R12, [R3, #1]!
  545. SUBS        R12, R12, R6

  546. split_sample_loading:

  547. ADD        R5, R5, R8, LSL#2                                @ R5 = End of HQ buffer

  548. uncached_mixing_loop:

  549. MUL        R9, R7, R12                                        @ calc interpolated DELTA
  550. MOV        R9, R9, ASR#22                                        @ scale down the DELTA
  551. ADDS        R9, R9, R6, LSL#1                                @ Add to Base Sample (upscaled to 8 bits again)
  552. LDRNE        R0, [R5, -R8, LSL#2]                                @ load sample from buffer
  553. MLANE        R0, R11, R9, R0                                        @ add it to the buffer sample
  554. STRNE        R0, [R5, -R8, LSL#2]                                @ write the sample
  555. ADD        R7, R7, R4                                        @ add the step size to the fine position
  556. MOVS        R9, R7, LSR#23                                        @ write the overflow amount to R9
  557. BEQ        uncached_mixing_load_skip                        @ skip the mixing load if it isn't required

  558. SUBS        R2, R2, R7, LSR#23                                @ remove the overflow count from the remaning samples
  559. BLLE        loop_end_sub                                        @ if the loop end is reached call the loop handler
  560. SUBS        R9, R9, #1                                        @ remove #1 from the overflow count
  561. ADDEQ        R6, R12, R6                                        @ new base sample is previous sample + DELTA
  562. @RETURN LOCATION FROM LOOP HANDLER
  563. LDRNESB        R6, [R3, R9]!                                        @ load new sample
  564. LDRSB        R12, [R3, #1]!                                        @ load the delta sample (always required)
  565. SUB        R12, R12, R6                                        @ calc new DELTA
  566. BIC        R7, R7, #0x3F800000                                @ clear the overflow from the fine position by using the bitmask

  567. uncached_mixing_load_skip:

  568. SUBS        R8, R8, #1                                        @ reduce the sample count for the buffer by #1
  569. BGT        uncached_mixing_loop

  570. mixing_end_func:

  571. SUB        R3, R3, #1                                        @ reduce sample pointer by #1
  572. LDMFD        SP!, {R4, R9, R12}                                @ pop values from stack
  573. STR        R7, [R4, #CHN_FINE_POSITION]                        @ store the fine position
  574. B        store_coarse_sample_pos                                @ jump over to code to store coarse channel position

  575. loop_end_sub:

  576. ADD        R3, SP, #ARG_LOOP_START_POS+0xC                        @ prepare sample loop start loading and lopo length loading (0xC due to the pushed stack pointer)
  577. LDMIA        R3, {R3, R6}                                        @ R3 = Loop Start; R6 = Loop Length
  578. CMP        R6, #0                                                @ check if loop is enabled; if Loop is enabled R6 is != 0
  579. RSBNE        R9, R2, #0                                        @ the sample overflow from the resampling needs to get subtracted so the remaining samples is slightly less
  580. ADDNE        R2, R6, R2                                        @ R2 = add the loop length
  581. ADDNE        PC, LR, #8                                        @ return from the subroutine to 2 instructions after the actual return location
  582. LDMFD        SP!, {R4, R9, R12}                                @ restore registers from stack
  583. B        update_channel_status

  584. fixed_freq_loop_end_handler:

  585. LDR        R2, [SP, #ARG_LOOP_LENGTH+0x8]                        @ load the loop length value
  586. MOVS        R6, R2                                                @ copy it to R6 and check if loop is disabled
  587. LDRNE        R3, [SP, #ARG_LOOP_START_POS+0x8]                @ reset the sample pointer to the loop start position
  588. BXNE        LR                                                @ if it loops return to mixing function, if it doesn't go on and end mixing

  589. LDMFD        SP!, {R4, R9}

  590. update_channel_status:

  591. STRB        R6, [R4]                                        @ if loop ist disabled R6 = 0 and we can disable the channel by writing R6 to R4 (channel area)
  592. B        switchto_thumb                                        @ switch to thumb

  593. fixed_math_resource:        @ not exectued, used to create mixing function

  594. MOVS        R6, R10, LSL#24
  595. MOVS        R6, R6, ASR#24
  596. MOVS        R6, R10, LSL#16
  597. MOVS        R6, R6, ASR#24
  598. MOVS        R6, R10, LSL#8
  599. MOVS        R6, R6, ASR#24
  600. MOVS        R6, R10, ASR#24
  601. LDMIA        R3!, {R10}                                        @ load chunk of samples
  602. MOVS        R6, R10, LSL#24
  603. MOVS        R6, R6, ASR#24
  604. MOVS        R6, R10, LSL#16
  605. MOVS        R6, R6, ASR#24
  606. MOVS        R6, R10, LSL#8
  607. MOVS        R6, R6, ASR#24
  608. LDMFD        SP!, {R4, R9, R12}

  609. fixed_mixing_setup:

  610. STMFD        SP!, {R4, R9}                                        @ backup the channel pointer and

  611. fixed_mixing_check_length:

  612. MOV        LR, R2                                                @ move absolute sample position to LR
  613. CMP        R2, R8                                                @
  614. MOVGT        LR, R8                                                @ if there is less samples than the buffer to process write the smaller sample amount to LR
  615. SUB        LR, LR, #1                                        @ shorten samples to process by #1
  616. MOVS        LR, LR, LSR#2                                        @ calculate the amount of words to process (-1/4)
  617. BEQ        fixed_mixing_process_unaligned                        @ process the unaligned samples if there is <= 3 samples to process

  618. SUB        R8, R8, LR, LSL#2                                @ subtract the amount of samples we need to process from the buffer length
  619. SUB        R2, R2, LR, LSL#2                                @ subtract the amount of samples we need to process from the remaining samples
  620. ADR        R1, fixed_mixing_custom_routine
  621. ADR        R0, fixed_math_resource                                @ load the 2 pointers to create function (@R0) by instructions from R1
  622. MOV        R9, R3, LSL#30                                        @ move sample alignment bits to the leftmost position
  623. ADD        R0, R0, R9, LSR#27                                @ alignment * 8 + resource offset = new resource offset
  624. LDMIA        R0!, {R6, R7, R9, R10}                                @ load 4 instructions
  625. STMIA        R1, {R6, R7}                                        @ write the 1st 2 instructions
  626. ADD        R1, R1, #0xC                                        @ move label pointer over to the next slot
  627. STMIA        R1, {R9, R10}                                        @ write 2nd block
  628. ADD        R1, R1, #0xC                                        @ move label pointer to next block
  629. LDMIA        R0, {R6, R7, R9, R10}                                @ load instructions for block #3 and #4
  630. STMIA        R1, {R6, R7}                                        @ write block #3
  631. ADD        R1, R1, #0xC                                        @ ...
  632. STMIA        R1, {R9, R10}                                        @ write block #4
  633. LDMIA        R3!, {R10}                                        @ write read 4 samples from ROM

  634. fixed_mixing_loop:

  635. LDMIA        R5, {R0, R1, R7, R9}                                @ load 4 samples from hq buffer

  636. fixed_mixing_custom_routine:

  637. NOP
  638. NOP
  639. MLANE        R0, R11, R6, R0                                        @ add new sample if neccessary
  640. NOP
  641. NOP
  642. MLANE        R1, R11, R6, R1
  643. NOP
  644. NOP
  645. MLANE        R7, R11, R6, R7
  646. NOP
  647. NOP
  648. MLANE        R9, R11, R6, R9
  649. STMIA        R5!, {R0, R1, R7, R9}                                @ write the samples to the work area buffer
  650. SUBS        LR, LR, #1                                        @ countdown the sample blocks to process
  651. BNE        fixed_mixing_loop                                @ if the end wasn't reached yet, repeat the loop

  652. SUB        R3, R3, #4                                        @ reduce sample position by #4, we'll need to load the samples again

  653. fixed_mixing_process_unaligned:

  654. MOV        R1, #4                                                @ we need to repeat the loop #4 times to completley get rid of alignment errors

  655. fixed_mixing_unaligned_loop:

  656. LDR        R0, [R5]                                        @ load sample from buffer
  657. LDRSB        R6, [R3], #1                                        @ load sample from ROM ro R6
  658. MLA        R0, R11, R6, R0                                        @ write the sample to the buffer
  659. STR        R0, [R5], #4
  660. SUBS        R2, R2, #1                                        @ reduce alignment error by #1
  661. BLEQ        fixed_freq_loop_end_handler
  662. SUBS        R1, R1, #1
  663. BGT        fixed_mixing_unaligned_loop                        @ repeat the loop #4 times

  664. SUBS        R8, R8, #4                                        @ reduce the sample amount we wrote to the buffer by #1
  665. BGT        fixed_mixing_check_length                        @ go up to repeat the mixing procedure until the buffer is filled

  666. LDMFD        SP!, {R4, R9}                                        @ pop registers from stack

  667. store_coarse_sample_pos:

  668. STR        R2, [R4, #CHN_POSITION_REL]                        @ store relative and absolute sample position
  669. STR        R3, [R4, #CHN_POSITION_ABS]                       

  670. switchto_thumb:

  671. ADR        R0, (check_remain_channels+1)                        @ load the label offset and switch to thumb
  672. BX        R0

  673.         .thumb

  674. check_remain_channels:

  675. LDR        R0, [SP, #ARG_REMAIN_CHN]                        @ load the remaining channels
  676. SUB        R0, #1                                                @ reduce the amount by #1
  677. BLE        mixer_return                                        @ end the mixing when finished processing all channels

  678. ADD        R4, #0x40
  679. B        mixer_entry

  680. mixer_return:

  681. ADR        R0, downsampler
  682. BX        R0

  683. downsampler_return:

  684. LDR        R0, [SP, #ARG_VAR_AREA]                        @ load the main var area to R0
  685. LDR        R3, mixer_finished_status                @ load some status indication value to R3
  686. STR        R3, [R0]                                @ store this value to the main var area
  687. ADD        SP, SP, #0x1C
  688. POP        {R0-R7}
  689. MOV        R8, R0
  690. MOV        R9, R1
  691. MOV        R10, R2
  692. MOV        R11, R3
  693. POP        {R3}
  694. BX        R3

  695.         .align        2

  696. mixer_finished_status:
  697.         .word        0x68736D53

  698.         .arm

  699. downsampler:

  700. LDR        R10, hq_buffer_label
  701. LDR        R9, [SP, #ARG_BUFFER_POS]
  702. LDR        R8, hq_buffer_length_label
  703. MOV        R11, #0xFF
  704. .if PREVENT_CLIP==1

  705. MOV        R12, #0xFFFFFFFF
  706. MOV        R12, R12, LSL#14
  707. MOV        R7, #0x630

  708. downsampler_loop:

  709. LDRSH        R2, [R10], #2
  710. LDRSH        R0, [R10], #2
  711. LDRSH        R3, [R10], #2
  712. LDRSH        R1, [R10], #2

  713. CMP        R0, #0x4000
  714. MOVGE        R0, #0x3F80
  715. CMP        R0, #-0x4000
  716. MOVLT        R0, R12

  717. CMP        R1, #0x4000
  718. MOVGE        R1, #0x3F80
  719. CMP        R1, #-0x4000
  720. MOVLT        R1, R12

  721. CMP        R2, #0x4000
  722. MOVGE        R2, #0x3F80
  723. CMP        R2, #-0x4000
  724. MOVLT        R2, R12

  725. CMP        R3, #0x4000
  726. MOVGE        R3, #0x3F80
  727. CMP        R3, #-0x4000
  728. MOVLT        R3, R12

  729. AND        R0, R11, R0, ASR#7
  730. AND        R1, R11, R1, ASR#7
  731. AND        R2, R11, R2, ASR#7
  732. AND        R3, R11, R3, ASR#7

  733. ORR        R2, R2, R3, LSL#8
  734. ORR        R0, R0, R1, LSL#8

  735. STRH        R2, [R9, R7]
  736. STRH        R0, [R9], #2

  737. SUBS        R8, #2
  738. BGT        downsampler_loop

  739. .else
  740. downsampler_loop:

  741. LDRH        R4, [R10], #2
  742. LDRH        R0, [R10], #2
  743. LDRH        R5, [R10], #2
  744. LDRH        R1, [R10], #2
  745. LDRH        R6, [R10], #2
  746. LDRH        R2, [R10], #2
  747. LDRH        R7, [R10], #2
  748. LDRH        R3, [R10], #2

  749. AND        R0, R11, R0, LSR#7
  750. AND        R1, R11, R1, LSR#7
  751. AND        R2, R11, R2, LSR#7
  752. AND        R3, R11, R3, LSR#7
  753. AND        R4, R11, R4, LSR#7
  754. AND        R5, R11, R5, LSR#7
  755. AND        R6, R11, R6, LSR#7
  756. AND        R7, R11, R7, LSR#7

  757. ORR        R4, R4, R5, LSL#8
  758. ORR        R4, R4, R6, LSL#16
  759. ORR        R4, R4, R7, LSL#24

  760. ORR        R0, R0, R1, LSL#8
  761. ORR        R0, R0, R2, LSL#16
  762. ORR        R0, R0, R3, LSL#24

  763. STR        R4, [R9, #0x630]
  764. STR        R0, [R9], #4

  765. SUBS        R8, #4
  766. BGT        downsampler_loop

  767. .endif

  768. ADR        R0, (downsampler_return+1)
  769. BX        R0

  770.         .align        2

  771. init_synth:

  772. CMP        R12, #0                @ $030057C4
  773. BNE        check_synth_type

  774. LDRB        R6, [R3, #SYNTH_WIDTH_CHANGE_1]                        @ for saw wave -> 0xF0 (base duty cycle change)
  775. ADD        R2, R2, R6, LSL#24                                @ add it to the current synt
  776. LDRB        R6, [R3, #SYNTH_WIDTH_CHANGE_2]                        @ for saw wave -> 0x80 (base duty cycle change #2)
  777. 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
  778. MVNMI        R6, R6                                                 @ negate if duty cycle is > 50%
  779. MOV        R10, R6, LSR#8                                        @ dividide the final duty cycle by 8 to R10
  780. LDRB        R1, [R3, #SYNTH_MOD_AMOUNT]                        @ for saw wave -> 0xE0
  781. LDRB        R0, [R3, #SYNTH_BASE_WAVE_DUTY]                        @ for saw wave -> 0x10 (base duty cycle offset)
  782. MOV        R0, R0, LSL#24                                        @ convert it to a usable duty cycle
  783. MLA        R6, R10, R1, R0                                        @ calculate the final duty cycle with the offset, and intensity * rotating duty cycle amount
  784. STMFD        SP!, {R2, R3, R9, R12}

  785. synth_type_0_loop:

  786. LDMIA        R5, {R0-R3, R9, R10, R12, LR}                        @ load 8 samples
  787. CMP        R7, R6                                                @ Block #1
  788. ADDCC        R0, R0, R11, LSL#6
  789. SUBCS        R0, R0, R11, LSL#6
  790. ADDS        R7, R7, R4, LSL#3
  791. CMP        R7, R6                                                @ Block #2
  792. ADDCC        R1, R1, R11, LSL#6
  793. SUBCS        R1, R1, R11, LSL#6
  794. ADDS        R7, R7, R4, LSL#3
  795. CMP        R7, R6                                                @ Block #3
  796. ADDCC        R2, R2, R11, LSL#6
  797. SUBCS        R2, R2, R11, LSL#6
  798. ADDS        R7, R7, R4, LSL#3
  799. CMP        R7, R6                                                @ Block #4
  800. ADDCC        R3, R3, R11, LSL#6
  801. SUBCS        R3, R3, R11, LSL#6
  802. ADDS        R7, R7, R4, LSL#3
  803. CMP        R7, R6                                                @ Block #5
  804. ADDCC        R9, R9, R11, LSL#6
  805. SUBCS        R9, R9, R11, LSL#6
  806. ADDS        R7, R7, R4, LSL#3
  807. CMP        R7, R6                                                @ Block #6
  808. ADDCC        R10, R10, R11, LSL#6
  809. SUBCS        R10, R10, R11, LSL#6
  810. ADDS        R7, R7, R4, LSL#3
  811. CMP        R7, R6                                                @ Block #7
  812. ADDCC        R12, R12, R11, LSL#6
  813. SUBCS        R12, R12, R11, LSL#6
  814. ADDS        R7, R7, R4, LSL#3
  815. CMP        R7, R6                                                @ Block #8
  816. ADDCC        LR, LR, R11, LSL#6
  817. SUBCS        LR, LR, R11, LSL#6
  818. ADDS        R7, R7, R4, LSL#3

  819. STMIA        R5!, {R0-R3, R9, R10, R12, LR}                        @ write 8 samples
  820. SUBS        R8, R8, #8                                        @ remove #8 from sample count
  821. BGT        synth_type_0_loop

  822. LDMFD        SP!, {R2, R3, R9, R12}
  823. B        mixing_end_func

  824. check_synth_type:

  825. SUBS        R12, R12, #1                                        @ remove #1 from the synth type byte and check if it's #0
  826. BNE        synth_type_2                                        @ if it still isn't it's synth type 2 (smooth pan flute)

  827. .if ENABLE_FM==1

  828. B        setup_fm

  829. .else
  830. MOV        R6, #0x300                                        @ R6 = 0x300
  831. MOV        R11, R11, LSR#1                                        @ halve the volume
  832. BIC        R11, R11, #0xFF00                                @ clear bad bits from division
  833. MOV        R12, #0x70                                        @ R12 = 0x70

  834. synth_type_1_loop:

  835. LDMIA        R5, {R0, R1, R10, LR}                                @ load 4 samples from memory
  836. ADDS        R7, R7, R4, LSL#3                                @ Block #1 (some oscillator type code)
  837. RSB        R9, R12, R7, LSR#24
  838. MOV        R6, R7, LSL#1
  839. SUB        R9, R9, R6, LSR#27
  840. ADDS        R2, R9, R2, ASR#1
  841. MLANE        R0, R11, R2, R0

  842. ADDS        R7, R7, R4, LSL#3                                @ Block #2
  843. RSB        R9, R12, R7, LSR#24
  844. MOV        R6, R7, LSL#1
  845. SUB        R9, R9, R6, LSR#27
  846. ADDS        R2, R9, R2, ASR#1
  847. MLANE        R1, R11, R2, R1

  848. ADDS        R7, R7, R4, LSL#3                                @ Block #3
  849. RSB        R9, R12, R7, LSR#24
  850. MOV        R6, R7, LSL#1
  851. SUB        R9, R9, R6, LSR#27
  852. ADDS        R2, R9, R2, ASR#1
  853. MLANE        R10, R11, R2, R10

  854. ADDS        R7, R7, R4, LSL#3                                @ Block #4
  855. RSB        R9, R12, R7, LSR#24
  856. MOV        R6, R7, LSL#1
  857. SUB        R9, R9, R6, LSR#27
  858. ADDS        R2, R9, R2, ASR#1
  859. MLANE        LR, R11, R2, LR

  860. STMIA        R5!, {R0, R1, R10, LR}
  861. SUBS        R8, R8, #4
  862. BGT        synth_type_1_loop

  863. B        mixing_end_func                                        @ goto end

  864. .endif

  865. synth_type_2:

  866. MOV        R6, #0x80                                        @ write base values to the registers
  867. MOV        R12, #0x180

  868. synth_type_2_loop:

  869. LDMIA        R5, {R0, R1, R10, LR}                                @ load samples from work buffer
  870. ADDS        R7, R7, R4, LSL#3                                @ Block #1
  871. RSBPL        R9, R6, R7, ASR#23
  872. SUBMI        R9, R12, R7, LSR#23
  873. MLA        R0, R11, R9, R0

  874. ADDS        R7, R7, R4, LSL#3                                @ Block #2
  875. RSBPL        R9, R6, R7, ASR#23
  876. SUBMI        R9, R12, R7, LSR#23
  877. MLA        R1, R11, R9, R1

  878. ADDS        R7, R7, R4, LSL#3                                @ Block #3
  879. RSBPL        R9, R6, R7, ASR#23
  880. SUBMI        R9, R12, R7, LSR#23
  881. MLA        R10, R11, R9, R10

  882. ADDS        R7, R7, R4, LSL#3                                @ Block #4
  883. RSBPL        R9, R6, R7, ASR#23
  884. SUBMI        R9, R12, R7, LSR#23
  885. MLA        LR, R11, R9, LR

  886. STMIA        R5!, {R0, R1, R10, LR}                                @ store the samples back to the buffer
  887. SUBS        R8, R8, #4                                        @ subtract #4 from the remainging samples
  888. BGT        synth_type_2_loop

  889. B        mixing_end_func

  890. @****************** SPECIAL MIXING ******************@
  891. .if ENABLE_DECOMPRESSION==1
  892. special_mixing:                @ $03006BF8

  893. LDR        R6, [R4, #CHN_WAVE_OFFSET]                @ load the wave header offset to R6
  894. LDRB        R0, [R4]
  895. TST        R0, #FLAG_CHN_COMP                        @ check if the channel is initialized
  896. BNE        setup_compressed_mixing_frequency        @ skip the setup procedure if it's running in compressed mode already

  897. ORR        R0, R0, #FLAG_CHN_COMP                        @ enable the flag in the channel status
  898. STRB        R0, [R4]                                @ store the channel status
  899. LDRB        R0, [R4, #CHN_MODE]                        @ load the channel mode byte
  900. TST        R0, #MODE_REVERSE                        @ check if reverse mode is not enabled

  901. BEQ        determine_compression                        @ if Reverse Mode isn't enabled we can directly check if the sample has to get decoded

  902. LDR        R1, [R6, #WAVE_LENGTH]                        @ load the amount of samples
  903. ADD        R1, R1, R6, LSL#1                        @ do some start position calculation
  904. ADD        R1, R1, #0x20
  905. SUB        R3, R1, R3
  906. STR        R3, [R4, #CHN_POSITION_ABS]                @ store the final seek position

  907. determine_compression:

  908. LDRH        R0, [R6]                                @ load the compression flag from the sample header
  909. CMP        R0, #0                                        @ check if the compression is not enabled
  910. BEQ        setup_compressed_mixing_frequency        @ skip the compression handler

  911. SUB        R3, R3, R6                                @ calc initial position
  912. SUB        R3, R3, #0x10
  913. STR        R3, [R4, #CHN_POSITION_ABS]                @ store the inital position (relative, not absolute)

  914. setup_compressed_mixing_frequency:

  915. STMFD        SP!, {R4, R9, R12}

  916. MOVS        R11, R11, LSR#1                                @ divide master volume by 2
  917. ADC        R11, R11, #0x8000
  918. BIC        R11, R11, #0xFF00

  919. LDR        R7, [R4, #CHN_FINE_POSITION]                @ load the fine position
  920. LDR        R1, [R4, #CHN_FREQUENCY]                @ load the channel frequency
  921. LDRB        R0, [R4, #CHN_MODE]                        @ load the channel mode again
  922. TST        R0, #MODE_FIXED_FREQ                        @ check if fixed frequency mode is enabled
  923. MOVNE        R1, #0x800000                                @ ### SAMPLE STEP FREQUENCY CHANGED TO R7
  924. MULEQ        R1, R12, R1                                @ default rate factor * frequency = sample steps

  925. ADD        R5, R5, R8, LSL#2                        @ set the buffer pointer to the end of the channel

  926. LDRH        R0, [R6]                                @ load the codec type
  927. CMP        R0, #0                                        @ check if compression is disabled
  928. BEQ        uncompressed_mixing_reverse_check

  929. MOV        R0, #0xFF000000                                @ set the current decoding block to "something very high" so that the first block always gets decoded
  930. STR        R0, [R4, #CHN_BLOCK_COUNT]                @ write the last decoded block into the channel vars
  931. LDRB        R0, [R4, #CHN_MODE]                        @ check again if reverse mode is enabled
  932. TST        R0, #MODE_REVERSE                        @ test if reverse mode is enabled
  933. BNE        compressed_mixing_reverse_init                @ check again of reverse mixing is enabled

  934. BL        bdpcm_decoder                                @ load a sample from the stream to R12
  935. MOV        R6, R12                                        @ move the base sample to R6
  936. ADD        R3, R3, #1                                @ increase stream position by #1
  937. BL        bdpcm_decoder                                @ load the delta sample and calculate delta value
  938. SUB        R12, R12, R6

  939. @***** MIXING LOOP REGISTER USAGE ***********@
  940. @ R0:        Sample to modify from buffer
  941. @ R1:        sample steps                (MOVED FROM R4)
  942. @ R2:        remaining samples before loop/end
  943. @ R3:        sample position
  944. @ R4:        channel pointer
  945. @ R5:        pointer to the end of buffer
  946. @ R6:        Base sample
  947. @ R7:        fine position
  948. @ R8:        remaining samples for current buffer
  949. @ R9:        interpolated sample
  950. @ R10:        not used
  951. @ R11:        volume
  952. @ R12:        Delta Sample
  953. @ LR:        not used
  954. @********************************************@

  955. compressed_mixing_loop:

  956. MUL        R9, R7, R12                                @ delta sample * fine position = interpolated DELTA
  957. MOV        R9, R9, ASR#22                                @ scale down the sample
  958. ADDS        R9, R9, R6, LSL#1                        @ double the base sample and add it to the interpolated downscaled DELTA
  959. LDRNE        R0, [R5, -R8, LSL#2]                        @ if the sample is NOT 0 load the sample from buffer and store the calulated value
  960. MLANE        R0, R11, R9, R0                                @ add the sample to the buffer sample and apply volume
  961. STRNE        R0, [R5, -R8, LSL#2]                        @ store the sample if it's not Zero
  962. ADD        R7, R7, R1                                @ ### changed from R4 to R1
  963. MOVS        R9, R7, LSR#23                                @ check if there is new samples to load

  964. BEQ        compressed_mixing_load_skip                @ no new samples need to be loaded

  965. SUBS        R2, R2, R7, LSR#23                        @ remove the sample overflow from the remaining samples
  966. BLLE        loop_end_sub                                @ call the loop/ending handler if the countdown reached zero or something negative
  967. SUBS        R9, R9, #1                                @ check if only one sample has to get loaded
  968. ADDEQ        R6, R12, R6                                @ if this is the case we can calculate the new base sample
  969. BEQ        compressed_mixing_base_load_skip

  970. ADD        R3, R3, R9                                @ these opcodes are equivalent to LDRNESB R6, [R3, R9]!
  971. BL        bdpcm_decoder
  972. MOV        R6, R12

  973. compressed_mixing_base_load_skip:

  974. ADD        R3, R3, #1                                        @ equivalent to LDRSB        R12, [R3, #1]!
  975. BL        bdpcm_decoder
  976. SUB        R12, R12, R6
  977. BIC        R7, R7, #0x3F800000                        @ clear the overflow bits by using the according bitmask

  978. compressed_mixing_load_skip:

  979. SUBS        R8, R8, #1                                @ remove #1 from the remaining samples
  980. BGT        compressed_mixing_loop

  981. @SUB        R3, R3, #1                                @ sample pointer -1 ; ALREADY DONE BY mixing_end_func
  982. B        mixing_end_func




  983. compressed_mixing_reverse_init:

  984. SUB        R3, R3, #1                                @ subtract one from the reverse playback location initially
  985. BL        bdpcm_decoder                                @ fetch a sample from stream
  986. MOV        R6, R12                                        @ bdpcm_decoder returns base sample in R12 --> R6
  987. SUB        R3, R3, #1                                @ seek one sample further backwards
  988. BL        bdpcm_decoder                                @ detch the DELTA sample
  989. SUB        R12, R12, R6                                @ calc the Delta value

  990. compressed_mixing_reverse_loop:

  991. MUL        R9, R7, R12                                @ delta sample * fine position = interpolated DELTA
  992. MOV        R9, R9, ASR#22                                @ scale down the sample
  993. ADDS        R9, R9, R6, LSL#1                        @ double the base sample and add it to the interpolated downscaled DELTA
  994. LDRNE        R0, [R5, -R8, LSL#2]                        @ if the sample is NOT 0 load the sample from buffer and store the calulated value
  995. MLANE        R0, R11, R9, R0                                @ add the sample to the buffer sample and apply volume
  996. STRNE        R0, [R5, -R8, LSL#2]                        @ store the sample if it's not Zero
  997. ADD        R7, R7, R1                                @ ### changed from R4 to R1
  998. MOVS        R9, R7, LSR#23                                @ check if there is new samples to load

  999. BEQ        compressed_mixing_reverse_load_skip        @ skip sample loading if we don't need to load new samples from ROM

  1000. SUBS        R2, R2, R7, LSR#23                        @ remove the overflowed samples from the remaining samples
  1001. BLLE        loop_end_sub                                @ if the sample playback finished go to end handler

  1002. SUBS        R9, R9, #1                                @ remove sample overflow count by #1
  1003. ADDEQ        R6, R12, R6                                @ make the previous delta sample the new base sample if only #1 sample needs to get loaded
  1004. BEQ        compressed_mixing_reverse_base_load_skip @skip base sample loading

  1005. SUB        R3, R3, R9                                @
  1006. BL        bdpcm_decoder                                @
  1007. MOV        R6, R12                                        @

  1008. compressed_mixing_reverse_base_load_skip:

  1009. SUB        R3, R3, #1
  1010. BL        bdpcm_decoder
  1011. SUB        R12, R12, R6                                @ load next samples
  1012. BIC        R7, R7, #0x3F800000                        @ clear overflow bits

  1013. compressed_mixing_reverse_load_skip:

  1014. SUBS        R8, R8, #1
  1015. BGT        compressed_mixing_reverse_loop

  1016. @ADD        R3, R3, #2                                @ copied from original code
  1017. ADD        R3, R3, #3

  1018. B        mixing_end_func


  1019. uncompressed_mixing_reverse_check:

  1020. LDRB        R0, [R4, #1]                                @ load the channel mode                =$03006D84
  1021. TST        R0, #MODE_REVERSE                        @ check if reverse mode is even enabled
  1022. BEQ        mixing_end_func                                @ skip the channel if the mode is "akward"

  1023. LDRSB        R6, [R3, #-1]!                                @ load first negative sample
  1024. LDRSB        R12, [R3, #-1]                                @ load the DELTA sample
  1025. SUB        R12, R12, R6                                @ calculate DELTA

  1026. reverse_mixing_loop:

  1027. MUL        R9, R7, R12                                @ delta sample * fine position = interpolated DELTA
  1028. MOV        R9, R9, ASR#22                                @ scale down the sample
  1029. ADDS        R9, R9, R6, LSL#1                        @ double the base sample and add it to the interpolated downscaled DELTA
  1030. LDRNE        R0, [R5, -R8, LSL#2]                        @ if the sample is NOT 0 load the sample from buffer and store the calulated value
  1031. MLANE        R0, R11, R9, R0                                @ add the sample to the buffer sample and apply volume
  1032. STRNE        R0, [R5, -R8, LSL#2]                        @ store the sample if it's not Zero
  1033. ADD        R7, R7, R1                                @ ### changed from R4 to R1
  1034. MOVS        R9, R7, LSR#23                                @ check if there is new samples to load

  1035. BEQ        reverse_mixing_load_skip

  1036. SUBS        R2, R2, R7, LSR#23                        @ blablabla, all same as above
  1037. BLLE        loop_end_sub

  1038. MOVS        R9, R9                                        @ check if sample
  1039. ADDEQ        R6, R12, R6
  1040. LDRNESB        R6, [R3, -R9]!
  1041. LDRSB        R12, [R3, #-1]                                @ load samples dependent on conditions
  1042. SUB        R12, R12, R6
  1043. BIC        R7, R7, #0x3F800000                        @ cut off overflow count to get new fine position

  1044. reverse_mixing_load_skip:

  1045. SUBS        R8, R8, #1                                @ remaining samples -1
  1046. BGT        reverse_mixing_loop                        @ continue lopo if there is still samples to process

  1047. @ADD        R3, R3, #1                                @ copied from original code
  1048. ADD        R3, R3, #2                                @ =$03006DE8

  1049. B        mixing_end_func

  1050. @**************** SPECIAL MIXING END ****************@

  1051. @************** SPECIAL MIXING LOOPING **************@

  1052. compressed_loop_end_sub:




  1053. @************ SPECIAL MIXING LOOPING END ************@

  1054. @****************** BDPCM DEOCODER ******************@

  1055. bdpcm_decoder:                                @ RETURNS SAMPLE FROM POSITION XXX in R12

  1056. STMFD        SP!, {R0, R2, R5-R7, LR}                @ push registers to make them free to use: R0, R2, R5, R6, R7, LR
  1057. MOV        R0, R3, LSR#6                                @ shift the relative position over to clip of every but the block offset
  1058. LDR        R12, [R4, #CHN_BLOCK_COUNT]                @ check if the current sample position is at the beginning of the current block
  1059. CMP        R0, R12
  1060. BEQ        bdpcm_decoder_return

  1061. STR        R0, [R4, #CHN_BLOCK_COUNT]                @ store the block position to Channel Vars
  1062. MOV        R12, #0x21                                @ load decoding byte count to R1 (1 Block = 0x21 Bytes)
  1063. MUL        R2, R12, R0                                @ multiply the block count with the block length to calc actual byte position of current block
  1064. LDR        R12, [R4, #CHN_WAVE_OFFSET]                @ load the wave data offset to R1
  1065. ADD        R2, R2, R12                                @ add the wave data offset and 0x10 to get the actual position in ROM
  1066. ADD        R2, R2, #0x10                                @
  1067. LDR        R5, decoder_buffer                        @ load the decoder buffer pointer to R5
  1068. ADR        R6, delta_lookup_table                        @ load the lookup table pointer to R6
  1069. MOV        R7, #0x40                                @ load the block sample count (0x40) to R7
  1070. 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
  1071. STRB        LR, [R5], #1                                @ write the sample to the decoder buffer
  1072. LDRB        R12, [R2], #1                                @ load the next 2 samples to R1 (to get decoded) --- LSBits is decoded first and MSBits last
  1073. B        bdpcm_decoder_lsb

  1074. bdpcm_decoder_msb:

  1075. LDRB        R12, [R2], #1                                @ load the next 2 samples to get decoded
  1076. MOV        R0, R12, LSR#4                                @ seperate the current samples' bits
  1077. LDRSB        R0, [R6, R0]                                @ load the differential value from the lookup table
  1078. ADD        LR, LR, R0                                @ add the decoded value to the previous sample value to calc the current samples' level
  1079. STRB        LR, [R5], #1                                @ write the output sample to the decoder buffer and increment buffer pointer

  1080. bdpcm_decoder_lsb:

  1081. AND        R0, R12, #0xF                                @ seperate the 4 LSBits
  1082. LDRSB        R0, [R6, R0]                                @ but the 4 bit value into the lookup table and save the result to R0
  1083. ADD        LR, LR, R0                                @ add the value from the lookup table to the previous value to calc the new one
  1084. STRB        LR, [R5], #1                                @ store the decoded sample to the decoding buffer
  1085. SUBS        R7, R7, #2                                @ decrease the block sample counter by 2 (2 samples each byte) and check if it is still above 0
  1086. BGT        bdpcm_decoder_msb                        @ if there is still samples to decode jump to the MSBits

  1087. bdpcm_decoder_return:

  1088. LDR        R5, decoder_buffer                        @ reload the decompressor buffer offset to R5
  1089. AND        R0, R3, #0x3F                                @ cut off the main position bits to read data from short buffer
  1090. LDRSB        R12, [R5, R0]                                @ read the decoded sample from buffer
  1091. LDMFD        SP!, {R0, R2, R5-R7, PC}                @ pop registers and return to the compressed sample mixer

  1092. @**************** END BDPCM DECODER *****************@

  1093. decoder_buffer:
  1094.         .word        decoder_buffer_target
  1095. delta_lookup_table:
  1096.         .byte        0x0, 0x1, 0x4, 0x9, 0x10, 0x19, 0x24, 0x31, 0xC0, 0xCF, 0xDC, 0xE7, 0xF0, 0xF7, 0xFC, 0xFF
  1097. .endif

  1098. .if ENABLE_FM==1
  1099. sin_lookup:
  1100.         .byte   0x00, 0x02, 0x03, 0x05, 0x06, 0x08, 0x09, 0x0B, 0x0C, 0x0E, 0x10, 0x11, 0x13, 0x14, 0x16, 0x17
  1101.         .byte   0x19, 0x1A, 0x1C, 0x1D, 0x1F, 0x20, 0x22, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2B, 0x2C, 0x2E, 0x2F
  1102.         .byte   0x31, 0x32, 0x33, 0x35, 0x36, 0x38, 0x39, 0x3A, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x43, 0x44, 0x45
  1103.         .byte   0x47, 0x48, 0x49, 0x4A, 0x4C, 0x4D, 0x4E, 0x4F, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x58, 0x59
  1104.         .byte   0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69
  1105.         .byte   0x6A, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x70, 0x71, 0x71, 0x72, 0x73, 0x73, 0x74, 0x75
  1106.         .byte   0x75, 0x76, 0x76, 0x77, 0x78, 0x78, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7C, 0x7C, 0x7C
  1107.         .byte   0x7D, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F
  1108.         .byte   0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7D, 0x7D
  1109.         .byte   0x7D, 0x7C, 0x7C, 0x7C, 0x7B, 0x7B, 0x7A, 0x7A, 0x7A, 0x79, 0x79, 0x78, 0x78, 0x77, 0x76, 0x76
  1110.         .byte   0x75, 0x75, 0x74, 0x73, 0x73, 0x72, 0x71, 0x71, 0x70, 0x6F, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A
  1111.         .byte   0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5F, 0x5E, 0x5D, 0x5C, 0x5B
  1112.         .byte   0x5A, 0x59, 0x58, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x4F, 0x4E, 0x4D, 0x4C, 0x4A, 0x49, 0x48
  1113.         .byte   0x47, 0x45, 0x44, 0x43, 0x41, 0x40, 0x3F, 0x3D, 0x3C, 0x3A, 0x39, 0x38, 0x36, 0x35, 0x33, 0x32
  1114.         .byte   0x31, 0x2F, 0x2E, 0x2C, 0x2B, 0x29, 0x28, 0x26, 0x25, 0x23, 0x22, 0x20, 0x1F, 0x1D, 0x1C, 0x1A
  1115.         .byte   0x19, 0x17, 0x16, 0x14, 0x13, 0x11, 0x10, 0x0E, 0x0C, 0x0B, 0x09, 0x08, 0x06, 0x05, 0x03, 0x02
  1116.         .byte   0x00, 0xFE, 0xFD, 0xFB, 0xFA, 0xF8, 0xF7, 0xF5, 0xF4, 0xF2, 0xF0, 0xEF, 0xED, 0xEC, 0xEA, 0xE9
  1117.         .byte   0xE7, 0xE6, 0xE4, 0xE3, 0xE1, 0xE0, 0xDE, 0xDD, 0xDB, 0xDA, 0xD8, 0xD7, 0xD5, 0xD4, 0xD2, 0xD1
  1118.         .byte   0xCF, 0xCE, 0xCD, 0xCB, 0xCA, 0xC8, 0xC7, 0xC6, 0xC4, 0xC3, 0xC1, 0xC0, 0xBF, 0xBD, 0xBC, 0xBB
  1119.         .byte   0xB9, 0xB8, 0xB7, 0xB6, 0xB4, 0xB3, 0xB2, 0xB1, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA8, 0xA7
  1120.         .byte   0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98, 0x97
  1121.         .byte   0x96, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x91, 0x90, 0x8F, 0x8F, 0x8E, 0x8D, 0x8D, 0x8C, 0x8B
  1122.         .byte   0x8B, 0x8A, 0x8A, 0x89, 0x88, 0x88, 0x87, 0x87, 0x86, 0x86, 0x86, 0x85, 0x85, 0x84, 0x84, 0x84
  1123.         .byte   0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
  1124.         .byte   0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83
  1125.         .byte   0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x8A, 0x8A
  1126.         .byte   0x8B, 0x8B, 0x8C, 0x8D, 0x8D, 0x8E, 0x8F, 0x8F, 0x90, 0x91, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96
  1127.         .byte   0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5
  1128.         .byte   0xA6, 0xA7, 0xA8, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB1, 0xB2, 0xB3, 0xB4, 0xB6, 0xB7, 0xB8
  1129.         .byte   0xB9, 0xBB, 0xBC, 0xBD, 0xBF, 0xC0, 0xC1, 0xC3, 0xC4, 0xC6, 0xC7, 0xC8, 0xCA, 0xCB, 0xCD, 0xCE
  1130.         .byte   0xCF, 0xD1, 0xD2, 0xD4, 0xD5, 0xD7, 0xD8, 0xDA, 0xDB, 0xDD, 0xDE, 0xE0, 0xE1, 0xE3, 0xE4, 0xE6
  1131.         .byte   0xE7, 0xE9, 0xEA, 0xEC, 0xED, 0xEF, 0xF0, 0xF2, 0xF4, 0xF5, 0xF7, 0xF8, 0xFA, 0xFB, 0xFD, 0xFE

  1132. setup_fm:

  1133. LDRB        R0, [R3, #1]                                        @ load frequency scaling factor
  1134. LDR        R1, fm_freq_scaling_resource                        @ load base opcode
  1135. ORR        R1, R1, R0, LSL#7                                @ modify the left shift to match the setting
  1136. LDRB        R0, [R3, #2]
  1137. LDR        R10, fm_intensity_resource                        @ same for the intensity
  1138. ORR        R10, R10, R0, LSL#7
  1139. ADR        LR, fm_loop_parse

  1140. fm_setup_loop:

  1141. STR        R1, [LR, #4]
  1142. STR        R10, [LR, #16]
  1143. ADD        LR, LR, #32
  1144. ADDS        R8, R8, #0x40000000
  1145. BCC        fm_setup_loop

  1146. ADR        R12, sin_lookup

  1147. fm_loop:

  1148. LDMIA        R5, {R0, R1, R10, LR}                                @ load 4 samples from memory

  1149. fm_loop_parse:

  1150. ADDS        R7, R7, R4, LSL#3
  1151. ADDS        R2, R2, R4, LSL#6                                @ Modulation Frequency Scaling Factor (LSL#3 = Bias Level)
  1152. MOV        R9, R2, LSR#23
  1153. LDRSB        R6, [R12, R9]
  1154. ADDS        R7, R7, R6, LSL#20                                @ Modulation Intensity
  1155. MOV        R9, R7, LSR#23
  1156. LDRSB        R6, [R12, R9]
  1157. MLA        R0, R11, R6, R0

  1158. ADDS        R7, R7, R4, LSL#3
  1159. ADDS        R2, R2, R4, LSL#6
  1160. MOV        R9, R2, LSR#23
  1161. LDRSB        R6, [R12, R9]
  1162. ADDS        R7, R7, R6, LSL#20
  1163. MOV        R9, R7, LSR#23
  1164. LDRSB        R6, [R12, R9]
  1165. MLA        R1, R11, R6, R1

  1166. ADDS        R7, R7, R4, LSL#3
  1167. ADDS        R2, R2, R4, LSL#6
  1168. MOV        R9, R2, LSR#23
  1169. LDRSB        R6, [R12, R9]
  1170. ADDS        R7, R7, R6, LSL#20
  1171. MOV        R9, R7, LSR#23
  1172. LDRSB        R6, [R12, R9]
  1173. MLA        R10, R11, R6, R10

  1174. ADDS        R7, R7, R4, LSL#3
  1175. ADDS        R2, R2, R4, LSL#6
  1176. MOV        R9, R2, LSR#23
  1177. LDRSB        R6, [R12, R9]
  1178. ADDS        R7, R7, R6, LSL#20
  1179. MOV        R9, R7, LSR#23
  1180. LDRSB        R6, [R12, R9]
  1181. MLA        LR, R11, R6, LR

  1182. STMIA        R5!, {R0, R1, R10, LR}
  1183. SUBS        R8, R8, #4
  1184. BGT        fm_loop

  1185. B        mixing_end_func

  1186. fm_freq_scaling_resource:

  1187. ADDS        R2, R2, R4

  1188. fm_intensity_resource:

  1189. ADDS        R7, R7, R6

  1190. .endif

  1191. main_mixer_end:

  1192.         .end
复制代码
回复 支持 反对

使用道具 举报

27

回帖

213

现金

0

勋章券

新伙伴的欢笑

Rank: 3

积分
89
发表于 2017-2-12 14:13:40 | 显示全部楼层
弄完测试加载到耿鬼VS尼多力诺动画那里死机了
回复 支持 反对

使用道具 举报

3333

回帖

551

现金

427

勋章券

超级版主

Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26

积分
20820
QQ

时光印记Lv.3挥金如土勋章水中王者勋章Lv3Omega红宝石发售确认纪念章Alpha蓝宝石发售确认纪念章金银好CP-Ho-oh/LUGIA【里】金银好CP-Ho-oh/LUGIA【真·正常向】异化型LUGIA【M超梦版】

 楼主| 发表于 2017-2-12 22:24:44 | 显示全部楼层
本帖最后由 jiangzhengwenjz 于 2017-2-12 22:26 编辑
sfsefsdfsd 发表于 2017-2-12 14:13
弄完测试加载到耿鬼VS尼多力诺动画那里死机了


以前实测过没问题,可能是教程哪里写错了?我依据的是这个:
  1. .org 0x080007B4
  2. .word  0x0203E000   // new PCM work area
  3. .org 0x081DD0B4
  4. .word  main_mixer   // new mixer ROM location
  5. .word  0x03005F50   // new mixer RAM location (used for loading)
  6. .halfword mixer_size
  7. .halfword 0x400        // CpuSet, copy code by 32 bit units
  8. .word  0x0203E000   // new PCM work area
  9. .org 0x081DD0C8
  10. // set correct sound driver operation mode
  11. // 12 channels at 26758 Hz samplerate
  12. .byte  0x00, 0xCC, 0x98, 0x00
  13. .org 0x081DC094
  14. .word  0x03005F50+1 // new mixer RAM location (used for branch)
复制代码
其中唯一不同的恐怕也就是0x1DD0C8的位置吧,不过我之前姑且把它当做修改sample rate了。
.org就是写入的地址,.word,.halfword是写入4,2字节(反写Little Endian),.byte是依次写入一字节
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入口袋中心

本版积分规则

手机版|Archiver|Pokemon Center

GMT+8, 2023-10-1 22:28 , Processed in 0.115631 second(s), 43 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表