5 * This work is licensed under the terms of MAME license.
6 * See COPYING file in the top-level directory.
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.
19 .equiv SLOT_STRUCT_SIZE, 0x30
21 .equiv TL_TAB_LEN, 0x1A00
29 .equiv EG_SH, 16 @ 16.16 fixed point (envelope generator timing)
30 .equiv EG_TIMER_OVERFLOW, (3*(1<<EG_SH)) @ envelope generator timer overflows every 3 samples (on real chip)
31 .equiv LFO_SH, 25 /* 7.25 fixed point (LFO calculations) */
33 .equiv ENV_QUIET, (2*13*256/8)/2
36 @ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
37 @ writes output to routp, but only if vol_out changes
38 .macro update_eg_phase_slot slot
39 ldrb r2, [r5,#0x17] @ state
49 ldr r2, [r5,#0x20] @ eg_pack_ar (1ci)
54 bne 5f @ do smth for tl problem (set on init?)
56 ldrh r0, [r5,#0x1a] @ volume, unsigned (0-1023)
58 add r3, r3, r3, lsl #1
60 and r3, r3, #7 @ shift for eg_inc calculation
63 add r0, r0, r2, asr #5
64 cmp r0, #0 @ if (volume <= MIN_ATT_INDEX)
66 strleb r3, [r5,#0x17] @ state
71 ldr r2, [r5,#0x24] @ eg_pack_d1r (1ci)
76 bne 5f @ do smth for tl problem (set on init?)
78 ldrh r0, [r5,#0x1a] @ volume
80 add r3, r3, r3, lsl #1
82 and r3, r3, #7 @ shift for eg_inc calculation
85 ldr r2, [r5,#0x1c] @ sl (can be 16bit?)
86 add r0, r0, r3, asr #1
87 cmp r0, r2 @ if ( volume >= (INT32) SLOT->sl )
89 strgeb r3, [r5,#0x17] @ state
93 ldr r2, [r5,#0x28] @ eg_pack_d2r (1ci)
98 bne 5f @ do smth for tl problem (set on init?)
100 ldrh r0, [r5,#0x1a] @ volume
102 add r3, r3, r3, lsl #1
104 and r3, r3, #7 @ shift for eg_inc calculation
107 add r0, r0, r3, asr #1
109 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
110 cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
115 ldr r2, [r5,#0x2c] @ eg_pack_rr (1ci)
120 bne 5f @ do smth for tl problem (set on init?)
122 ldrh r0, [r5,#0x1a] @ volume
124 add r3, r3, r3, lsl #1
126 and r3, r3, #7 @ shift for eg_inc calculation
129 add r0, r0, r3, asr #1
131 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
132 cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
135 strgeb r3, [r5,#0x17] @ state
138 ldrh r3, [r5,#0x18] @ tl
139 strh r0, [r5,#0x1a] @ volume
143 orr r6, r0, r6, lsl #16
144 .elseif \slot == SLOT2
148 orr r6, r0, r6, lsr #16
149 .elseif \slot == SLOT3
152 orr r7, r0, r7, lsl #16
153 .elseif \slot == SLOT4
157 orr r7, r0, r7, lsr #16
164 @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt, r3=scratch
166 mov r2, r2, lsr #LFO_SH
167 cmp r2, r1, lsr #LFO_SH
172 bic r12,r12, #0xff000000 @ lfo_ampm &= 0xff
173 orr r12,r12, r3, lsl #1+24
176 cmp r2, r1, lsr #LFO_SH+2
177 bicne r12,r12, #0xff0000
178 orrne r12,r12, r2, lsl #16
184 @ result goes to r1, trashes r2
185 .macro make_eg_out slot
187 tstne r12, #(1<<(\slot+8))
191 .elseif \slot == SLOT2
193 .elseif \slot == SLOT3
196 .elseif \slot == SLOT4
202 addne r1, r1, r12, lsr r2
208 eorne \r, \r, #0xff @ if (sin & 0x100) sin = 0xff - (sin&0xff);
211 orr \r, \r, r1, lsl #8
213 ldrh \r, [r3, \r] @ 2ci if ne
218 @ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
219 @ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
228 ldr r0, [lr, #0x38] @ mem (signed)
230 add r0, r2, r0, lsr #1
242 add r0, r0, r2, lsr #16
243 lookup_tl r0 @ r0=output smp
251 ldr r2, [lr, #0x14] @ 1ci
253 add r2, r5, r2, lsr #16
254 lookup_tl r2 @ r2=mem
257 str r2, [lr, #0x38] @ mem
269 ldr r0, [lr, #0x38] @ mem (signed)
271 add r0, r2, r0, lsr #1
282 add r0, r0, r2, lsr #16
283 lookup_tl r0 @ r0=output smp
291 ldr r2, [lr, #0x14] @ 1ci
293 lookup_tl r2 @ r2=mem
296 add r2, r2, r10, asr #16
309 ldr r0, [lr, #0x38] @ mem (signed)
311 add r0, r2, r0, lsr #1
315 add r0, r0, r10, asr #16
324 add r0, r0, r2, lsr #16
325 lookup_tl r0 @ r0=output smp
334 mov r2, r2, lsr #16 @ 1ci
335 lookup_tl r2 @ r2=mem
338 str r2, [lr, #0x38] @ mem
347 ldr r2, [lr, #0x38] @ mem (for future)
350 ldr r0, [lr, #0x18] @ 1ci
364 add r0, r0, r2, lsr #16
365 lookup_tl r0 @ r0=output smp
375 add r2, r5, r2, lsr #16
376 lookup_tl r2 @ r2=mem
379 str r2, [lr, #0x38] @ mem
391 mov r0, r0, lsr #16 @ 1ci
402 add r0, r0, r2, lsr #16
403 lookup_tl r0 @ r0=output smp
412 add r2, r5, r2, lsr #16
414 add r0, r0, r2 @ add to smp
428 ldr r0, [lr, #0x38] @ mem (signed)
430 add r0, r2, r0, lsr #1
431 lookup_tl r0 @ r0=output smp
440 add r2, r5, r2, lsr #16
442 add r0, r0, r2 @ add to smp
450 add r2, r5, r2, lsr #16
452 add r0, r0, r2 @ add to smp
456 str r1, [lr, #0x38] @ mem
468 mov r0, r0, lsr #16 @ 1ci
469 lookup_tl r0 @ r0=output smp
477 mov r2, r2, lsr #16 @ 1ci
479 add r0, r0, r2 @ add to smp
487 add r2, r5, r2, lsr #16
489 add r0, r0, r2 @ add to smp
503 mov r0, r0, lsr #16 @ 1ci
504 lookup_tl r0 @ r0=output smp
507 add r0, r0, r10, asr #16
514 mov r2, r2, lsr #16 @ 1ci
516 add r0, r0, r2 @ add to smp
523 mov r2, r2, lsr #16 @ 1ci
525 add r0, r0, r2 @ add to smp
535 movcs r10, r10, lsl #16 @ ct->op1_out <<= 16; // op1_out0 = op1_out1; op1_out1 = 0;
537 ands r2, r12, #0xf000
539 movne r2, r2, lsr #12
540 addne r0, r10, r10, lsl #16
541 movne r0, r0, asr #16
546 add r0, r0, r2, lsr #16
548 mov r10,r10,lsl #16 @ ct->op1_out <<= 16;
550 orr r10,r10, r0, lsr #16
557 .global update_eg_phase @ FM_SLOT *SLOT, UINT32 eg_cnt
562 ldrh r3, [r5,#0x18] @ tl
563 ldrh r6, [r5,#0x1a] @ volume
565 update_eg_phase_slot SLOT1
572 .global advance_lfo @ int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt
582 .global upd_algo0 @ chan_rend_context *c
584 stmfd sp!, {r4-r10,lr}
595 ldmfd sp!, {r4-r10,pc}
599 .global upd_algo1 @ chan_rend_context *c
601 stmfd sp!, {r4-r10,lr}
612 ldmfd sp!, {r4-r10,pc}
616 .global upd_algo2 @ chan_rend_context *c
618 stmfd sp!, {r4-r10,lr}
629 ldmfd sp!, {r4-r10,pc}
633 .global upd_algo3 @ chan_rend_context *c
635 stmfd sp!, {r4-r10,lr}
646 ldmfd sp!, {r4-r10,pc}
650 .global upd_algo4 @ chan_rend_context *c
652 stmfd sp!, {r4-r10,lr}
663 ldmfd sp!, {r4-r10,pc}
667 .global upd_algo5 @ chan_rend_context *c
669 stmfd sp!, {r4-r10,lr}
680 ldmfd sp!, {r4-r10,pc}
684 .global upd_algo6 @ chan_rend_context *c
686 stmfd sp!, {r4-r10,lr}
697 ldmfd sp!, {r4-r10,pc}
701 .global upd_algo7 @ chan_rend_context *c
703 stmfd sp!, {r4-r10,lr}
714 ldmfd sp!, {r4-r10,pc}
718 .global upd_slot1 @ chan_rend_context *c
720 stmfd sp!, {r4-r10,lr}
732 ldmfd sp!, {r4-r10,pc}
737 @ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
738 @ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|unused[4],was_update,algo[3], r5=tl_tab/slot,
739 @ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer
740 .global chan_render_loop @ chan_rend_context *ct, int *buffer, int length
743 stmfd sp!, {r4-r11,lr}
745 mov r4, r2, lsl #8 @ no more 24 bits here
750 orr r4, r4, r0 @ (length<<8)|algo
752 ldmia r0, {r8,r9} @ eg_timer, eg_timer_add
753 ldr r10, [lr, #0x54] @ op1_out
754 ldmia lr, {r6,r7} @ load volumes
764 @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
773 cmp r8, #EG_TIMER_OVERFLOW
776 ldmia r0, {r1,r5} @ eg_cnt, CH
778 sub r8, r8, #EG_TIMER_OVERFLOW
781 @ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
782 update_eg_phase_slot SLOT1
783 add r5, r5, #SLOT_STRUCT_SIZE*2 @ SLOT2 (2)
784 update_eg_phase_slot SLOT2
785 sub r5, r5, #SLOT_STRUCT_SIZE @ SLOT3 (1)
786 update_eg_phase_slot SLOT3
787 add r5, r5, #SLOT_STRUCT_SIZE*2 @ SLOT4 (3)
788 update_eg_phase_slot SLOT4
790 cmp r8, #EG_TIMER_OVERFLOW
791 subcs r5, r5, #SLOT_STRUCT_SIZE*3
807 @ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
808 @ r0-r2=scratch, r3=tl_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
813 ldr pc, [pc, r0, lsl #2]
869 orr r4, r4, #8 @ have_output
888 add r11,r11, r1, lsl #2
920 str r8, [lr, #0x44] @ eg_timer
921 str r12, [lr, #0x4c] @ pack (for lfo_ampm)
922 str r4, [lr, #0x50] @ was_update
923 str r10, [lr, #0x54] @ op1_out
924 ldmfd sp!, {r4-r11,pc}