--- np2/win9x/x86/opngeng.x86 2003/10/18 07:28:50 1.1 +++ np2/win9x/x86/opngeng.x86 2011/02/04 14:43:55 1.8 @@ -1,4 +1,33 @@ +FMDIV_BITS equ 8 +FMDIV_ENT equ (1 << FMDIV_BITS) +FMVOL_SFTBIT equ 4 + +SIN_BITS equ 11 +EVC_BITS equ 10 +ENV_BITS equ 16 +KF_BITS equ 6 +FREQ_BITS equ 21 +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 + + struc slot_t .detune1 resd 1 ; 00 .totallevel resd 1 ; 04 @@ -21,14 +50,14 @@ .env_inc_decay1 resd 1 ; 3c .env_inc_decay2 resd 1 ; 40 .env_inc_rel resd 1 ; 44 -.size endstruc struc ch_t -.slot resb (slot_t.size * 4) +.slot resb (slot_t_size * 4) .algorithm resb 1 .feedback resb 1 - resb 2 +.playing resb 1 +.outslot resb 1 .op1fb resd 1 .connect1 resd 1 .connect3 resd 1 @@ -42,11 +71,11 @@ .extop resb 1 .stereo resb 1 resb 1 -.size endstruc struc opngen_t .playchannels resd 1 +.playing resd 1 .feedback2 resd 1 .feedback3 resd 1 .feedback4 resd 1 @@ -61,38 +90,16 @@ .calc1024 resd 1 .fmvol resd 1 .ratebit resd 1 +.vr_en resd 1 +.vr_l resd 1 +.vr_r resd 1 + +.sintable resd SIN_ENT +.envtable resd EVC_ENT +.envcurve resd (EVC_ENT*2 + 1) endstruc -FMDIV_BITS equ 8 -FMDIV_ENT equ (1 << FMDIV_BITS) -FMVOL_SFTBIT equ 4 - -SIN_BITS equ 11 -EVC_BITS equ 10 -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 - - section .text extern _opngen @@ -100,22 +107,24 @@ section .text extern _opncfg extern _sinshift - extern _sintable extern _envshift - extern _envtable - extern _env_curve + +ENVCURVE equ (_opncfg + opncfg_t.envcurve) +SINTABLE equ (_opncfg + opncfg_t.sintable) +ENVTABLE equ (_opncfg + opncfg_t.envtable) global @opngen_getpcm@12 + global @opngen_getpcmvr@12 %macro op_out 0 add eax, [edi + slot_t.freq_cnt] shr eax, (FREQ_BITS - SIN_BITS) and eax, (SIN_ENT - 1) mov cl, [_sinshift + eax] - mov eax, [_sintable + eax*4] + mov eax, [SINTABLE + eax*4] add cl, [_envshift + edx] - imul eax, [_envtable + edx*4] + imul eax, [ENVTABLE + edx*4] sar eax, cl %endmacro @@ -129,10 +138,10 @@ section .text %2: mov [edi + slot_t.env_cnt], eax shr eax, ENV_BITS mov edx, [edi + slot_t.totallevel] - sub edx, [_env_curve + eax*4] + sub edx, [ENVCURVE + eax*4] %endmacro -%macro setenv 2 +%macro setenv 3 %1: mov dl, [edi + slot_t.env_mode] dec dl je short %%setrr @@ -158,6 +167,7 @@ section .text %%setrr: mov byte [edi + slot_t.env_mode], EM_OFF %%setd2: mov dword [edi + slot_t.env_end], EC_OFF + 1 and dword [edi + slot_t.env_inc], byte 0 + and byte [esi + ch_t.playing], ~(%3) mov eax, EC_OFF jmp near %2 %endmacro @@ -167,6 +177,8 @@ section .text @opngen_getpcm@12: cmp dword [esp+4], byte 0 je near og_noupdate + cmp dword [_opngen + opngen_t.playing], byte 0 + je near og_noupdate push ebx push esi @@ -187,18 +199,20 @@ og_fmout_st: mov eax, ebx sub ebx, eax imul eax, [_opngen + opngen_t.outdr] mov [esp + OPN_SAMPR], eax -og_fmout_lp: xor eax, eax - mov [_opngen + opngen_t.calcremain], ebx - mov [_opngen + opngen_t.outdl], eax - mov [_opngen + opngen_t.outdc], eax - mov [_opngen + opngen_t.outdr], eax +og_fmout_lp: mov [_opngen + opngen_t.calcremain], ebx + and dword [_opngen + opngen_t.playing], byte 0 + and dword [_opngen + opngen_t.outdl], byte 0 + and dword [_opngen + opngen_t.outdc], byte 0 + and dword [_opngen + opngen_t.outdr], byte 0 mov ch, [_opngen + opngen_t.playchannels] - mov edi, _opnch -og_calcch_lp: xor eax, eax - mov [_opngen + opngen_t.feedback2], eax - mov [_opngen + opngen_t.feedback3], eax - mov [_opngen + opngen_t.feedback4], eax - mov esi, edi + mov esi, _opnch +og_calcch_lp: mov cl, [esi + ch_t.outslot] + test cl, [esi + ch_t.playing] + je near og_calcch_nt + and dword [_opngen + opngen_t.feedback2], byte 0 + and dword [_opngen + opngen_t.feedback3], byte 0 + and dword [_opngen + opngen_t.feedback4], byte 0 + mov edi, esi calcenv envcalc1, envret1 ; slot1 calculate jl near og_calcslot3 mov cl, [esi + ch_t.feedback] @@ -222,28 +236,29 @@ og_algchk: cmp byte [esi + ch_t.algori jmp short og_calcslot3 og_calcalg5: mov ebx, [esi + ch_t.connect1] ; case ALG != 5 add [ebx], eax -og_calcslot3: add edi, byte slot_t.size ; slot3 calculate +og_calcslot3: add edi, byte slot_t_size ; slot3 calculate calcenv envcalc2, envret2 jl short og_calcslot2 mov eax, [_opngen + opngen_t.feedback2] op_out mov ebx, [esi + ch_t.connect2] add [ebx], eax -og_calcslot2: add edi, byte slot_t.size ; slot2 calculate +og_calcslot2: add edi, byte slot_t_size ; slot2 calculate calcenv envcalc3, envret3 jl short og_calcslot4 mov eax, [_opngen + opngen_t.feedback3] op_out mov ebx, [esi + ch_t.connect3] add [ebx], eax -og_calcslot4: add edi, byte slot_t.size ; slot4 calculate +og_calcslot4: add edi, byte slot_t_size ; slot4 calculate calcenv envcalc4, envret4 jl short og_calcsloted mov eax, [_opngen + opngen_t.feedback4] op_out mov ebx, [esi + ch_t.connect4] add [ebx], eax -og_calcsloted: add edi, byte (ch_t.size - (slot_t.size * 3)) +og_calcsloted: inc dword [_opngen + opngen_t.playing] +og_calcch_nt: add esi, ch_t_size dec ch jne near og_calcch_lp mov eax, [_opngen + opngen_t.outdc] @@ -269,12 +284,12 @@ og_nextsamp: neg ebx imul eax, [_opngen + opngen_t.outdl] add eax, [esp + OPN_SAMPL] imul dword [_opncfg + opncfg_t.fmvol] - mov [ebp], edx + add [ebp], edx mov eax, [_opngen + opngen_t.outdr] imul ecx add eax, [esp + OPN_SAMPR] imul dword [_opncfg + opncfg_t.fmvol] - mov [ebp+4], edx + add [ebp+4], edx add ebp, byte 8 dec dword [esp + OPN_LENG] jne near og_fmout_st @@ -285,10 +300,152 @@ og_nextsamp: neg ebx pop ebx og_noupdate: ret 4 - setenv envcalc1, envret1 - setenv envcalc2, envret2 - setenv envcalc3, envret3 - setenv envcalc4, envret4 + setenv envcalc1, envret1, 1 + setenv envcalc2, envret2, 2 + setenv envcalc3, envret3, 4 + setenv envcalc4, envret4, 8 + + + align 16 +@opngen_getpcmvr@12: + cmp dword [_opncfg + opncfg_t.vr_en], byte 0 + je near @opngen_getpcm@12 + + cmp dword [esp+4], byte 0 + je near ogv_noupdate + + push ebx + push esi + push edi + push ebp + sub esp, byte 8 + +OPNV_SAMPL equ 0 +OPNV_SAMPR equ 4 +OPNV_LENG equ 16 + 8 + 4 + + mov ebp, edx + mov ebx, [_opngen + opngen_t.calcremain] +ogv_fmout_st: mov eax, ebx + imul ebx, [_opngen + opngen_t.outdl] + mov [esp + OPNV_SAMPL], ebx + mov ebx, FMDIV_ENT + sub ebx, eax + imul eax, [_opngen + opngen_t.outdr] + mov [esp + OPNV_SAMPR], eax +ogv_fmout_lp: xor eax, eax + mov [_opngen + opngen_t.calcremain], ebx + mov [_opngen + opngen_t.outdl], eax + mov [_opngen + opngen_t.outdc], eax + mov [_opngen + opngen_t.outdr], eax + mov ch, [_opngen + opngen_t.playchannels] + mov edi, _opnch +ogv_calcch_lp: xor eax, eax + mov [_opngen + opngen_t.feedback2], eax + mov [_opngen + opngen_t.feedback3], eax + mov [_opngen + opngen_t.feedback4], eax + mov esi, edi + calcenv vrenvcalc1, vrenvret1 ; slot1 calculate + jl near ogv_calcslot3 + mov cl, [esi + ch_t.feedback] + test cl, cl + je short ogv_nofeed + mov eax, [esi + ch_t.op1fb] ; with feedback + mov ebx, eax + shr eax, cl + op_out + mov [esi + ch_t.op1fb], eax + add eax, ebx + sar eax, 1 + jmp short ogv_algchk +ogv_nofeed: xor eax, eax ; without feedback + op_out +ogv_algchk: cmp byte [esi + ch_t.algorithm], 5 + jne short ogv_calcalg5 + mov [_opngen + opngen_t.feedback2], eax ; case ALG == 5 + mov [_opngen + opngen_t.feedback3], eax + mov [_opngen + opngen_t.feedback4], eax + jmp short ogv_calcslot3 +ogv_calcalg5: mov ebx, [esi + ch_t.connect1] ; case ALG != 5 + add [ebx], eax +ogv_calcslot3: add edi, byte slot_t_size ; slot3 calculate + calcenv vrenvcalc2, vrenvret2 + jl short ogv_calcslot2 + mov eax, [_opngen + opngen_t.feedback2] + op_out + mov ebx, [esi + ch_t.connect2] + add [ebx], eax +ogv_calcslot2: add edi, byte slot_t_size ; slot2 calculate + calcenv vrenvcalc3, vrenvret3 + jl short ogv_calcslot4 + mov eax, [_opngen + opngen_t.feedback3] + op_out + mov ebx, [esi + ch_t.connect3] + add [ebx], eax +ogv_calcslot4: add edi, byte slot_t_size ; slot4 calculate + calcenv vrenvcalc4, vrenvret4 + jl short ogv_calcsloted + mov eax, [_opngen + opngen_t.feedback4] + op_out + mov ebx, [esi + ch_t.connect4] + add [ebx], eax +ogv_calcsloted: add edi, byte (ch_t_size - (slot_t_size * 3)) + dec ch + jne near ogv_calcch_lp + mov eax, [_opngen + opngen_t.outdl] + mov edx, [_opngen + opngen_t.outdc] + imul eax, [_opncfg + opncfg_t.vr_l] + mov ebx, edx + sar eax, 5 + add ebx, eax + sar eax, 2 + add edx, eax + mov eax, [_opngen + opngen_t.outdr] + imul eax, [_opncfg + opncfg_t.vr_r] + sar eax, 5 + add edx, eax + sar eax, 2 + add ebx, eax + add [_opngen + opngen_t.outdl], edx + add [_opngen + opngen_t.outdr], ebx + sar dword [_opngen + opngen_t.outdl], FMVOL_SFTBIT + sar dword [_opngen + opngen_t.outdr], FMVOL_SFTBIT + mov edx, [_opncfg + opncfg_t.calc1024] + mov ebx, [_opngen + opngen_t.calcremain] + mov eax, ebx + sub ebx, edx + jbe short ogv_nextsamp + mov [_opngen + opngen_t.calcremain], ebx + mov eax, edx + imul eax, [_opngen + opngen_t.outdl] + add [esp + OPNV_SAMPL], eax + imul edx, [_opngen + opngen_t.outdr] + add [esp + OPNV_SAMPR], edx + jmp near ogv_fmout_lp +ogv_nextsamp: neg ebx + mov [_opngen + opngen_t.calcremain], ebx + mov ecx, eax + imul eax, [_opngen + opngen_t.outdl] + add eax, [esp + OPNV_SAMPL] + imul dword [_opncfg + opncfg_t.fmvol] + add [ebp], edx + mov eax, [_opngen + opngen_t.outdr] + imul ecx + add eax, [esp + OPNV_SAMPR] + imul dword [_opncfg + opncfg_t.fmvol] + add [ebp+4], edx + add ebp, byte 8 + dec dword [esp + OPNV_LENG] + jne near ogv_fmout_st + add esp, byte 8 + pop ebp + pop edi + pop esi + pop ebx +ogv_noupdate: ret 4 - ends + setenv vrenvcalc1, vrenvret1, 1 + setenv vrenvcalc2, vrenvret2, 2 + setenv vrenvcalc3, vrenvret3, 4 + setenv vrenvcalc4, vrenvret4, 8