ym2612_arm.S 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. /*
  2. * PicoDrive
  3. * (C) notaz, 2006
  4. * (C) kub, 2020 added SSG-EG and simple output rate interpolation
  5. *
  6. * This work is licensed under the terms of MAME license.
  7. * See COPYING file in the top-level directory.
  8. */
  9. @ this is a rewrite of MAME's ym2612 code, in particular this is only the main sample-generatin loop.
  10. @ it does not seem to give much performance increase (if any at all), so don't use it if it causes trouble.
  11. @ - notaz, 2006
  12. @ vim:filetype=armasm
  13. #include <pico/arm_features.h>
  14. @ very simple YM2612 output rate to sample rate adaption (~500k cycles @44100)
  15. #define INTERPOL
  16. #define SSG_EG
  17. .equiv SLOT1, 0
  18. .equiv SLOT2, 2
  19. .equiv SLOT3, 1
  20. .equiv SLOT4, 3
  21. .equiv SLOT_STRUCT_SIZE, 0x38
  22. .equiv TL_TAB_LEN, 0x1A00
  23. .equiv EG_ATT, 4
  24. .equiv EG_DEC, 3
  25. .equiv EG_SUS, 2
  26. .equiv EG_REL, 1
  27. .equiv EG_OFF, 0
  28. .equiv EG_SH, 16 @ 16.16 fixed point (envelope generator timing)
  29. .equiv EG_TIMER_OVERFLOW, (3*(1<<EG_SH)) @ envelope generator timer overflows every 3 samples (on real chip)
  30. .equiv LFO_SH, 24 /* 8.24 fixed point (LFO calculations) */
  31. .equiv ENV_QUIET, (2*13*256/8)
  32. .text
  33. .align 2
  34. PIC_LDR_INIT()
  35. @ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
  36. @ writes output to routp, but only if vol_out changes
  37. .macro update_eg_phase_slot
  38. #if defined(INTERPOL)
  39. ldrh r0, [r5,#0x34] @ vol_out
  40. #endif
  41. ldrb r2, [r5,#0x17] @ state
  42. add r3, r5, #0x1c
  43. #if defined(INTERPOL)
  44. strh r0, [r5,#0x36] @ vol_ipol
  45. #endif
  46. tst r2, r2
  47. beq 0f @ EG_OFF
  48. ldr r2, [r3, r2, lsl #2] @ pack
  49. mov r3, #1
  50. mov r0, r2, lsr #24 @ shift
  51. mov r3, r3, lsl r0
  52. sub r3, r3, #1
  53. tst r1, r3
  54. bne 0f @ no volume change
  55. mov r3, r1, lsr r0
  56. ldrb r0, [r5,#0x30] @ ssg
  57. and r3, r3, #7
  58. add r3, r3, r3, lsl #1
  59. mov r3, r2, lsr r3
  60. and r3, r3, #7 @ eg_inc_val shift, may be 0
  61. ldrb r2, [r5,#0x17] @ state
  62. #if defined(SSG_EG)
  63. tst r0, #0x08 @ ssg enabled?
  64. tstne r12, #0x02
  65. bne 9f
  66. #endif
  67. @ non-SSG-EG mode
  68. cmp r2, #4 @ EG_ATT
  69. ldrh r0, [r5,#0x1a] @ volume, unsigned (0-1023)
  70. beq 4f
  71. cmp r2, #2
  72. mov r2, #1
  73. mov r2, r2, lsl r3
  74. mov r2, r2, lsr #1 @ eg_inc_val
  75. add r0, r0, r2
  76. blt 1f @ EG_REL
  77. beq 2f @ EG_SUS
  78. 3: @ EG_DEC
  79. ldr r2, [r5,#0x1c] @ sl (can be 16bit?)
  80. mov r3, #EG_SUS
  81. cmp r0, r2 @ if ( volume >= (INT32) SLOT->sl )
  82. strgeb r3, [r5,#0x17] @ state
  83. b 10f
  84. 4: @ EG_ATT
  85. subs r3, r3, #1 @ eg_inc_val_shift - 1
  86. mvnpl r2, r0
  87. movpl r2, r2, lsl r3
  88. addpl r0, r0, r2, asr #4
  89. cmp r0, #0 @ if (volume <= MIN_ATT_INDEX)
  90. bgt 10f
  91. ldr r2, [r5,#0x1c]
  92. mov r0, #0
  93. cmp r2, #0
  94. movne r3, #EG_DEC
  95. moveq r3, #EG_SUS
  96. strb r3, [r5,#0x17] @ state
  97. b 10f
  98. 2: @ EG_SUS
  99. mov r2, #1024
  100. sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
  101. cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
  102. movge r0, r2
  103. b 10f
  104. 1: @ EG_REL
  105. mov r2, #1024
  106. sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
  107. cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
  108. movge r0, r2
  109. movge r3, #EG_OFF
  110. strgeb r3, [r5,#0x17] @ state
  111. 10: @ finish
  112. ldrh r3, [r5,#0x18] @ tl
  113. strh r0, [r5,#0x1a] @ volume
  114. #if defined(SSG_EG)
  115. b 11f
  116. 9: @ SSG-EG mode
  117. ldrh r0, [r5,#0x1a] @ volume, unsigned (0-1023)
  118. cmp r2, #4 @ EG_ATT
  119. beq 4f
  120. cmp r0, #0x200 @ if ( volume < 0x200 )
  121. movlt r0, #1
  122. movlt r3, r0, lsl r3
  123. ldrlth r0, [r5,#0x1a] @ volume, unsigned (0-1023)
  124. movlt r3, r3, lsr #1 @ eg_inc_val
  125. addlt r0, r0, r3, lsl #2
  126. cmp r2, #2
  127. blt 1f @ EG_REL
  128. beq 10f @ EG_SUS - nothing more to do
  129. 3: @ EG_DEC
  130. ldr r2, [r5,#0x1c] @ sl (can be 16bit?)
  131. mov r3, #EG_SUS
  132. cmp r0, r2 @ if ( volume >= (INT32) SLOT->sl )
  133. strgeb r3, [r5,#0x17] @ state
  134. b 10f
  135. 4: @ EG_ATT
  136. subs r3, r3, #1 @ eg_inc_val_shift - 1
  137. mvnpl r2, r0
  138. movpl r2, r2, lsl r3
  139. addpl r0, r0, r2, asr #4
  140. cmp r0, #0 @ if (volume <= MIN_ATT_INDEX)
  141. bgt 10f
  142. ldr r2, [r5,#0x1c] @ sl
  143. mov r0, #0
  144. cmp r2, #0
  145. movne r3, #EG_DEC
  146. moveq r3, #EG_SUS
  147. strb r3, [r5,#0x17] @ state
  148. b 10f
  149. 1: @ EG_REL
  150. cmp r0, #0x200 @ if ( volume >= 0x200 )
  151. movge r0, #1024
  152. subge r0, #1
  153. movge r3, #EG_OFF
  154. strgeb r3, [r5,#0x17] @ state
  155. 10: @ finish
  156. ldrb r2, [r5,#0x30] @ ssg
  157. ldrb r3, [r5,#0x17] @ state
  158. strh r0, [r5,#0x1a] @ volume
  159. cmp r2, #0x0c @ if ( ssg&0x04 && state > EG_REL )
  160. cmpge r3, #EG_REL+1
  161. ldrh r3, [r5,#0x18] @ tl
  162. rsbge r0, r0, #0x200 @ volume = (0x200-volume) & MAX_ATT
  163. lslge r0, r0, #22
  164. lsrge r0, r0, #22
  165. 11:
  166. #endif
  167. add r0, r0, r3 @ volume += tl
  168. strh r0, [r5,#0x34] @ vol_out
  169. 0: @ EG_OFF
  170. .endm
  171. #if defined(SSG_EG)
  172. @ r5=slot, trashes: r0,r2,r3
  173. .macro update_ssg_eg
  174. ldrh r0, [r5,#0x30] @ ssg+ssgn
  175. ldrb r2, [r5,#0x17] @ state
  176. ldrh r3, [r5,#0x1a] @ volume
  177. tst r0, #0x08 @ ssg enabled &&
  178. beq 9f
  179. cmp r2, #EG_REL+1 @ state > EG_REL &&
  180. cmpge r3, #0x200 @ volume >= 0x200?
  181. blt 9f
  182. orr r4, r4, #0x10 @ ssg_update
  183. tst r0, #0x01
  184. beq 1f
  185. tst r0, #0x02
  186. eorne r0, r0, lsr #8 @ ssg ^= ssgn ^ 4
  187. eorne r0, r0, #0x4
  188. orrne r0, r0, #0x400 @ ssgn = 4
  189. strneh r0, [r5,#0x30]
  190. eor r0, r0, #0x4 @ if ( !(ssg&0x04) )
  191. tst r0, #0x4
  192. cmpne r2, #EG_ATT @ if ( state != EG_ATT )
  193. movne r3, #0x400
  194. subne r3, r3, #1
  195. strneh r3, [r5,#0x1a] @ volume = MAX_ATT
  196. b 9f
  197. 1: tst r0, #0x02
  198. eorne r0, r0, #0x4 @ ssg ^= 4
  199. eorne r0, r0, #0x400 @ ssgn ^= 4
  200. strneh r0, [r5,#0x30]
  201. moveq r0, #0
  202. streq r0, [lr,#0x10] @ phase = 0
  203. cmp r2, #EG_ATT @ if ( state != EG_ATT )
  204. beq 9f
  205. ldr r0, [r5,#0x1c] @ sl
  206. mov r2, #EG_SUS @ state = sl==MIN_ATT ? EG_SUS:EG_DEC
  207. cmp r0, #0
  208. ldrh r0, [r5,#0x32] @ ar+ksr
  209. movne r2, #EG_DEC
  210. cmp r0, #32+62 @ if ( ar+ksr >= 32+62 )
  211. movge r3, #0
  212. strgeh r3, [r5,#0x1a] @ volume = MIN_ATT
  213. bge 8f
  214. cmp r3, #0
  215. movgt r2, #EG_ATT
  216. 8: strb r2, [r5,#0x17] @ state
  217. 9:
  218. .endm
  219. @ r5=slot, trashes: r0,r2,r3
  220. .macro recalc_volout
  221. #if defined(INTERPOL)
  222. ldrh r0, [r5,#0x34] @ vol_out
  223. #endif
  224. ldrb r2, [r5,#0x30] @ ssg
  225. ldrb r3, [r5,#0x17] @ state
  226. #if defined(INTERPOL)
  227. strh r0, [r5,#0x36] @ vol_ipol
  228. #endif
  229. ldrh r0, [r5,#0x1a] @ volume
  230. @ and r2, r2, #0x0c
  231. cmp r2, #0x0c @ if ( ~ssg&0x0c && state > EG_REL )
  232. cmpge r3, #EG_REL+1
  233. ldrh r3, [r5,#0x18] @ tl
  234. rsbge r0, r0, #0x200 @ volume = (0x200-volume) & MAX_ATT
  235. lslge r0, r0, #22
  236. lsrge r0, r0, #22
  237. add r0, r0, r3 @ volume += tl
  238. strh r0, [r5,#0x34] @ vol_out
  239. .endm
  240. #endif
  241. @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt, r3=scratch
  242. .macro advance_lfo_m
  243. mov r2, r2, lsr #LFO_SH
  244. cmp r2, r1, lsr #LFO_SH
  245. beq 0f
  246. and r3, r2, #0x3f
  247. cmp r2, #0x40
  248. eorlt r3, r3, #0x3f
  249. bic r12,r12, #0xff000000 @ lfo_ampm &= 0xff
  250. orr r12,r12, r3, lsl #1+24
  251. mov r2, r2, lsr #2
  252. cmp r2, r1, lsr #LFO_SH+2
  253. bicne r12,r12, #0xff0000
  254. orrne r12,r12, r2, lsl #16
  255. 0:
  256. .endm
  257. @ result goes to r1, trashes r2
  258. .macro make_eg_out slot
  259. tst r12, #8
  260. tstne r12, #(1<<(\slot+8))
  261. .if \slot == SLOT1
  262. mov r1, r6, lsl #16
  263. mov r1, r1, lsr #16
  264. .elseif \slot == SLOT2
  265. mov r1, r6, lsr #16
  266. .elseif \slot == SLOT3
  267. mov r1, r7, lsl #16
  268. mov r1, r1, lsr #16
  269. .elseif \slot == SLOT4
  270. mov r1, r7, lsr #16
  271. .endif
  272. andne r2, r12, #0xc0
  273. movne r2, r2, lsr #6
  274. addne r2, r2, #24
  275. addne r1, r1, r12, lsr r2
  276. bic r1, r1, #1
  277. .endm
  278. @ \r=sin/result, r1=env, r3=ym_tl_tab
  279. .macro lookup_tl r
  280. tst \r, #0x100
  281. eorne \r, \r, #0xff @ if (sin & 0x100) sin = 0xff - (sin&0xff);
  282. tst \r, #0x200
  283. and \r, \r, #0xff
  284. orr \r, \r, r1, lsl #7
  285. mov \r, \r, lsl #1
  286. ldrh \r, [r3, \r] @ 2ci if ne
  287. rsbne \r, \r, #0
  288. .endm
  289. @ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
  290. @ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
  291. .macro upd_algo0_m
  292. @ SLOT3
  293. make_eg_out SLOT3
  294. cmp r1, #ENV_QUIET
  295. movcs r0, #0
  296. bcs 0f
  297. ldr r2, [lr, #0x18]
  298. ldr r0, [lr, #0x38] @ mem (signed)
  299. mov r2, r2, lsr #16
  300. add r0, r2, r0, lsr #1
  301. lookup_tl r0 @ r0=c2
  302. 0:
  303. @ SLOT4
  304. make_eg_out SLOT4
  305. cmp r1, #ENV_QUIET
  306. movcs r0, #0
  307. bcs 1f
  308. ldr r2, [lr, #0x1c]
  309. mov r0, r0, lsr #1
  310. add r0, r0, r2, lsr #16
  311. lookup_tl r0 @ r0=output smp
  312. 1:
  313. @ SLOT2
  314. make_eg_out SLOT2
  315. cmp r1, #ENV_QUIET
  316. movcs r2, #0
  317. bcs 2f
  318. ldr r2, [lr, #0x14] @ 1ci
  319. mov r5, r10, lsr #17
  320. add r2, r5, r2, lsr #16
  321. lookup_tl r2 @ r2=mem
  322. 2:
  323. str r2, [lr, #0x38] @ mem
  324. .endm
  325. .macro upd_algo1_m
  326. @ SLOT3
  327. make_eg_out SLOT3
  328. cmp r1, #ENV_QUIET
  329. movcs r0, #0
  330. bcs 0f
  331. ldr r2, [lr, #0x18]
  332. ldr r0, [lr, #0x38] @ mem (signed)
  333. mov r2, r2, lsr #16
  334. add r0, r2, r0, lsr #1
  335. lookup_tl r0 @ r0=c2
  336. 0:
  337. @ SLOT4
  338. make_eg_out SLOT4
  339. cmp r1, #ENV_QUIET
  340. movcs r0, #0
  341. bcs 1f
  342. ldr r2, [lr, #0x1c]
  343. mov r0, r0, lsr #1
  344. add r0, r0, r2, lsr #16
  345. lookup_tl r0 @ r0=output smp
  346. 1:
  347. @ SLOT2
  348. make_eg_out SLOT2
  349. cmp r1, #ENV_QUIET
  350. movcs r2, #0
  351. bcs 2f
  352. ldr r2, [lr, #0x14] @ 1ci
  353. mov r2, r2, lsr #16
  354. lookup_tl r2 @ r2=mem
  355. 2:
  356. add r2, r2, r10, asr #16
  357. str r2, [lr, #0x38]
  358. .endm
  359. .macro upd_algo2_m
  360. @ SLOT3
  361. make_eg_out SLOT3
  362. cmp r1, #ENV_QUIET
  363. movcs r0, #0
  364. bcs 0f
  365. ldr r2, [lr, #0x18]
  366. ldr r0, [lr, #0x38] @ mem (signed)
  367. mov r2, r2, lsr #16
  368. add r0, r2, r0, lsr #1
  369. lookup_tl r0 @ r0=c2
  370. 0:
  371. add r0, r0, r10, asr #16
  372. @ SLOT4
  373. make_eg_out SLOT4
  374. cmp r1, #ENV_QUIET
  375. movcs r0, #0
  376. bcs 1f
  377. ldr r2, [lr, #0x1c]
  378. mov r0, r0, lsr #1
  379. add r0, r0, r2, lsr #16
  380. lookup_tl r0 @ r0=output smp
  381. 1:
  382. @ SLOT2
  383. make_eg_out SLOT2
  384. cmp r1, #ENV_QUIET
  385. movcs r2, #0
  386. bcs 2f
  387. ldr r2, [lr, #0x14]
  388. mov r2, r2, lsr #16 @ 1ci
  389. lookup_tl r2 @ r2=mem
  390. 2:
  391. str r2, [lr, #0x38] @ mem
  392. .endm
  393. .macro upd_algo3_m
  394. @ SLOT3
  395. make_eg_out SLOT3
  396. cmp r1, #ENV_QUIET
  397. ldr r2, [lr, #0x38] @ mem (for future)
  398. mov r0, #0
  399. bcs 0f
  400. ldr r0, [lr, #0x18] @ phase3
  401. mov r0, r0, lsr #16
  402. lookup_tl r0 @ r0=c2
  403. 0:
  404. add r0, r0, r2
  405. @ SLOT4
  406. make_eg_out SLOT4
  407. cmp r1, #ENV_QUIET
  408. movcs r0, #0
  409. bcs 1f
  410. ldr r2, [lr, #0x1c]
  411. mov r0, r0, lsr #1
  412. add r0, r0, r2, lsr #16
  413. lookup_tl r0 @ r0=output smp
  414. 1:
  415. @ SLOT2
  416. make_eg_out SLOT2
  417. cmp r1, #ENV_QUIET
  418. movcs r2, #0
  419. bcs 2f
  420. ldr r2, [lr, #0x14] @ phase2
  421. mov r5, r10, lsr #17
  422. add r2, r5, r2, lsr #16
  423. lookup_tl r2 @ r2=mem
  424. 2:
  425. str r2, [lr, #0x38] @ mem
  426. .endm
  427. .macro upd_algo4_m
  428. @ SLOT3
  429. make_eg_out SLOT3
  430. cmp r1, #ENV_QUIET
  431. movcs r0, #0
  432. bcs 0f
  433. ldr r0, [lr, #0x18]
  434. mov r0, r0, lsr #16 @ 1ci
  435. lookup_tl r0 @ r0=c2
  436. 0:
  437. @ SLOT4
  438. make_eg_out SLOT4
  439. cmp r1, #ENV_QUIET
  440. movcs r0, #0
  441. bcs 1f
  442. ldr r2, [lr, #0x1c]
  443. mov r0, r0, lsr #1
  444. add r0, r0, r2, lsr #16
  445. lookup_tl r0 @ r0=output smp
  446. 1:
  447. @ SLOT2
  448. make_eg_out SLOT2
  449. cmp r1, #ENV_QUIET
  450. bcs 2f
  451. ldr r2, [lr, #0x14]
  452. mov r5, r10, lsr #17
  453. add r2, r5, r2, lsr #16
  454. lookup_tl r2
  455. add r0, r0, r2 @ add to smp
  456. 2:
  457. .endm
  458. .macro upd_algo5_m
  459. @ SLOT3
  460. make_eg_out SLOT3
  461. cmp r1, #ENV_QUIET
  462. movcs r0, #0
  463. bcs 0f
  464. ldr r2, [lr, #0x18]
  465. ldr r0, [lr, #0x38] @ mem (signed)
  466. mov r2, r2, lsr #16
  467. add r0, r2, r0, lsr #1
  468. lookup_tl r0 @ r0=output smp
  469. 0:
  470. @ SLOT4
  471. make_eg_out SLOT4
  472. cmp r1, #ENV_QUIET
  473. bcs 1f
  474. ldr r2, [lr, #0x1c]
  475. mov r5, r10, lsr #17
  476. add r2, r5, r2, lsr #16
  477. lookup_tl r2
  478. add r0, r0, r2 @ add to smp
  479. 1: @ SLOT2
  480. make_eg_out SLOT2
  481. cmp r1, #ENV_QUIET
  482. bcs 2f
  483. ldr r2, [lr, #0x14]
  484. mov r5, r10, lsr #17
  485. add r2, r5, r2, lsr #16
  486. lookup_tl r2
  487. add r0, r0, r2 @ add to smp
  488. 2:
  489. mov r1, r10, asr #16
  490. str r1, [lr, #0x38] @ mem
  491. .endm
  492. .macro upd_algo6_m
  493. @ SLOT3
  494. make_eg_out SLOT3
  495. cmp r1, #ENV_QUIET
  496. movcs r0, #0
  497. bcs 0f
  498. ldr r0, [lr, #0x18]
  499. mov r0, r0, lsr #16 @ 1ci
  500. lookup_tl r0 @ r0=output smp
  501. 0:
  502. @ SLOT4
  503. make_eg_out SLOT4
  504. cmp r1, #ENV_QUIET
  505. bcs 1f
  506. ldr r2, [lr, #0x1c]
  507. mov r2, r2, lsr #16 @ 1ci
  508. lookup_tl r2
  509. add r0, r0, r2 @ add to smp
  510. 1: @ SLOT2
  511. make_eg_out SLOT2
  512. cmp r1, #ENV_QUIET
  513. bcs 2f
  514. ldr r2, [lr, #0x14]
  515. mov r5, r10, lsr #17
  516. add r2, r5, r2, lsr #16
  517. lookup_tl r2
  518. add r0, r0, r2 @ add to smp
  519. 2:
  520. .endm
  521. .macro upd_algo7_m
  522. @ SLOT3
  523. make_eg_out SLOT3
  524. cmp r1, #ENV_QUIET
  525. movcs r0, #0
  526. bcs 0f
  527. ldr r0, [lr, #0x18]
  528. mov r0, r0, lsr #16 @ 1ci
  529. lookup_tl r0 @ r0=output smp
  530. 0:
  531. add r0, r0, r10, asr #16
  532. @ SLOT4
  533. make_eg_out SLOT4
  534. cmp r1, #ENV_QUIET
  535. bcs 1f
  536. ldr r2, [lr, #0x1c]
  537. mov r2, r2, lsr #16 @ 1ci
  538. lookup_tl r2
  539. add r0, r0, r2 @ add to smp
  540. 1: @ SLOT2
  541. make_eg_out SLOT2
  542. cmp r1, #ENV_QUIET
  543. bcs 2f
  544. ldr r2, [lr, #0x14]
  545. mov r2, r2, lsr #16 @ 1ci
  546. lookup_tl r2
  547. add r0, r0, r2 @ add to smp
  548. 2:
  549. .endm
  550. .macro upd_slot1_m
  551. make_eg_out SLOT1
  552. cmp r1, #ENV_QUIET
  553. movcs r10, r10, lsl #16 @ ct->op1_out <<= 16; // op1_out0 = op1_out1; op1_out1 = 0;
  554. bcs 0f
  555. ands r2, r12, #0xf000
  556. moveq r0, #0
  557. movne r2, r2, lsr #12
  558. addne r0, r10, r10, lsl #16
  559. movne r0, r0, asr #16
  560. movne r0, r0, lsl r2
  561. ldr r2, [lr, #0x10] @ phase1
  562. add r0, r0, r2
  563. mov r0, r0, lsr #16
  564. lookup_tl r0
  565. mov r10,r10,lsl #16 @ ct->op1_out <<= 16;
  566. mov r0, r0, lsl #16
  567. orr r10,r10, r0, lsr #16
  568. 0:
  569. .endm
  570. @ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
  571. @ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|dac,unused[2],ssg_update,was_update,algo[3], r5=tl_tab/slot,
  572. @ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer
  573. .global chan_render_loop @ chan_rend_context *ct, int *buffer, int length
  574. chan_render_loop:
  575. stmfd sp!, {r4-r11,lr}
  576. mov lr, r0
  577. mov r4, r2, lsl #8 @ no more 24 bits here
  578. ldr r12, [lr, #0x4c]
  579. ldr r0, [lr, #0x50]
  580. mov r11, r1
  581. and r0, r0, #0x87
  582. orr r4, r4, r0 @ (length<<8)|dac,unused[4],algo[3]
  583. ldr r8, [lr, #0x44] @ eg_timer
  584. ldr r9, [lr, #0x48] @ eg_timer_add
  585. ldr r10, [lr, #0x54] @ op1_out
  586. tst r12, #8 @ lfo?
  587. beq crl_loop
  588. crl_loop_lfo:
  589. ldr r1, [lr, #0x30] @ lfo_cnt
  590. ldr r2, [lr, #0x34] @ lfo_inc
  591. subs r4, r4, #0x100
  592. bmi crl_loop_end
  593. add r2, r2, r1
  594. str r2, [lr, #0x30]
  595. @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
  596. advance_lfo_m
  597. add r4, r4, #0x100
  598. crl_loop:
  599. subs r4, r4, #0x100
  600. bmi crl_loop_end
  601. ldr r5, [lr, #0x40] @ CH
  602. #if defined(SSG_EG)
  603. tst r12, #0x02 @ ssg_enabled?
  604. beq ssg_done
  605. @ -- SSG --
  606. lsl r7, r8, #EG_SH
  607. add r7, r9, r7, lsr #EG_SH
  608. subs r7, r7, #1<<EG_SH
  609. blt ssg_done
  610. ssg_loop:
  611. mov r6, #4
  612. bic r4, r4, #0x10 @ ssg_update
  613. ssg_upd_loop:
  614. @ use lr as a pointer to the slot phases stored in the context
  615. update_ssg_eg
  616. #if 0
  617. subs r6, r6, #1
  618. addne lr, lr, #4
  619. addne r5, r5, #SLOT_STRUCT_SIZE
  620. #else
  621. add lr, lr, #4*2
  622. add r5, r5, #SLOT_STRUCT_SIZE*2
  623. update_ssg_eg
  624. subs r6, r6, #2
  625. subne lr, lr, #4
  626. subne r5, r5, #SLOT_STRUCT_SIZE
  627. #endif
  628. bne ssg_upd_loop
  629. sub lr, lr, #4*3
  630. sub r5, r5, #SLOT_STRUCT_SIZE*3
  631. subs r7, r7, #1<<EG_SH
  632. bge ssg_loop
  633. ssg_done:
  634. #endif
  635. @ -- EG --
  636. add r8, r8, r9
  637. cmp r8, #EG_TIMER_OVERFLOW
  638. blo volout_upd
  639. ldr r1, [lr, #0x3c] @ eg_cnt
  640. eg_loop:
  641. sub r8, r8, #EG_TIMER_OVERFLOW
  642. add r1, r1, #1
  643. cmp r1, #4096
  644. movge r1, #1
  645. mov r6, #4
  646. eg_upd_loop:
  647. update_eg_phase_slot
  648. #if 1
  649. subs r6, r6, #1
  650. addne r5, r5, #SLOT_STRUCT_SIZE
  651. #else
  652. add r5, r5, #SLOT_STRUCT_SIZE*2
  653. update_eg_phase_slot
  654. subs r6, r6, #2
  655. subne r5, r5, #SLOT_STRUCT_SIZE
  656. #endif
  657. bne eg_upd_loop
  658. cmp r8, #EG_TIMER_OVERFLOW
  659. sub r5, r5, #SLOT_STRUCT_SIZE*3
  660. bhs eg_loop
  661. str r1, [lr, #0x3c]
  662. b eg_done
  663. volout_upd:
  664. #if defined(SSG_EG)
  665. tst r4, #0x10 @ ssg_update?
  666. beq eg_done
  667. @ recalc vol_out
  668. mov r6, #4
  669. volout_loop:
  670. recalc_volout
  671. #if 0
  672. subs r6, r6, #1
  673. addne r5, r5, #SLOT_STRUCT_SIZE
  674. #else
  675. add r5, r5, #SLOT_STRUCT_SIZE*2
  676. recalc_volout
  677. subs r6, r6, #2
  678. subne r5, r5, #SLOT_STRUCT_SIZE
  679. #endif
  680. bne volout_loop
  681. sub r5, r5, #SLOT_STRUCT_SIZE*3
  682. #endif
  683. eg_done:
  684. @ -- disabled? --
  685. and r0, r12, #0xC
  686. cmp r0, #0xC
  687. beq crl_loop_lfo
  688. cmp r0, #0x4
  689. beq crl_loop
  690. @ output interpolation
  691. #if defined(INTERPOL)
  692. #if 1 // possibly too expensive for slow platforms?
  693. @ basic interpolator, interpolate in middle region, else use closer value
  694. mov r3, r8, lsr #EG_SH @ eg_timer, [0..3<<EG_SH) after loop
  695. cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH)/2
  696. bne 0f @ mix is vol_out
  697. ldr r6, [r5, #0x34] @ vol_out, vol_ipol for all slots
  698. ldr r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
  699. ldr r7, [r5, #0x34+SLOT_STRUCT_SIZE]
  700. ldr r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
  701. add r6, r6, r6, lsl #16
  702. lsr r6, r6, #17
  703. add r2, r2, r2, lsl #16
  704. lsr r2, r2, #17
  705. add r7, r7, r7, lsl #16
  706. lsr r7, r7, #17
  707. add r3, r3, r3, lsl #16
  708. lsr r3, r3, #17
  709. b 1f
  710. #else
  711. @ super-basic... just take value closest to sample point
  712. mov r3, r8, lsr #EG_SH-1 @ eg_timer, [0..3<<EG_SH) after loop
  713. cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH)
  714. #endif
  715. 0: ldrgeh r6, [r5, #0x34] @ vol_out values for all slots
  716. ldrlth r6, [r5, #0x36] @ vol_ipol values for all slots
  717. ldrgeh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
  718. ldrlth r2, [r5, #0x36+SLOT_STRUCT_SIZE*2]
  719. ldrgeh r7, [r5, #0x34+SLOT_STRUCT_SIZE]
  720. ldrlth r7, [r5, #0x36+SLOT_STRUCT_SIZE]
  721. ldrgeh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
  722. ldrlth r3, [r5, #0x36+SLOT_STRUCT_SIZE*3]
  723. #else
  724. ldrh r6, [r5, #0x34] @ vol_out values for all slots
  725. ldrh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
  726. ldrh r7, [r5, #0x34+SLOT_STRUCT_SIZE]
  727. ldrh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
  728. #endif
  729. 1: orr r6, r6, r2, lsl #16
  730. orr r7, r7, r3, lsl #16
  731. @ -- SLOT1 --
  732. PIC_LDR(r3, r2, ym_tl_tab)
  733. @ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
  734. @ r0-r2=scratch, r3=tl_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
  735. upd_slot1_m
  736. @ -- SLOT2+ --
  737. and r0, r4, #7
  738. PIC_XB(,r0, lsl #2)
  739. nop
  740. PIC_BT(crl_algo0)
  741. PIC_BT(crl_algo1)
  742. PIC_BT(crl_algo2)
  743. PIC_BT(crl_algo3)
  744. PIC_BT(crl_algo4)
  745. PIC_BT(crl_algo5)
  746. PIC_BT(crl_algo6)
  747. PIC_BT(crl_algo7)
  748. .pool
  749. crl_algo0:
  750. upd_algo0_m
  751. b crl_algo_done
  752. .pool
  753. crl_algo1:
  754. upd_algo1_m
  755. b crl_algo_done
  756. .pool
  757. crl_algo2:
  758. upd_algo2_m
  759. b crl_algo_done
  760. .pool
  761. crl_algo3:
  762. upd_algo3_m
  763. b crl_algo_done
  764. .pool
  765. crl_algo4:
  766. upd_algo4_m
  767. b crl_algo_done
  768. .pool
  769. crl_algo5:
  770. upd_algo5_m
  771. b crl_algo_done
  772. .pool
  773. crl_algo6:
  774. upd_algo6_m
  775. b crl_algo_done
  776. .pool
  777. crl_algo7:
  778. upd_algo7_m
  779. crl_algo_done:
  780. @ -- WRITE SAMPLE --
  781. tst r0, r0
  782. beq ctl_sample_skip
  783. orr r4, r4, #8 @ have_output
  784. lsr r1, r0, #31 @ clip (saturate) sample to 14 bit
  785. cmn r1, r0, asr #13
  786. subne r0, r1, #0x80000001
  787. asrne r0, r0, #18
  788. tst r4, r1, lsl #7 @ (sample < 0) && dac?
  789. bicne r0, r0, #0x1f
  790. subne r0, r0, #7<<5
  791. tst r12, #1
  792. beq ctl_sample_mono
  793. tst r12, #0x20 @ L
  794. ldrne r1, [r11]
  795. addeq r11, r11, #4
  796. addne r1, r0, r1
  797. strne r1, [r11], #4
  798. tst r12, #0x10 @ R
  799. ldrne r1, [r11]
  800. addeq r11, r11, #4
  801. addne r1, r0, r1
  802. strne r1, [r11], #4
  803. b crl_do_phase
  804. ctl_sample_mono:
  805. ldr r1, [r11]
  806. add r1, r0, r1
  807. str r1, [r11], #4
  808. b crl_do_phase
  809. ctl_sample_skip:
  810. and r1, r12, #1
  811. add r1, r1, #1
  812. add r11,r11, r1, lsl #2
  813. crl_do_phase:
  814. @ -- PHASE UPDATE --
  815. add r5, lr, #0x10
  816. ldmia r5, {r0-r3,r6-r7}
  817. add r0, r0, r6
  818. add r1, r1, r7
  819. ldr r6, [r5, #0x18]
  820. ldr r7, [r5, #0x1c]
  821. add r2, r2, r6
  822. add r3, r3, r7
  823. stmia r5, {r0-r3}
  824. tst r12, #8
  825. bne crl_loop_lfo
  826. b crl_loop
  827. crl_loop_end:
  828. str r8, [lr, #0x44] @ eg_timer
  829. str r12, [lr, #0x4c] @ pack (for lfo_ampm)
  830. str r4, [lr, #0x50] @ was_update
  831. str r10, [lr, #0x54] @ op1_out
  832. ldmfd sp!, {r4-r11,pc}
  833. .pool
  834. @ vim:filetype=armasm