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