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