FMDIV_BITS equ 9 FMDIV_ENT equ (1 << FMDIV_BITS) FMVOL_SFTBIT equ 5 SIN_BITS equ 8 EVC_BITS equ 7 ENV_BITS equ 16 KF_BITS equ 6 FREQ_BITS equ 20 ENVTBL_BIT equ 14 SINTBL_BIT equ 14 TL_BITS equ (FREQ_BITS + 2) OPM_OUTSB equ (TL_BITS + 2 - 16) SIN_ENT equ (1 << SIN_BITS) EVC_ENT equ (1 << EVC_BITS) EC_ATTACK equ 0 EC_DECAY equ (EVC_ENT << ENV_BITS) EC_OFF equ ((2 * EVC_ENT) << ENV_BITS) EM_ATTACK equ 4 EM_DECAY1 equ 3 EM_DECAY2 equ 2 EM_RELEASE equ 1 EM_OFF equ 0 ; s_detune1 equ 0 ; s_detune2 equ 4 S1_TOTALLEVEL equ 8 S1_DECAYLEVEL equ 12 ; s_attack equ 16 ; s_decay1 equ 20 ; s_decay2 equ 24 ; s_release equ 28 S1_FREQ_CNT equ 32 S1_FREQ_INC equ 36 ; s_keyscale equ 40 ; s_multiple equ 41 S1_ENV_MODE equ 42 ; s_envraito equ 43 S1_ENV_CNT equ 44 S1_ENV_END equ 48 S1_ENV_INC equ 52 ; s_env_inc_attack equ 56 S1_ENVINCDECAY1 equ 60 S1_ENVINCDECAY2 equ 64 ; s_env_inc_release equ 68 S_SIZE equ 72 ; c_algorithm equ (S_SIZE * 4 + 0) C_FEEDBACK equ (S_SIZE * 4 + 1) C_PLAYING equ (S_SIZE * 4 + 2) C_OUTSLOT equ (S_SIZE * 4 + 3) C_OP1FB equ (S_SIZE * 4 + 4) C_CONNECT1 equ (S_SIZE * 4 + 8) C_CONNECT3 equ (S_SIZE * 4 + 12) C_CONNECT2 equ (S_SIZE * 4 + 16) C_CONNECT4 equ (S_SIZE * 4 + 20) ; c_keynote equ (S_SIZE * 4 + 24) ; c_keyfunc equ (S_SIZE * 4 + 28) ; c_kcode equ (S_SIZE * 4 + 29) ; c_pan equ (S_SIZE * 4 + 30) ; c_padding1 equ (S_SIZE * 4 + 31) C_SIZE equ (S_SIZE * 4 + 32) G_PLAYING equ 0 ; G_mode equ 4 G_FEEDBACK2 equ 8 G_FEEDBACK3 equ 12 G_FEEDBACK4 equ 16 G_OUTDL equ 20 G_OUTDC equ 24 G_OUTDR equ 28 G_CALCREMAIN equ 32 ; G_keyreg equ 36 T_ORG equ 8 T_CALC1024 equ (0 - T_ORG) T_FMVOL equ (4 - T_ORG) T_sintable equ (8 - T_ORG) T_envtable equ (8 - T_ORG + SIN_ENT * 4) T_envcurve equ (8 - T_ORG + SIN_ENT * 4 + EVC_ENT * 4) IMPORT opmch IMPORT opmgen IMPORT opmcfg EXPORT opmgen_getpcm AREA .text, CODE, READONLY ; r0 Temporary Register ; r1 Offset ; r2 Counter ; r3 Temporary Register ; r4 Temporary Register ; r5 channel counter ; r6 OPMCH ; r7 OPMCH base ; r8 L ; r9 R ; r10 opmgen Fix ; r11 opmcfg Fix ; r12 Temporary Register MACRO $label SLTFREQ $o, $upd $label ldr r3, [r6, #($o + S1_ENV_INC)] ; calc env ldr r4, [r6, #($o + S1_ENV_CNT)] ldr r12, [r6, #($o + S1_ENV_END)] ; add r3, r3, r4 cmp r3, r12 bcs $upd MEND MACRO $label SLTOUT $o, $fd, $cn $label mov r4, r3 lsr #ENV_BITS subs r12, r4, #EVC_ENT addcc r12, r11, #T_envcurve ; r12 = opmtbl.envcurve ldr r0, [r6, #($o + S1_TOTALLEVEL)] ldrcc r12, [r12, r4 lsl #2] str r3, [r6, #($o + S1_ENV_CNT)] ldr r4, [r6, #($o + S1_FREQ_CNT)] ldr r3, [r6, #($o + S1_FREQ_INC)] ; freq subs r0, r0, r12 ldr r12, [r10, $fd] add r3, r3, r4 str r3, [r6, #($o + S1_FREQ_CNT)] bls $label.ed add r3, r3, r12 add r0, r11, r0 lsl #2 mov r3, r3 lsl #(32 - FREQ_BITS) add r12, r11, #T_sintable ; r12 = opmtbl.sintable mov r3, r3 lsr #(32 - SIN_BITS) ldr r4, [r6, $cn] ldr r0, [r0, #T_envtable] ldr r3, [r12, r3 lsl #2] ldr r12, [r4] mul r0, r3, r0 ; add r12, r12, r0 asr #(ENVTBL_BIT + SINTBL_BIT - TL_BITS) str r12, [r4] $label.ed MEND MACRO $label SLTUPD $r, $o, $m $label ldrb r3, [r6, #($o + S1_ENV_MODE)] ; ; sub r3, r3, #1 cmp r3, #EM_ATTACK addcc pc, pc, r3 lsl #2 b $label.off ; EM_OFF b $label.rel ; EM_RELEASE b $label.dc2 ; EM_DECAY2 b $label.dc1 ; EM_DECAY1 $label.att strb r3, [r6, #($o + S1_ENV_MODE)] ldr r0, [r6, #($o + S1_DECAYLEVEL)] ldr r4, [r6, #($o + S1_ENVINCDECAY1)] mov r3, #EC_DECAY str r0, [r6, #($o + S1_ENV_END)] str r4, [r6, #($o + S1_ENV_INC)] b $r $label.dc1 strb r3, [r6, #($o + S1_ENV_MODE)] mov r0, #EC_OFF ldr r4, [r6, #($o + S1_ENVINCDECAY2)] ldr r3, [r6, #($o + S1_DECAYLEVEL)] str r0, [r6, #($o + S1_ENV_END)] str r4, [r6, #($o + S1_ENV_INC)] b $r $label.rel strb r3, [r6, #($o + S1_ENV_MODE)] $label.dc2 add r3, r12, #1 ldrb r4, [r6, #C_PLAYING] mov r0, #0 str r3, [r6, #($o + S1_ENV_END)] str r0, [r6, #($o + S1_ENV_INC)] and r4, r4, $m strb r4, [r6, #C_PLAYING] $label.off mov r3, #EC_OFF b $r MEND opmgen_getpcm cmp r2, #0 moveq pc, lr ldr r12, dcd_opmgen ldr r3, [r12, #G_PLAYING] cmp r3, #0 moveq pc, lr stmdb sp!, {r4 - r11, lr} ldr r7, dcd_opmch mov r10, r12 ldr r11, dcd_opmcfg ldr lr, [r10, #G_CALCREMAIN] ldr r3, [r10, #G_OUTDL] ldr r4, [r10, #G_OUTDR] getpcm_lp rsb r0, lr, #0 mul r8, r0, r3 mul r9, r0, r4 add lr, lr, #FMDIV_ENT mksmp_lp mov r12, #0 mov r6, r7 str r12, [r10, #G_OUTDL] str r12, [r10, #G_OUTDC] str r12, [r10, #G_OUTDR] mov r5, #(0 - (8 << 24)) ; ldr r5, [r10, #G_PLAYCHANNELS] ; sub r5, r12, r5 lsl #24 slotcalc_lp ldrb r0, [r6, #C_PLAYING] ldrb r12, [r6, #C_OUTSLOT] tst r0, r12 beq slot5calc add r5, r5, #1 mov r12, #0 str r12, [r10, #G_FEEDBACK2] str r12, [r10, #G_FEEDBACK3] str r12, [r10, #G_FEEDBACK4] slot1calc SLTFREQ 0, slot1update s1calcenv mov r12, r3, lsr #ENV_BITS subs r4, r12, #EVC_ENT addcc r4, r11, #T_envcurve ; r4 = opmtbl.envcurve ldr r0, [r6, #S1_TOTALLEVEL] ldrcc r4, [r4, r12 lsl #2] str r3, [r6, #S1_ENV_CNT] ldr r12, [r6, #S1_FREQ_CNT] ldr r3, [r6, #S1_FREQ_INC] ; freq subs r0, r0, r4 ldrb r4, [r6, #C_FEEDBACK] add r3, r3, r12 str r3, [r6, #S1_FREQ_CNT] bls slot2calc ldr r12, [r6, #C_OP1FB] cmp r4, #0 addne r3, r3, r12 asr r4 ; back! add r4, r11, #T_sintable ; r1 = opmtbl.sintable mov r3, r3 lsl #(32 - FREQ_BITS) add r0, r11, r0 lsl #2 mov r3, r3 lsr #(32 - SIN_BITS) ldr r0, [r0, #T_envtable] ldr r3, [r4, r3 lsl #2] ldr r4, [r6, #C_CONNECT1] mul r0, r3, r0 mov r3, r0 asr #(ENVTBL_BIT + SINTBL_BIT - TL_BITS) strne r3, [r6, #C_OP1FB] addne r3, r3, r12 subne r3, r3, r3 asr #31 ; adjust.... movne r3, r3 asr #1 cmp r4, #0 ldrne r0, [r4] streq r3, [r10, #G_FEEDBACK2] streq r3, [r10, #G_FEEDBACK3] streq r3, [r10, #G_FEEDBACK4] addne r0, r0, r3 strne r0, [r4] slot2calc SLTFREQ (S_SIZE * 1), slot2update s2calcenv SLTOUT (S_SIZE * 1), #G_FEEDBACK2, #C_CONNECT2 slot3calc SLTFREQ (S_SIZE * 2), slot3update s3calcenv SLTOUT (S_SIZE * 2), #G_FEEDBACK3, #C_CONNECT3 slot4calc SLTFREQ (S_SIZE * 3), slot4update s4calcenv SLTOUT (S_SIZE * 3), #G_FEEDBACK4, #C_CONNECT4 slot5calc add r6, r6, #C_SIZE adds r5, r5, #(1 << 24) bcc slotcalc_lp ldr r0, [r10, #G_OUTDC] ldr r3, [r10, #G_OUTDL] ldr r4, [r10, #G_OUTDR] ldr r12, [r11, #T_CALC1024] add r3, r3, r0 add r4, r4, r0 mov r3, r3, asr #FMVOL_SFTBIT mov r4, r4, asr #FMVOL_SFTBIT subs lr, lr, r12 addle r12, lr, r12 mla r8, r12, r3, r8 mla r9, r12, r4, r9 bgt mksmp_lp ldr r0, [r11, #T_FMVOL] mov r8, r8 asr #FMDIV_BITS mov r9, r9 asr #FMDIV_BITS mul r8, r0, r8 ldr r12, [r1] mul r9, r0, r9 ldr r0, [r1, #4] add r12, r12, r8 asr #(OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) str r12, [r1], #4 add r0, r0, r9 asr #(OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) str r0, [r1], #4 subs r2, r2, #1 bne getpcm_lp str r3, [r10, #G_OUTDL] str r4, [r10, #G_OUTDR] str lr, [r10, #G_CALCREMAIN] strb r5, [r10, #G_PLAYING] ldmia sp!, {r4 - r11, pc} dcd_opmgen dcd opmgen dcd_opmch dcd opmch dcd_opmcfg dcd opmcfg + T_ORG slot1update SLTUPD s1calcenv, (S_SIZE * 0), #&fe slot2update SLTUPD s2calcenv, (S_SIZE * 1), #&fd slot3update SLTUPD s3calcenv, (S_SIZE * 2), #&fb slot4update SLTUPD s4calcenv, (S_SIZE * 3), #&f7 END