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
RetroPC.NET-CVS <cvs@retropc.net>