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.
9 .equiv SLOT_STRUCT_SIZE, 0x30
11 .equiv TL_TAB_LEN, 0x1A00
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) */
23 .equiv ENV_QUIET, (2*13*256/8)/2
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
39 ldr r2, [r5,#0x20] @ eg_pack_ar (1ci)
44 bne 5f @ do smth for tl problem (set on init?)
46 ldrh r0, [r5,#0x1a] @ volume, unsigned (0-1023)
48 add r3, r3, r3, lsl #1
50 and r3, r3, #7 @ shift for eg_inc calculation
53 add r0, r0, r2, asr #5
54 cmp r0, #0 @ if (volume <= MIN_ATT_INDEX)
56 strleb r3, [r5,#0x17] @ state
61 ldr r2, [r5,#0x24] @ eg_pack_d1r (1ci)
66 bne 5f @ do smth for tl problem (set on init?)
68 ldrh r0, [r5,#0x1a] @ volume
70 add r3, r3, r3, lsl #1
72 and r3, r3, #7 @ shift for eg_inc calculation
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 )
79 strgeb r3, [r5,#0x17] @ state
83 ldr r2, [r5,#0x28] @ eg_pack_d2r (1ci)
88 bne 5f @ do smth for tl problem (set on init?)
90 ldrh r0, [r5,#0x1a] @ volume
92 add r3, r3, r3, lsl #1
94 and r3, r3, #7 @ shift for eg_inc calculation
97 add r0, r0, r3, asr #1
99 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
100 cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
105 ldr r2, [r5,#0x2c] @ eg_pack_rr (1ci)
110 bne 5f @ do smth for tl problem (set on init?)
112 ldrh r0, [r5,#0x1a] @ volume
114 add r3, r3, r3, lsl #1
116 and r3, r3, #7 @ shift for eg_inc calculation
119 add r0, r0, r3, asr #1
121 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
122 cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
125 strgeb r3, [r5,#0x17] @ state
128 ldrh r3, [r5,#0x18] @ tl
129 strh r0, [r5,#0x1a] @ volume
133 orr r6, r0, r6, lsl #16
134 .elseif \slot == SLOT2
138 orr r6, r0, r6, lsr #16
139 .elseif \slot == SLOT3
142 orr r7, r0, r7, lsl #16
143 .elseif \slot == SLOT4
147 orr r7, r0, r7, lsr #16
154 @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt, r3=scratch
156 mov r2, r2, lsr #LFO_SH
157 cmp r2, r1, lsr #LFO_SH
162 bic r12,r12, #0xff000000 @ lfo_ampm &= 0xff
163 orr r12,r12, r3, lsl #1+24
166 cmp r2, r1, lsr #LFO_SH+2
167 bicne r12,r12, #0xff0000
168 orrne r12,r12, r2, lsl #16
174 @ result goes to r1, trashes r2
175 .macro make_eg_out slot
177 tstne r12, #(1<<(\slot+8))
181 .elseif \slot == SLOT2
183 .elseif \slot == SLOT3
186 .elseif \slot == SLOT4
192 addne r1, r1, r12, lsr r2
198 eorne \r, \r, #0xff @ if (sin & 0x100) sin = 0xff - (sin&0xff);
201 orr \r, \r, r1, lsl #8
203 ldrh \r, [r3, \r] @ 2ci if ne
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
218 ldr r0, [lr, #0x38] @ mem (signed)
220 add r0, r2, r0, lsr #1
232 add r0, r0, r2, lsr #16
233 lookup_tl r0 @ r0=output smp
241 ldr r2, [lr, #0x14] @ 1ci
243 add r2, r5, r2, lsr #16
244 lookup_tl r2 @ r2=mem
247 str r2, [lr, #0x38] @ mem
259 ldr r0, [lr, #0x38] @ mem (signed)
261 add r0, r2, r0, lsr #1
272 add r0, r0, r2, lsr #16
273 lookup_tl r0 @ r0=output smp
281 ldr r2, [lr, #0x14] @ 1ci
283 lookup_tl r2 @ r2=mem
286 add r2, r2, r10, asr #16
299 ldr r0, [lr, #0x38] @ mem (signed)
301 add r0, r2, r0, lsr #1
305 add r0, r0, r10, asr #16
314 add r0, r0, r2, lsr #16
315 lookup_tl r0 @ r0=output smp
324 mov r2, r2, lsr #16 @ 1ci
325 lookup_tl r2 @ r2=mem
328 str r2, [lr, #0x38] @ mem
337 ldr r2, [lr, #0x38] @ mem (for future)
340 ldr r0, [lr, #0x18] @ 1ci
354 add r0, r0, r2, lsr #16
355 lookup_tl r0 @ r0=output smp
365 add r2, r5, r2, lsr #16
366 lookup_tl r2 @ r2=mem
369 str r2, [lr, #0x38] @ mem
381 mov r0, r0, lsr #16 @ 1ci
392 add r0, r0, r2, lsr #16
393 lookup_tl r0 @ r0=output smp
402 add r2, r5, r2, lsr #16
404 add r0, r0, r2 @ add to smp
418 ldr r0, [lr, #0x38] @ mem (signed)
420 add r0, r2, r0, lsr #1
421 lookup_tl r0 @ r0=output smp
430 add r2, r5, r2, lsr #16
432 add r0, r0, r2 @ add to smp
440 add r2, r5, r2, lsr #16
442 add r0, r0, r2 @ add to smp
446 str r1, [lr, #0x38] @ mem
458 mov r0, r0, lsr #16 @ 1ci
459 lookup_tl r0 @ r0=output smp
467 mov r2, r2, lsr #16 @ 1ci
469 add r0, r0, r2 @ add to smp
477 add r2, r5, r2, lsr #16
479 add r0, r0, r2 @ add to smp
493 mov r0, r0, lsr #16 @ 1ci
494 lookup_tl r0 @ r0=output smp
497 add r0, r0, r10, asr #16
504 mov r2, r2, lsr #16 @ 1ci
506 add r0, r0, r2 @ add to smp
513 mov r2, r2, lsr #16 @ 1ci
515 add r0, r0, r2 @ add to smp
525 movcs r10, r10, lsl #16 @ ct->op1_out <<= 16; // op1_out0 = op1_out1; op1_out1 = 0;
527 ands r2, r12, #0xf000
529 movne r2, r2, lsr #12
530 addne r0, r10, r10, lsl #16
531 movne r0, r0, asr #16
536 add r0, r0, r2, lsr #16
538 mov r10,r10,lsl #16 @ ct->op1_out <<= 16;
540 orr r10,r10, r0, lsr #16
547 .global update_eg_phase @ FM_SLOT *SLOT, UINT32 eg_cnt
552 ldrh r3, [r5,#0x18] @ tl
553 ldrh r6, [r5,#0x1a] @ volume
555 update_eg_phase_slot SLOT1
562 .global advance_lfo @ int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt
572 .global upd_algo0 @ chan_rend_context *c
574 stmfd sp!, {r4-r10,lr}
585 ldmfd sp!, {r4-r10,pc}
589 .global upd_algo1 @ chan_rend_context *c
591 stmfd sp!, {r4-r10,lr}
602 ldmfd sp!, {r4-r10,pc}
606 .global upd_algo2 @ chan_rend_context *c
608 stmfd sp!, {r4-r10,lr}
619 ldmfd sp!, {r4-r10,pc}
623 .global upd_algo3 @ chan_rend_context *c
625 stmfd sp!, {r4-r10,lr}
636 ldmfd sp!, {r4-r10,pc}
640 .global upd_algo4 @ chan_rend_context *c
642 stmfd sp!, {r4-r10,lr}
653 ldmfd sp!, {r4-r10,pc}
657 .global upd_algo5 @ chan_rend_context *c
659 stmfd sp!, {r4-r10,lr}
670 ldmfd sp!, {r4-r10,pc}
674 .global upd_algo6 @ chan_rend_context *c
676 stmfd sp!, {r4-r10,lr}
687 ldmfd sp!, {r4-r10,pc}
691 .global upd_algo7 @ chan_rend_context *c
693 stmfd sp!, {r4-r10,lr}
704 ldmfd sp!, {r4-r10,pc}
708 .global upd_slot1 @ chan_rend_context *c
710 stmfd sp!, {r4-r10,lr}
722 ldmfd sp!, {r4-r10,pc}
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
733 stmfd sp!, {r4-r11,lr}
735 mov r4, r2, lsl #8 @ no more 24 bits here
740 orr r4, r4, r0 @ (length<<8)|algo
742 ldmia r0, {r8,r9} @ eg_timer, eg_timer_add
743 ldr r10, [lr, #0x54] @ op1_out
744 ldmia lr, {r6,r7} @ load volumes
754 @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
763 cmp r8, #EG_TIMER_OVERFLOW
766 ldmia r0, {r1,r5} @ eg_cnt, CH
768 sub r8, r8, #EG_TIMER_OVERFLOW
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
780 cmp r8, #EG_TIMER_OVERFLOW
781 subcs r5, r5, #SLOT_STRUCT_SIZE*3
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
803 ldr pc, [pc, r0, lsl #2]
877 add r11,r11, r1, lsl #2
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}