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)
38 @ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
39 @ writes output to routp, but only if vol_out changes
40 .macro update_eg_phase_slot slot
41 ldrb r2, [r5,#0x17] @ state
46 ldr r2, [r3, r2, lsl #2] @ pack
48 mov r0, r2, lsr #24 @ shift
53 bne 0f @ no volume change
57 add r3, r3, r3, lsl #1
59 and r3, r3, #7 @ eg_inc_val shift, may be 0
60 ldrb r2, [r5,#0x17] @ state
61 ldrh r0, [r5,#0x1a] @ volume, unsigned (0-1023)
68 mov r2, r2, lsr #1 @ eg_inc_val
74 ldr r2, [r5,#0x1c] @ sl (can be 16bit?)
76 cmp r0, r2 @ if ( volume >= (INT32) SLOT->sl )
77 strgeb r3, [r5,#0x17] @ state
81 subs r3, r3, #1 @ eg_inc_val_shift - 1
85 add r0, r0, r2, asr #4
86 cmp r0, #0 @ if (volume <= MIN_ATT_INDEX)
88 strleb r3, [r5,#0x17] @ state
94 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
95 cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
101 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
102 cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
105 strgeb r3, [r5,#0x17] @ state
108 ldrh r3, [r5,#0x18] @ tl
109 strh r0, [r5,#0x1a] @ volume
113 orr r6, r0, r6, lsl #16
114 .elseif \slot == SLOT2
118 orr r6, r0, r6, lsr #16
119 .elseif \slot == SLOT3
122 orr r7, r0, r7, lsl #16
123 .elseif \slot == SLOT4
127 orr r7, r0, r7, lsr #16
134 @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt, r3=scratch
136 mov r2, r2, lsr #LFO_SH
137 cmp r2, r1, lsr #LFO_SH
142 bic r12,r12, #0xff000000 @ lfo_ampm &= 0xff
143 orr r12,r12, r3, lsl #1+24
146 cmp r2, r1, lsr #LFO_SH+2
147 bicne r12,r12, #0xff0000
148 orrne r12,r12, r2, lsl #16
154 @ result goes to r1, trashes r2
155 .macro make_eg_out slot
157 tstne r12, #(1<<(\slot+8))
161 .elseif \slot == SLOT2
163 .elseif \slot == SLOT3
166 .elseif \slot == SLOT4
172 addne r1, r1, r12, lsr r2
177 @ \r=sin/result, r1=env, r3=ym_tl_tab
180 eorne \r, \r, #0xff @ if (sin & 0x100) sin = 0xff - (sin&0xff);
183 orr \r, \r, r1, lsl #7
185 ldrh \r, [r3, \r] @ 2ci if ne
190 @ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
191 @ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
200 ldr r0, [lr, #0x38] @ mem (signed)
202 add r0, r2, r0, lsr #1
214 add r0, r0, r2, lsr #16
215 lookup_tl r0 @ r0=output smp
223 ldr r2, [lr, #0x14] @ 1ci
225 add r2, r5, r2, lsr #16
226 lookup_tl r2 @ r2=mem
229 str r2, [lr, #0x38] @ mem
241 ldr r0, [lr, #0x38] @ mem (signed)
243 add r0, r2, r0, lsr #1
254 add r0, r0, r2, lsr #16
255 lookup_tl r0 @ r0=output smp
263 ldr r2, [lr, #0x14] @ 1ci
265 lookup_tl r2 @ r2=mem
268 add r2, r2, r10, asr #16
281 ldr r0, [lr, #0x38] @ mem (signed)
283 add r0, r2, r0, lsr #1
287 add r0, r0, r10, asr #16
296 add r0, r0, r2, lsr #16
297 lookup_tl r0 @ r0=output smp
306 mov r2, r2, lsr #16 @ 1ci
307 lookup_tl r2 @ r2=mem
310 str r2, [lr, #0x38] @ mem
319 ldr r2, [lr, #0x38] @ mem (for future)
322 ldr r0, [lr, #0x18] @ phase3
336 add r0, r0, r2, lsr #16
337 lookup_tl r0 @ r0=output smp
345 ldr r2, [lr, #0x14] @ phase2
347 add r2, r5, r2, lsr #16
348 lookup_tl r2 @ r2=mem
351 str r2, [lr, #0x38] @ mem
363 mov r0, r0, lsr #16 @ 1ci
374 add r0, r0, r2, lsr #16
375 lookup_tl r0 @ r0=output smp
384 add r2, r5, r2, lsr #16
386 add r0, r0, r2 @ add to smp
400 ldr r0, [lr, #0x38] @ mem (signed)
402 add r0, r2, r0, lsr #1
403 lookup_tl r0 @ r0=output smp
412 add r2, r5, r2, lsr #16
414 add r0, r0, r2 @ add to smp
422 add r2, r5, r2, lsr #16
424 add r0, r0, r2 @ add to smp
428 str r1, [lr, #0x38] @ mem
440 mov r0, r0, lsr #16 @ 1ci
441 lookup_tl r0 @ r0=output smp
449 mov r2, r2, lsr #16 @ 1ci
451 add r0, r0, r2 @ add to smp
459 add r2, r5, r2, lsr #16
461 add r0, r0, r2 @ add to smp
475 mov r0, r0, lsr #16 @ 1ci
476 lookup_tl r0 @ r0=output smp
479 add r0, r0, r10, asr #16
486 mov r2, r2, lsr #16 @ 1ci
488 add r0, r0, r2 @ add to smp
495 mov r2, r2, lsr #16 @ 1ci
497 add r0, r0, r2 @ add to smp
507 movcs r10, r10, lsl #16 @ ct->op1_out <<= 16; // op1_out0 = op1_out1; op1_out1 = 0;
509 ands r2, r12, #0xf000
511 movne r2, r2, lsr #12
512 addne r0, r10, r10, lsl #16
513 movne r0, r0, asr #16
516 ldr r2, [lr, #0x10] @ phase1
520 mov r10,r10,lsl #16 @ ct->op1_out <<= 16;
522 orr r10,r10, r0, lsr #16
529 .global update_eg_phase @ FM_SLOT *SLOT, UINT32 eg_cnt
534 ldrh r3, [r5,#0x18] @ tl
535 ldrh r6, [r5,#0x1a] @ volume
537 update_eg_phase_slot SLOT1
544 .global advance_lfo @ int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt
554 .global upd_algo0 @ chan_rend_context *c
556 stmfd sp!, {r4-r10,lr}
567 ldmfd sp!, {r4-r10,pc}
571 .global upd_algo1 @ chan_rend_context *c
573 stmfd sp!, {r4-r10,lr}
584 ldmfd sp!, {r4-r10,pc}
588 .global upd_algo2 @ chan_rend_context *c
590 stmfd sp!, {r4-r10,lr}
601 ldmfd sp!, {r4-r10,pc}
605 .global upd_algo3 @ chan_rend_context *c
607 stmfd sp!, {r4-r10,lr}
618 ldmfd sp!, {r4-r10,pc}
622 .global upd_algo4 @ chan_rend_context *c
624 stmfd sp!, {r4-r10,lr}
635 ldmfd sp!, {r4-r10,pc}
639 .global upd_algo5 @ chan_rend_context *c
641 stmfd sp!, {r4-r10,lr}
652 ldmfd sp!, {r4-r10,pc}
656 .global upd_algo6 @ chan_rend_context *c
658 stmfd sp!, {r4-r10,lr}
669 ldmfd sp!, {r4-r10,pc}
673 .global upd_algo7 @ chan_rend_context *c
675 stmfd sp!, {r4-r10,lr}
686 ldmfd sp!, {r4-r10,pc}
690 .global upd_slot1 @ chan_rend_context *c
692 stmfd sp!, {r4-r10,lr}
704 ldmfd sp!, {r4-r10,pc}
709 @ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
710 @ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|unused[4],was_update,algo[3], r5=tl_tab/slot,
711 @ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer
712 .global chan_render_loop @ chan_rend_context *ct, int *buffer, int length
715 stmfd sp!, {r4-r11,lr}
717 mov r4, r2, lsl #8 @ no more 24 bits here
722 orr r4, r4, r0 @ (length<<8)|algo
724 ldmia r0, {r8,r9} @ eg_timer, eg_timer_add
725 ldr r10, [lr, #0x54] @ op1_out
726 ldmia lr, {r6,r7} @ load volumes
741 @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
752 cmp r8, #EG_TIMER_OVERFLOW
755 ldmia r0, {r1,r5} @ eg_cnt, CH
757 sub r8, r8, #EG_TIMER_OVERFLOW
760 @ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
761 update_eg_phase_slot SLOT1
762 add r5, r5, #SLOT_STRUCT_SIZE*2 @ SLOT2 (2)
763 update_eg_phase_slot SLOT2
764 sub r5, r5, #SLOT_STRUCT_SIZE @ SLOT3 (1)
765 update_eg_phase_slot SLOT3
766 add r5, r5, #SLOT_STRUCT_SIZE*2 @ SLOT4 (3)
767 update_eg_phase_slot SLOT4
769 cmp r8, #EG_TIMER_OVERFLOW
770 subcs r5, r5, #SLOT_STRUCT_SIZE*3
786 @ lr=context, r12=pack (stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
787 @ r0-r2=scratch, r3=tl_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
792 ldr pc, [pc, r0, lsl #2]
847 orr r4, r4, #8 @ have_output
866 add r11,r11, r1, lsl #2
898 @ stmia lr, {r6,r7} @ save volumes (for debug)
899 str r8, [lr, #0x44] @ eg_timer
900 str r12, [lr, #0x4c] @ pack (for lfo_ampm)
901 str r4, [lr, #0x50] @ was_update
902 str r10, [lr, #0x54] @ op1_out
903 ldmfd sp!, {r4-r11,pc}
907 @ vim:filetype=armasm