d21a6e85e7
git-svn-id: svn://kolibrios.org@1845 a494cfbc-eb01-0410-851d-a64ba20cac60
3374 lines
73 KiB
NASM
3374 lines
73 KiB
NASM
; CORE.ASM
|
|
; --------
|
|
; uFMOD public source code release. Provided as-is.
|
|
|
|
if VIBRATO_OR_TREMOLO
|
|
sin127 db 00h,0Ch,19h,25h,31h,3Ch,47h,51h,5Ah,62h,6Ah,70h,75h,7Ah,7Dh,7Eh
|
|
db 7Fh,7Eh,7Dh,7Ah,75h,70h,6Ah,62h,5Ah,51h,47h,3Ch,31h,25h,19h,0Ch
|
|
endif
|
|
if INSTRUMENTVIBRATO_ON
|
|
sin64 db 00h,02h,03h,05h,06h,08h,09h,0Bh,0Ch,0Eh,10h,11h,13h,14h,16h,17h
|
|
db 18h,1Ah,1Bh,1Dh,1Eh,20h,21h,22h,24h,25h,26h,27h,29h,2Ah,2Bh,2Ch
|
|
db 2Dh,2Eh,2Fh,30h,31h,32h,33h,34h,35h,36h,37h,38h,38h,39h,3Ah,3Bh
|
|
db 3Bh,3Ch,3Ch,3Dh,3Dh,3Eh,3Eh,3Eh,3Fh,3Fh,3Fh,40h,40h,40h,40h,40h
|
|
endif
|
|
if AMIGAPERIODS_ON
|
|
f0_0833 dd 8.3333336e-2
|
|
f13_375 dd 1.3375e1
|
|
endif
|
|
f0_0013 dd 1.302083375e-3
|
|
f8363_0 dd 8.3630004275e3
|
|
|
|
; Mixer ramping
|
|
Ramp:
|
|
; [arg0] - ptr. to end of buffer
|
|
; ESI - _mod+36
|
|
; EDI - length
|
|
; EDX - buffer
|
|
; LOOP THROUGH CHANNELS
|
|
mov ecx,[esi+FMUSIC_MODULE.Channels-36]
|
|
push ebx
|
|
push ebp
|
|
loop_ch:
|
|
push esi
|
|
mov esi,[ecx+FSOUND_CHANNEL.fsptr] ; load the correct SAMPLE pointer for this channel
|
|
test esi,esi ; if(!fsptr) skip this channel!
|
|
jz MixExit_1
|
|
push edx ; mix buffer
|
|
push edx ; cur. mix buffer pointer
|
|
mov ebx,[ecx+FSOUND_CHANNEL.mixpos]
|
|
; Set up a mix counter. See what will happen first, will the output buffer
|
|
; end be reached first? or will the end of the sample be reached first? whatever
|
|
; is smallest will be the mixcount.
|
|
push edi
|
|
CalculateLoopCount:
|
|
cmp BYTE PTR [ecx+FSOUND_CHANNEL.speeddir],0
|
|
mov edx,[esi+FSOUND_SAMPLE.loopstart]
|
|
mov eax,[ecx+FSOUND_CHANNEL.mixposlo]
|
|
jne samplesleftbackwards
|
|
; work out how many samples left from mixpos to loop end
|
|
add edx,[esi+FSOUND_SAMPLE.looplen]
|
|
sub edx,ebx
|
|
ja submixpos
|
|
mov edx,[esi+FSOUND_SAMPLE._length]
|
|
sub edx,ebx
|
|
submixpos:
|
|
; edx : samples left (loopstart+looplen-mixpos)
|
|
neg edx
|
|
neg eax
|
|
adc edx,ebx
|
|
samplesleftbackwards:
|
|
; work out how many samples left from mixpos to loop start
|
|
neg edx
|
|
add edx,ebx
|
|
js MixExit
|
|
; edx:eax now contains number of samples left to mix
|
|
mov ebp,[ecx+FSOUND_CHANNEL.speedlo]
|
|
shrd eax,edx,5
|
|
mov ebx,[ecx+FSOUND_CHANNEL.speedhi]
|
|
shr edx,5
|
|
shrd ebp,ebx,5
|
|
jnz speedok ; divide by 0 check
|
|
mov ebp,FREQ_40HZ_p
|
|
mov DWORD PTR [ecx+FSOUND_CHANNEL.speedlo],FREQ_40HZ_f
|
|
speedok:
|
|
div ebp
|
|
xor ebp,ebp
|
|
neg edx
|
|
adc eax,ebp
|
|
jz DoOutputbuffEnd
|
|
mov ebx,OFFSET uFMOD_fopen
|
|
cmp eax,edi
|
|
; set a flag to say mix will end when end of output buffer is reached
|
|
seta [ebx-22] ; mix_endflag
|
|
jae staywithoutputbuffend
|
|
xchg eax,edi
|
|
staywithoutputbuffend:
|
|
if RAMP_NONE
|
|
else
|
|
movzx eax,WORD PTR [ecx+FSOUND_CHANNEL.ramp_count]
|
|
; VOLUME RAMP SETUP
|
|
; Reasons to ramp
|
|
; 1 volume change
|
|
; 2 sample starts (just treat as volume change - 0 to volume)
|
|
; 3 sample ends (ramp last n number of samples from volume to 0)
|
|
; now if the volume has changed, make end condition equal a volume ramp
|
|
test eax,eax
|
|
endif
|
|
mov edx,[ecx+FSOUND_CHANNEL.leftvolume]
|
|
mov ebp,[ecx+FSOUND_CHANNEL.rightvolume]
|
|
if RAMP_NONE
|
|
mov [ecx+FSOUND_CHANNEL.ramp_leftvolume],ebp
|
|
mov [ecx+FSOUND_CHANNEL.ramp_rightvolume],edx
|
|
else
|
|
mov [ebx-16],edi ; mmf+4 <- remember mix count before modifying it
|
|
jz volumerampstart
|
|
; if it tries to continue an old ramp, but the target has changed,
|
|
; set up a new ramp
|
|
cmp dx,[ecx+FSOUND_CHANNEL.ramp_lefttarget]
|
|
jne volumerampstart
|
|
cmp bp,[ecx+FSOUND_CHANNEL.ramp_righttarget]
|
|
je volumerampclamp ; restore old ramp
|
|
volumerampstart:
|
|
; SETUP NEW RAMP
|
|
mov [ecx+FSOUND_CHANNEL.ramp_lefttarget],dx
|
|
shl edx,volumeramps_pow
|
|
sub edx,[ecx+FSOUND_CHANNEL.ramp_leftvolume]
|
|
xor eax,eax
|
|
sar edx,volumeramps_pow
|
|
mov DWORD PTR [ecx+FSOUND_CHANNEL.ramp_leftspeed],edx
|
|
jz novolumerampL
|
|
mov al,volumerampsteps
|
|
novolumerampL:
|
|
mov [ecx+FSOUND_CHANNEL.ramp_righttarget],bp
|
|
shl ebp,volumeramps_pow
|
|
sub ebp,[ecx+FSOUND_CHANNEL.ramp_rightvolume]
|
|
sar ebp,volumeramps_pow
|
|
mov DWORD PTR [ecx+FSOUND_CHANNEL.ramp_rightspeed],ebp
|
|
jz novolumerampR
|
|
mov al,volumerampsteps
|
|
novolumerampR:
|
|
test eax,eax
|
|
mov [ecx+FSOUND_CHANNEL.ramp_count],ax
|
|
jz volumerampend
|
|
volumerampclamp:
|
|
cmp edi,eax
|
|
jbe volumerampend ; dont clamp mixcount
|
|
mov edi,eax
|
|
volumerampend:
|
|
mov eax,[ecx+FSOUND_CHANNEL.ramp_leftspeed]
|
|
mov [ebx],eax ; ramp_leftspeed
|
|
mov eax,[ecx+FSOUND_CHANNEL.ramp_rightspeed]
|
|
mov [ebx+4],eax ; ramp_rightspeed
|
|
endif
|
|
mov [ebx-20],edi ; mmf
|
|
; SET UP ALL OF THE REGISTERS HERE FOR THE INNER LOOP
|
|
; edx : speed
|
|
; ebx : mixpos
|
|
; ebp : speed low
|
|
; esi : destination pointer
|
|
; edi : counter
|
|
mov ebx,[ecx+FSOUND_CHANNEL.mixpos]
|
|
lea ebx,[ebx*2+esi+FSOUND_SAMPLE.buff]
|
|
push esi
|
|
cmp BYTE PTR [ecx+FSOUND_CHANNEL.speeddir],0
|
|
mov esi,[esp+8] ; <- cur. mix buffer
|
|
mov edx,[ecx+FSOUND_CHANNEL.speedhi]
|
|
mov ebp,[ecx+FSOUND_CHANNEL.speedlo]
|
|
je MixLoop16
|
|
; neg edx:ebp
|
|
neg ebp
|
|
not edx
|
|
sbb edx,-1
|
|
align 4
|
|
MixLoop16:
|
|
push edi
|
|
push edx
|
|
movsx edi,WORD PTR [ebx]
|
|
movsx eax,WORD PTR [ebx+2]
|
|
mov edx,[ecx+FSOUND_CHANNEL.mixposlo]
|
|
sub eax,edi
|
|
shr edx,1 ; force unsigned
|
|
imul edx
|
|
shl edi,volumeramps_pow-1
|
|
shld edx,eax,volumeramps_pow
|
|
add edx,edi
|
|
if RAMP_NONE
|
|
mov eax,edx
|
|
imul edx,[ecx+FSOUND_CHANNEL.ramp_rightvolume]
|
|
add [esi],edx
|
|
imul DWORD PTR [ecx+FSOUND_CHANNEL.ramp_leftvolume]
|
|
add [esi+4],eax
|
|
else
|
|
xchg eax,edx
|
|
mov edi,eax
|
|
imul DWORD PTR [ecx+FSOUND_CHANNEL.ramp_rightvolume]
|
|
shrd eax,edx,volumeramps_pow-1
|
|
rol edx,1
|
|
and edx,1
|
|
add eax,edx
|
|
sar eax,1
|
|
add [esi],eax
|
|
xchg eax,edi
|
|
imul DWORD PTR [ecx+FSOUND_CHANNEL.ramp_leftvolume]
|
|
shrd eax,edx,volumeramps_pow-1
|
|
rol edx,1
|
|
and edx,1
|
|
add eax,edx
|
|
mov edi,[uFMOD_fread]
|
|
sar eax,1
|
|
add [esi+4],eax
|
|
mov edx,[uFMOD_fopen]
|
|
add [ecx+FSOUND_CHANNEL.ramp_rightvolume],edi ; + cur_ramp_rightspeed
|
|
add [ecx+FSOUND_CHANNEL.ramp_leftvolume],edx ; + cur_ramp_leftspeed
|
|
endif
|
|
pop edx
|
|
xor eax,eax
|
|
add [ecx+FSOUND_CHANNEL.mixposlo],ebp
|
|
pop edi
|
|
adc eax,edx
|
|
add esi,8
|
|
dec edi
|
|
lea ebx,[ebx+eax*2]
|
|
jnz MixLoop16
|
|
mov edi,[esp+20h] ; find out how many OUTPUT samples left to mix
|
|
mov [esp+8],esi ; update cur. mix buffer
|
|
sub edi,esi
|
|
shr edi,3 ; edi <- # of samples left
|
|
pop esi ; esi <- sample pointer
|
|
lea eax,[esi+FSOUND_SAMPLE.buff]
|
|
sub ebx,eax
|
|
shr ebx,1
|
|
mov [ecx+FSOUND_CHANNEL.mixpos],ebx
|
|
if RAMP_NONE
|
|
xor edx,edx
|
|
else
|
|
; DID A VOLUME RAMP JUST HAPPEN?
|
|
movzx edx,WORD PTR [ecx+FSOUND_CHANNEL.ramp_count]
|
|
test edx,edx
|
|
jz DoOutputbuffEnd
|
|
mov eax,[mmf]
|
|
cdq
|
|
sub [ecx+FSOUND_CHANNEL.ramp_count],ax
|
|
; if(!rampcount) a ramp has FINISHED, so finish the rest of the mix
|
|
jnz DoOutputbuffEnd
|
|
sub eax,[mmf+4]
|
|
; clear out the ramp speeds
|
|
mov [ecx+FSOUND_CHANNEL.ramp_leftspeed],edx
|
|
neg eax
|
|
mov [ecx+FSOUND_CHANNEL.ramp_rightspeed],edx
|
|
; is it 0 because ramp ended only? or both ended together?
|
|
; if sample ended together with ramp... problems... loop isn't handled
|
|
sbb edx,edx
|
|
; start again and continue rest of mix
|
|
test edi,edx
|
|
jnz CalculateLoopCount ; dont start again if nothing left
|
|
xor edx,edx
|
|
endif
|
|
DoOutputbuffEnd:
|
|
cmp [mix_endflag],dl
|
|
jne MixExit
|
|
movzx eax,BYTE PTR [esi+FSOUND_SAMPLE.loopmode]
|
|
; SWITCH ON LOOP MODE TYPE
|
|
dec eax ; check for normal loop (FSOUND_LOOP_NORMAL = 1)
|
|
jnz CheckBidiLoop
|
|
mov eax,[esi+FSOUND_SAMPLE.loopstart]
|
|
mov ebp,[esi+FSOUND_SAMPLE.looplen]
|
|
add eax,ebp
|
|
cmp ebx,eax
|
|
jbe rewind_ok
|
|
sub ebx,eax
|
|
xchg eax,ebx
|
|
div ebp
|
|
rewind_ok:
|
|
sub ebp,edx
|
|
sub ebx,ebp
|
|
jmp ChkLoop_OK
|
|
CheckBidiLoop:
|
|
dec eax ; FSOUND_LOOP_BIDI = 2
|
|
neg eax
|
|
adc edx,-1
|
|
and [ecx+FSOUND_CHANNEL.mixposlo],edx
|
|
and [ecx+FSOUND_CHANNEL.mixpos],edx
|
|
and [ecx+FSOUND_CHANNEL.fsptr],edx
|
|
jz MixExit
|
|
cmp [ecx+FSOUND_CHANNEL.speeddir],al ; FSOUND_MIXDIR_FORWARDS
|
|
je BidiForward
|
|
BidiBackwards:
|
|
mov eax,[esi+FSOUND_SAMPLE.loopstart]
|
|
neg ebp
|
|
dec eax
|
|
sub ebp,1
|
|
dec BYTE PTR [ecx+FSOUND_CHANNEL.speeddir] ; set FSOUND_MIXDIR_FORWARDS
|
|
sbb eax,ebx
|
|
mov ebx,[esi+FSOUND_SAMPLE.loopstart]
|
|
add ebx,eax
|
|
cmp eax,[esi+FSOUND_SAMPLE.looplen]
|
|
jl BidiFinish
|
|
BidiForward:
|
|
mov eax,[esi+FSOUND_SAMPLE.loopstart]
|
|
add eax,[esi+FSOUND_SAMPLE.looplen]
|
|
lea edx,[eax-1]
|
|
sbb eax,ebx
|
|
neg ebp
|
|
xchg eax,ebx
|
|
sub ebp,1
|
|
adc ebx,edx
|
|
inc BYTE PTR [ecx+FSOUND_CHANNEL.speeddir] ; go backwards
|
|
cmp ebx,[esi+FSOUND_SAMPLE.loopstart]
|
|
jl BidiBackwards
|
|
BidiFinish:
|
|
mov [ecx+FSOUND_CHANNEL.mixposlo],ebp
|
|
ChkLoop_OK:
|
|
test edi,edi
|
|
mov [ecx+FSOUND_CHANNEL.mixpos],ebx
|
|
jnz CalculateLoopCount
|
|
MixExit:
|
|
pop edi
|
|
pop eax ; discard cur. mix buffer pointer
|
|
pop edx
|
|
MixExit_1:
|
|
add ecx,FSOUND_CHANNEL_size
|
|
pop esi
|
|
cmp ecx,[esi+FMUSIC_MODULE.uFMOD_Ch-36]
|
|
jl loop_ch
|
|
pop ebp
|
|
pop ebx
|
|
ret
|
|
|
|
if AMIGAPERIODS_ON
|
|
AmigaPeriod:
|
|
; [sptr] in ECX
|
|
; note in EAX
|
|
; ESI != 0
|
|
mov edx,132
|
|
push edi
|
|
sub edx,eax
|
|
push esi
|
|
test eax,eax
|
|
push edx
|
|
movsx eax,BYTE PTR [ecx+FSOUND_SAMPLE.finetune]
|
|
mov edi,edx
|
|
jz _do_inc
|
|
cdq
|
|
shl edx,1
|
|
_do_inc:
|
|
inc edx
|
|
exp2:
|
|
fild DWORD PTR [esp]
|
|
fmul DWORD PTR [f0_0833] ; /12.0f
|
|
fld st0
|
|
frndint
|
|
fsub st1,st0
|
|
fxch st1
|
|
f2xm1
|
|
fld1
|
|
faddp st1,st0
|
|
fscale
|
|
fstp st1
|
|
fmul DWORD PTR [f13_375] ; *13.375f
|
|
fistp DWORD PTR [esp]
|
|
test esi,esi
|
|
pop ecx
|
|
jz exp2_end
|
|
sub edi,edx
|
|
push edi
|
|
xor esi,esi
|
|
mov edi,ecx
|
|
jmp exp2
|
|
exp2_end:
|
|
sub ecx,edi
|
|
test edx,edx
|
|
jns _do_imul
|
|
neg ecx
|
|
_do_imul:
|
|
imul ecx
|
|
and edx,127 ; +2^7-1
|
|
add eax,edx
|
|
sar eax,7
|
|
pop esi
|
|
add eax,edi
|
|
pop edi
|
|
ret
|
|
endif ; AMIGAPERIODS_ON
|
|
|
|
; DESCRIPTION: To carry out a vibrato at a certain depth and speed
|
|
if VIBRATO_OR_VOLSLIDE
|
|
if TREMOLO_ON
|
|
VibratoOrTremolo:
|
|
; cptr+2 = ESI
|
|
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2]
|
|
mov al,[esi+FMUSIC_CHANNEL.wavecontrol-2]
|
|
mov edx,ecx
|
|
add dl,[esi+FMUSIC_CHANNEL.vibspeed-2]
|
|
and edx,3Fh
|
|
and eax,3 ; switch(cptr->wavecontrol&3)
|
|
mov [esi+FMUSIC_CHANNEL.vibpos-2],dl
|
|
jz vibrato_c0
|
|
; C2 : Sqare wave
|
|
rol ecx,27
|
|
sbb edx,edx
|
|
xor edx,7Fh
|
|
or edx,1
|
|
dec eax
|
|
jnz vibrato_default
|
|
; C1 : Triangle wave (ramp down)
|
|
shr edx,24
|
|
ror ecx,23
|
|
add edx,ecx
|
|
neg edx
|
|
jmp vibrato_default
|
|
vibrato_c0:
|
|
; C0 : Sine wave
|
|
; delta = 127 sin(2 Pi x/64)
|
|
mov eax,ecx
|
|
and ecx,1Fh
|
|
shr eax,6
|
|
movzx edx,BYTE PTR [OFFSET sin127+ecx]
|
|
sbb eax,eax
|
|
xor edx,eax
|
|
sub edx,eax
|
|
vibrato_default:
|
|
movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.vibdepth-2]
|
|
imul edx ; delta *= cptr->vibdepth
|
|
sar eax,5
|
|
ret
|
|
endif
|
|
|
|
Vibrato:
|
|
; cptr+2 = ESI
|
|
if TREMOLO_ON
|
|
call VibratoOrTremolo
|
|
sar eax,1
|
|
else
|
|
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2]
|
|
mov al,[esi+FMUSIC_CHANNEL.wavecontrol-2]
|
|
mov edx,ecx
|
|
add dl,[esi+FMUSIC_CHANNEL.vibspeed-2]
|
|
and edx,3Fh
|
|
and eax,3 ; switch(cptr->wavecontrol&3)
|
|
mov [esi+FMUSIC_CHANNEL.vibpos-2],dl
|
|
jz vibrato_c0
|
|
; C2 : Sqare wave
|
|
rol ecx,27
|
|
sbb edx,edx
|
|
xor edx,7Fh
|
|
or edx,1
|
|
dec eax
|
|
jnz vibrato_default
|
|
; C1 : Triangle wave (ramp down)
|
|
shr edx,24
|
|
ror ecx,23
|
|
add edx,ecx
|
|
neg edx
|
|
jmp vibrato_default
|
|
vibrato_c0:
|
|
; C0 : Sine wave
|
|
; delta = 127 sin(2 Pi x/64)
|
|
mov eax,ecx
|
|
and ecx,1Fh
|
|
shr eax,6
|
|
movzx edx,BYTE PTR [OFFSET sin127+ecx]
|
|
sbb eax,eax
|
|
xor edx,eax
|
|
sub edx,eax
|
|
vibrato_default:
|
|
movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.vibdepth-2]
|
|
imul edx ; delta *= cptr->vibdepth
|
|
sar eax,6
|
|
endif
|
|
mov [esi+FMUSIC_CHANNEL.freqdelta-2],eax
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
|
|
ret
|
|
endif ; VIBRATO_OR_VOLSLIDE
|
|
|
|
if TREMOLO_ON
|
|
Tremolo:
|
|
; cptr+2 = ESI
|
|
if VIBRATO_OR_VOLSLIDE
|
|
push esi
|
|
add esi,FMUSIC_CHANNEL.tremolopos-FMUSIC_CHANNEL.vibpos
|
|
call VibratoOrTremolo
|
|
pop esi
|
|
else
|
|
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.tremolopos-2]
|
|
mov al,[esi+FMUSIC_CHANNEL.wavecontrol-2]
|
|
mov edx,ecx
|
|
add dl,[esi+FMUSIC_CHANNEL.tremolospeed-2]
|
|
and edx,3Fh
|
|
and eax,3 ; switch(cptr->wavecontrol&3)
|
|
mov [esi+FMUSIC_CHANNEL.tremolopos-2],dl
|
|
jz tremolo_c0
|
|
; C2 : Sqare wave
|
|
rol ecx,27
|
|
sbb edx,edx
|
|
xor edx,7Fh
|
|
or edx,1
|
|
dec eax
|
|
jnz tremolo_default
|
|
; C1 : Triangle wave (ramp down)
|
|
shr edx,24
|
|
ror ecx,23
|
|
add edx,ecx
|
|
neg edx
|
|
jmp tremolo_default
|
|
tremolo_c0:
|
|
; C0 : Sine wave
|
|
; delta = 127 sin(2 Pi x/64)
|
|
mov eax,ecx
|
|
and ecx,1Fh
|
|
shr eax,6
|
|
movzx edx,BYTE PTR [OFFSET sin127+ecx]
|
|
sbb eax,eax
|
|
xor edx,eax
|
|
sub edx,eax
|
|
tremolo_default:
|
|
movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.tremolodepth-2]
|
|
imul edx
|
|
sar eax,5
|
|
endif
|
|
mov [esi+FMUSIC_CHANNEL.voldelta-2],eax
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
ret
|
|
endif ; TREMOLO_ON
|
|
|
|
if PORTATO_OR_VOLSLIDE
|
|
Portamento:
|
|
; cptr+2 = ESI
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
|
|
mov eax,[esi+FMUSIC_CHANNEL.freq-2]
|
|
mov ecx,[esi+FMUSIC_CHANNEL.portatarget-2]
|
|
movzx edx,BYTE PTR [esi+FMUSIC_CHANNEL.portaspeed-2]
|
|
shl edx,2
|
|
sub eax,ecx
|
|
jg porta_do_sub
|
|
add eax,edx
|
|
jg _do_trim
|
|
jmp _no_trim
|
|
porta_do_sub:
|
|
sub eax,edx
|
|
jl _do_trim
|
|
_no_trim:
|
|
add ecx,eax
|
|
_do_trim:
|
|
mov [esi+FMUSIC_CHANNEL.freq-2],ecx
|
|
ret
|
|
endif ; PORTATO_OR_VOLSLIDE
|
|
|
|
if VOLUME_OR_PANENVELOPE
|
|
Envelope:
|
|
; cptr+2 = ESI
|
|
; env_iptr = ECX
|
|
; control = AL
|
|
env_type equ -4
|
|
envstopped equ -8
|
|
envdelta equ -12
|
|
env_value equ -16
|
|
valfrac equ -20
|
|
; env_tick = -24
|
|
sustain_l2 equ -26
|
|
sustain_l1 equ -27
|
|
sustain_loop equ -28
|
|
env_next equ -32
|
|
env_pos equ -36
|
|
push edi
|
|
push ebx
|
|
push ebp
|
|
mov ebp,esp
|
|
; Initialize local vars with PAN/VOL data
|
|
lea edi,[ecx+FMUSIC_INSTRUMENT.PANPoints]
|
|
xor ebx,ebx
|
|
if PANENVELOPE_ON
|
|
mov edx,DWORD PTR [edi+FMUSIC_INSTRUMENT.PANsustain-FMUSIC_INSTRUMENT.PANPoints]
|
|
mov [ebp+sustain_loop],edx ; load PANsustain, PANLoopStart and PANLoopEnd
|
|
mov cl,BYTE PTR [edi+FMUSIC_INSTRUMENT.PANtype-FMUSIC_INSTRUMENT.PANPoints]
|
|
movzx edx,BYTE PTR [edi+FMUSIC_INSTRUMENT.PANnumpoints-FMUSIC_INSTRUMENT.PANPoints]
|
|
endif
|
|
or [esi+FMUSIC_CHANNEL.notectrl-2],al ; cptr->notectrl |= control
|
|
if PANENVELOPE_ON
|
|
if VOLUMEENVELOPE_ON
|
|
cmp al,FMUSIC_VOLUME ; is it FMUSIC_VOLUME or FMUSIC_PAN?
|
|
endif
|
|
lea eax,[esi+FMUSIC_CHANNEL.envpanstopped-2]
|
|
endif
|
|
if VOLUMEENVELOPE_ON
|
|
if PANENVELOPE_ON
|
|
jnz pan_or_vol_ok
|
|
endif
|
|
; control = FMUSIC_VOLUME
|
|
add ebx,FMUSIC_CHANNEL.envvol-FMUSIC_CHANNEL.envpan
|
|
mov eax,DWORD PTR [edi+FMUSIC_INSTRUMENT.VOLsustain-FMUSIC_INSTRUMENT.PANPoints]
|
|
mov [ebp+sustain_loop],eax ; load VOLsustain, VOLLoopStart and VOLLoopEnd
|
|
mov cl,BYTE PTR [edi+FMUSIC_INSTRUMENT.VOLtype-FMUSIC_INSTRUMENT.PANPoints]
|
|
movzx edx,BYTE PTR [edi+FMUSIC_INSTRUMENT.VOLnumpoints-FMUSIC_INSTRUMENT.PANPoints]
|
|
lea eax,[esi+FMUSIC_CHANNEL.envvolstopped-2]
|
|
add edi,FMUSIC_INSTRUMENT.VOLPoints-FMUSIC_INSTRUMENT.PANPoints
|
|
pan_or_vol_ok:
|
|
endif
|
|
cmp BYTE PTR [eax],dh
|
|
jne goto_envelope_ret
|
|
push ecx ; -> env_type
|
|
push eax ; -> envstopped
|
|
lea ecx,[esi+ebx+FMUSIC_CHANNEL.envpanpos-2]
|
|
lea eax,[esi+ebx+FMUSIC_CHANNEL.envpandelta-2]
|
|
push eax ; -> envdelta
|
|
lea eax,[esi+ebx+FMUSIC_CHANNEL.envpan-2]
|
|
push eax ; -> env_value
|
|
lea eax,[esi+ebx+FMUSIC_CHANNEL.envpanfrac-2]
|
|
lea ebx,[esi+ebx+FMUSIC_CHANNEL.envpantick-2]
|
|
push eax ; -> valfrac
|
|
mov eax,[ecx]
|
|
cmp eax,edx ; if(*pos>=numpoints) envelop out of bound
|
|
push ebx ; -> env_tick
|
|
jge envelope_done
|
|
movzx eax,WORD PTR [edi+eax*4]
|
|
cmp [ebx],eax ; if(*tick == points[(*pos)<<1]) we are at the correct tick for the position
|
|
jnz add_envdelta
|
|
test BYTE PTR [ebp+env_type],FMUSIC_ENVELOPE_LOOP
|
|
jz loop_ok
|
|
movzx eax,BYTE PTR [ebp+sustain_l2]
|
|
cmp [ecx],eax
|
|
jnz loop_ok ; if((type&FMUSIC_ENVELOPE_LOOP) && *pos == loopend) handle loop
|
|
movzx eax,BYTE PTR [ebp+sustain_l1]
|
|
mov [ecx],eax ; *pos = loopstart
|
|
movzx eax,WORD PTR [edi+eax*4]
|
|
mov [ebx],eax ; *tick = points[(*pos)<<1]
|
|
loop_ok:
|
|
mov eax,[ecx]
|
|
mov [ebp+env_pos],eax
|
|
lea eax,[edi+eax*4]
|
|
dec edx
|
|
movzx ebx,WORD PTR [eax] ; get tick at this point
|
|
cmp [ecx],edx
|
|
mov edx,[eax+4]
|
|
mov edi,edx
|
|
movzx eax,WORD PTR [eax+2]
|
|
mov [ebp+env_next],edx ; get tick at next point
|
|
mov edx,[ebp+env_value]
|
|
mov [edx],eax ; *value = points[(currpos<<1)+1]
|
|
jne env_continue
|
|
; if it is at the last position, abort the envelope and continue last value
|
|
mov eax,[ebp+envstopped]
|
|
inc BYTE PTR [eax] ; *envstopped = TRUE
|
|
goto_envelope_ret:
|
|
jmp Envelope_Ret
|
|
env_continue:
|
|
shl eax,16
|
|
sub edi,eax
|
|
xchg eax,edi
|
|
xor ax,ax
|
|
; sustain
|
|
test BYTE PTR [ebp+env_type],FMUSIC_ENVELOPE_SUSTAIN
|
|
jz not_sustain
|
|
movzx edx,BYTE PTR [ebp+sustain_loop]
|
|
cmp [ebp+env_pos],edx
|
|
jne not_sustain
|
|
cmp BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2],al
|
|
je Envelope_Ret
|
|
not_sustain:
|
|
; interpolate 2 points to find delta step
|
|
inc DWORD PTR [ecx] ; (*pos)++
|
|
mov ecx,[ebp+valfrac]
|
|
mov [ecx],edi ; *valfrac = curr
|
|
mov edi,[ebp+envdelta]
|
|
movzx ecx,WORD PTR [ebp+env_next]
|
|
and DWORD PTR [edi],0 ; *envdelta = 0
|
|
sub ecx,ebx
|
|
jz envelope_done
|
|
cdq
|
|
idiv ecx
|
|
mov [edi],eax ; *envdelta = (next-curr)/(nexttick-currtick)
|
|
jmp envelope_done
|
|
add_envdelta:
|
|
; interpolate
|
|
mov eax,[ebp+envdelta]
|
|
mov ecx,[eax]
|
|
mov eax,[ebp+valfrac]
|
|
add [eax],ecx ; *valfrac += *envdelta
|
|
envelope_done:
|
|
pop edx ; <- env_tick
|
|
pop eax ; <- valfrac
|
|
pop ecx ; <- env_value
|
|
mov eax,[eax]
|
|
inc DWORD PTR [edx] ; (*tick)++
|
|
sar eax,16
|
|
mov [ecx],eax ; *value = *valfrac >> 16
|
|
Envelope_Ret:
|
|
leave
|
|
pop ebx
|
|
pop edi
|
|
ret
|
|
endif ; VOLUME_OR_PANENVELOPE
|
|
|
|
if VOLUMEBYTE_ON
|
|
VolByte:
|
|
; volume = EDX
|
|
; cptr+2 = ESI
|
|
sub edx,16
|
|
jb switch_volume
|
|
cmp edx,40h
|
|
ja switch_volume
|
|
; if(volume >= 0x10 && volume <= 0x50)
|
|
mov [esi+FMUSIC_CHANNEL.volume-2],edx
|
|
switch_volume:
|
|
mov eax,edx
|
|
and edx,0Fh
|
|
shr eax,4 ; switch(volume>>4)
|
|
sub eax,5
|
|
jz case_6
|
|
dec eax
|
|
jz case_7
|
|
dec eax
|
|
jz case_6
|
|
dec eax
|
|
jz case_7
|
|
sub eax,2
|
|
jbe case_AB
|
|
dec eax
|
|
jz case_C
|
|
dec eax
|
|
jz case_D
|
|
dec eax
|
|
jz case_E
|
|
dec eax
|
|
jnz vol_default
|
|
; case 0xF
|
|
test edx,edx
|
|
jz vol_z
|
|
shl dl,4
|
|
mov [esi+FMUSIC_CHANNEL.portaspeed-2],dl
|
|
vol_z:
|
|
and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER
|
|
if PORTATO_OR_VOLSLIDE
|
|
mov eax,[esi+FMUSIC_CHANNEL.period-2]
|
|
mov [esi+FMUSIC_CHANNEL.portatarget-2],eax ; cptr->portatarget = cptr->period
|
|
endif
|
|
vol_default:
|
|
ret
|
|
case_6: ; / case 8
|
|
neg edx
|
|
case_7: ; / case 9
|
|
add [esi+FMUSIC_CHANNEL.volume-2],edx
|
|
ret
|
|
case_AB:
|
|
mov [esi+eax+FMUSIC_CHANNEL.vibspeed-1],dl
|
|
ret
|
|
case_C:
|
|
shl edx,4
|
|
mov [esi+FMUSIC_CHANNEL.pan-2],edx
|
|
xchg eax,edx
|
|
case_D:
|
|
neg edx
|
|
case_E:
|
|
add [esi+FMUSIC_CHANNEL.pan-2],edx
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
|
|
ret
|
|
endif ; VOLUMEBYTE_ON
|
|
|
|
if TREMOR_ON
|
|
Tremor:
|
|
; cptr+2 = ESI
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
mov dx,WORD PTR [esi+FMUSIC_CHANNEL.tremorpos-2]
|
|
cmp dl,dh
|
|
jbe inc_pos
|
|
mov ecx,[esi+FMUSIC_CHANNEL.volume-2]
|
|
neg ecx
|
|
mov [esi+FMUSIC_CHANNEL.voldelta-2],ecx
|
|
inc_pos:
|
|
add dh,[esi+FMUSIC_CHANNEL.tremoroff-2]
|
|
cmp dl,dh
|
|
jbe Tremor_Ret
|
|
mov dl,-1
|
|
Tremor_Ret:
|
|
inc dl
|
|
mov [esi+FMUSIC_CHANNEL.tremorpos-2],dl
|
|
ret
|
|
endif ; TREMOR_ON
|
|
|
|
SetBPM:
|
|
; bpm = ECX
|
|
test ecx,ecx
|
|
mov eax,FSOUND_MixRate*5/2
|
|
jz SetBPM_Ret
|
|
cdq
|
|
div ecx
|
|
SetBPM_Ret:
|
|
mov DWORD PTR [_mod+FMUSIC_MODULE.mixer_samplespertick],eax
|
|
ret
|
|
|
|
; Loads an XM stream into memory. Returns non-zero on success.
|
|
LoadXM:
|
|
loadxm_count1 equ -4
|
|
loadxm_numpat equ -8
|
|
loadxm_fnumpat equ -12
|
|
loadxm_count2 equ -16
|
|
loadxm_skip equ -20
|
|
loadxm_s0loopmode equ -38
|
|
loadxm_s0bytes equ -42
|
|
loadxm_s0looplen equ -48
|
|
loadxm_s0loopstart equ -52
|
|
loadxm_sample_2 equ -56
|
|
loadxm_pat_size equ -63
|
|
loadxm_pat equ -68
|
|
loadxm_tmp29 equ -91
|
|
loadxm_tmp27 equ -93
|
|
loadxm_tmp equ -120
|
|
mov eax,OFFSET _mod
|
|
push ebp
|
|
mov esi,eax
|
|
mov ebp,esp
|
|
mov edx,FMUSIC_MODULE_size
|
|
; buf : EAX
|
|
; size : EDX
|
|
call [uFMOD_fread]
|
|
xor ecx,ecx
|
|
mov eax,[esi+FMUSIC_MODULE.mixer_samplespertick]
|
|
push ecx ; -> loadxm_count1
|
|
; GOTO PATTERN DATA
|
|
lea eax,[eax+60]
|
|
; pos : EAX
|
|
; org : ECX
|
|
; !org : Z
|
|
call uFMOD_lseek
|
|
add esp,-116
|
|
push ebx
|
|
; SAVE TRACK TITLE
|
|
if INFO_API_ON
|
|
push 20 ; a title has max. 20 chars
|
|
lea edx,[esi+17]
|
|
mov edi,OFFSET szTtl
|
|
if UCODE
|
|
xor eax,eax
|
|
endif
|
|
pop ecx
|
|
loadxm_ttl:
|
|
mov al,[edx]
|
|
inc edx
|
|
cmp al,20h ; copy only printable chars
|
|
jl loadxm_ttl_ok
|
|
if UCODE
|
|
stosw
|
|
else
|
|
stosb
|
|
endif
|
|
loadxm_ttl_ok:
|
|
dec ecx
|
|
jnz loadxm_ttl
|
|
xchg eax,ecx
|
|
stosd
|
|
else
|
|
xor eax,eax
|
|
endif
|
|
; COUNT NUM. OF PATTERNS
|
|
movzx ecx,WORD PTR [esi+FMUSIC_MODULE.numorders]
|
|
movzx ebx,WORD PTR [esi+FMUSIC_MODULE.numpatternsmem]
|
|
neg ebx
|
|
mov edi,esi
|
|
sbb edx,edx
|
|
and ecx,edx
|
|
neg ebx
|
|
dec ecx
|
|
movzx edx,dl
|
|
mov [ebp+loadxm_fnumpat],ebx
|
|
if CHK4VALIDITY
|
|
cmp ecx,edx
|
|
ja loadxm_R
|
|
endif
|
|
loadxm_for_pats:
|
|
mov dl,[esi+FMUSIC_MODULE.orderlist]
|
|
cmp edx,eax
|
|
jbe loadxm_for_continue
|
|
xchg eax,edx
|
|
loadxm_for_continue:
|
|
inc esi
|
|
dec ecx
|
|
jns loadxm_for_pats
|
|
mov [ebp+loadxm_numpat],eax
|
|
inc eax
|
|
mov esi,edi
|
|
; ALLOCATE THE PATTERN ARRAY (whatever is bigger: fnumpat or numpat) & CHANNEL POOL
|
|
cmp eax,ebx
|
|
jae loadxm_pats_ok2
|
|
xchg eax,ebx
|
|
loadxm_pats_ok2:
|
|
movzx ecx,BYTE PTR [esi+FMUSIC_MODULE.numinsts]
|
|
imul ecx,FMUSIC_INSTRUMENT_size
|
|
mov [esi+FMUSIC_MODULE.numpatternsmem],ax
|
|
lea edi,[ecx+eax*FMUSIC_PATTERN_size]
|
|
mov eax,edi
|
|
sub edi,ecx
|
|
movzx ecx,BYTE PTR [esi+FMUSIC_MODULE.numchannels_xm]
|
|
if CHK4VALIDITY
|
|
cmp ecx,64
|
|
jle loadxm_numchan_ok
|
|
xor ecx,ecx
|
|
loadxm_numchan_ok:
|
|
endif
|
|
mov [esi+FMUSIC_MODULE.numchannels],ecx
|
|
mov ebx,ecx
|
|
shl ebx,7 ; *FSOUND_CHANNEL_size*2 == *FMUSIC_CHANNEL_size
|
|
if CHK4VALIDITY
|
|
jz loadxm_R
|
|
endif
|
|
mov [ebp+loadxm_count2],ecx
|
|
lea eax,[eax+ebx*2]
|
|
; numbytes : EAX
|
|
call alloc
|
|
lea edx,[eax+ebx]
|
|
mov [esi+FMUSIC_MODULE.Channels],eax
|
|
mov [esi+FMUSIC_MODULE.uFMOD_Ch],edx
|
|
mov ebx,FMUSIC_CHANNEL_size ; = FSOUND_CHANNEL_size*2
|
|
loop_2:
|
|
mov BYTE PTR [eax+FSOUND_CHANNEL.speedhi],1
|
|
mov [edx+FMUSIC_CHANNEL.cptr],eax
|
|
add eax,ebx
|
|
add edx,ebx
|
|
dec DWORD PTR [ebp+loadxm_count2]
|
|
jnz loop_2
|
|
mov [esi],edx ; FMUSIC_MODULE.pattern
|
|
add edi,edx
|
|
movzx ecx,WORD PTR [esi+FMUSIC_MODULE.defaultbpm]
|
|
mov [esi+FMUSIC_MODULE.instrument],edi
|
|
mov edi,edx
|
|
; bpm : ECX
|
|
call SetBPM
|
|
push 64
|
|
movzx ecx,WORD PTR [esi+FMUSIC_MODULE.defaultspeed]
|
|
pop DWORD PTR [esi+FMUSIC_MODULE.globalvolume]
|
|
mov [esi+FMUSIC_MODULE.speed],ecx
|
|
; ALLOCATE INSTRUMENT ARRAY
|
|
mov eax,[ebp+loadxm_fnumpat]
|
|
; READ & UNPACK PATTERNS
|
|
loadxm_load_pats:
|
|
push 9
|
|
lea eax,[ebp+loadxm_pat]
|
|
pop edx
|
|
; buf : EAX
|
|
; size : EDX
|
|
call [uFMOD_fread]
|
|
; ALLOCATE PATTERN BUFFER
|
|
mov eax,[ebp+loadxm_pat_size] ; length of pattern & packed pattern size
|
|
mov ecx,[esi+FMUSIC_MODULE.numchannels]
|
|
cmp eax,10000h
|
|
mov [edi],eax
|
|
movzx eax,ax
|
|
jb loadxm_ldpats_continue ; skip an empty pattern
|
|
if CHK4VALIDITY
|
|
cmp eax,257
|
|
sbb edx,edx
|
|
and eax,edx
|
|
jz loadxm_R
|
|
endif
|
|
mul ecx
|
|
mov [ebp+loadxm_count2],eax
|
|
lea eax,[eax+eax*4] ; x SIZE FMUSIC_NOTE
|
|
; numbytes : EAX
|
|
call alloc
|
|
mov [edi+FMUSIC_PATTERN.data],eax
|
|
xchg eax,ebx
|
|
loadxm_for_rowsxchan:
|
|
push esi
|
|
mov esi,[uFMOD_fread]
|
|
xor edx,edx
|
|
lea eax,[ebp+loadxm_skip]
|
|
inc edx
|
|
; buf : EAX
|
|
; size : EDX
|
|
call esi ; uFMOD_fread
|
|
movzx edx,BYTE PTR [ebp+loadxm_skip]
|
|
test dl,80h
|
|
jz loadxm_noskip
|
|
and edx,1
|
|
jz loadxm_nonote
|
|
mov eax,ebx ; &nptr->note
|
|
; buf : EAX
|
|
; size : EDX
|
|
call esi ; uFMOD_fread
|
|
loadxm_nonote:
|
|
test BYTE PTR [ebp+loadxm_skip],2
|
|
jz loadxm_nonumber
|
|
xor edx,edx
|
|
lea eax,[ebx+1] ; &nptr->number
|
|
inc edx
|
|
; buf : EAX
|
|
; size : EDX
|
|
call esi ; uFMOD_fread
|
|
loadxm_nonumber:
|
|
test BYTE PTR [ebp+loadxm_skip],4
|
|
jz loadxm_novolume
|
|
xor edx,edx
|
|
lea eax,[ebx+2] ; &nptr->volume
|
|
inc edx
|
|
; buf : EAX
|
|
; size : EDX
|
|
call esi ; uFMOD_fread
|
|
loadxm_novolume:
|
|
test BYTE PTR [ebp+loadxm_skip],8
|
|
jz loadxm_noeffect
|
|
xor edx,edx
|
|
lea eax,[ebx+3] ; &nptr->effect
|
|
inc edx
|
|
; buf : EAX
|
|
; size : EDX
|
|
call esi ; uFMOD_fread
|
|
loadxm_noeffect:
|
|
test BYTE PTR [ebp+loadxm_skip],16
|
|
jz loadxm_isnote97
|
|
xor edx,edx
|
|
lea eax,[ebx+4] ; &nptr->eparam
|
|
inc edx
|
|
jmp loadxm_skip_read
|
|
loadxm_noskip:
|
|
test edx,edx
|
|
jz loadxm_skip_z
|
|
mov [ebx],dl
|
|
loadxm_skip_z:
|
|
lea eax,[ebx+1]
|
|
mov dl,4
|
|
loadxm_skip_read:
|
|
; buf : EAX
|
|
; size : EDX
|
|
call esi ; uFMOD_fread
|
|
loadxm_isnote97:
|
|
pop esi
|
|
inc ebx
|
|
mov dl,BYTE PTR [esi+FMUSIC_MODULE.numinsts]
|
|
cmp [ebx],dl
|
|
jbe loadxm_number_ok
|
|
mov BYTE PTR [ebx],0
|
|
loadxm_number_ok:
|
|
add ebx,4
|
|
dec DWORD PTR [ebp+loadxm_count2]
|
|
jnz loadxm_for_rowsxchan
|
|
loadxm_ldpats_continue:
|
|
inc DWORD PTR [ebp+loadxm_count1]
|
|
mov eax,[ebp+loadxm_fnumpat]
|
|
add edi,8
|
|
cmp eax,[ebp+loadxm_count1]
|
|
ja loadxm_load_pats
|
|
; allocate and clean out any extra patterns
|
|
mov ecx,[ebp+loadxm_numpat]
|
|
cmp ecx,eax
|
|
jb loadxm_extrapats_ok
|
|
mov ebx,[esi] ; FMUSIC_MODULE.pattern
|
|
mov eax,[esi+FMUSIC_MODULE.numchannels]
|
|
push esi
|
|
lea esi,[ebx+ecx*FMUSIC_PATTERN_size]
|
|
lea edi,[eax+eax*4]
|
|
shl edi,6 ; numchannels*64*SIZE FMUSIC_NOTE
|
|
loadxm_for_extrapats:
|
|
dec DWORD PTR [ebp+loadxm_numpat]
|
|
mov eax,edi
|
|
mov BYTE PTR [esi],64 ; pptr->rows = 64
|
|
; Allocate memory for pattern buffer
|
|
; numbytes : EAX
|
|
call alloc
|
|
mov [esi+FMUSIC_PATTERN.data],eax
|
|
sub esi,FMUSIC_PATTERN_size
|
|
mov eax,[ebp+loadxm_fnumpat]
|
|
cmp [ebp+loadxm_numpat],eax
|
|
jae loadxm_for_extrapats
|
|
pop esi
|
|
loadxm_extrapats_ok:
|
|
xor eax,eax
|
|
mov [esi+FMUSIC_MODULE.mixer_samplesleft],eax
|
|
mov [esi+FMUSIC_MODULE.tick],eax
|
|
if PATTERNDELAY_ON
|
|
lea edi,[esi+FMUSIC_MODULE.patterndelay]
|
|
stosd
|
|
else
|
|
lea edi,[esi+FMUSIC_MODULE.nextorder]
|
|
endif
|
|
stosd
|
|
stosd
|
|
; Load instrument information
|
|
mov al,BYTE PTR [esi+FMUSIC_MODULE.numinsts]
|
|
test al,al
|
|
jz loadxm_ret1
|
|
mov [ebp+loadxm_count1],al
|
|
mov ebx,[esi+FMUSIC_MODULE.instrument]
|
|
loadxm_for_instrs:
|
|
push 33
|
|
lea eax,[ebp+loadxm_tmp]
|
|
pop edx
|
|
; buf : EAX
|
|
; size : EDX
|
|
call [uFMOD_fread] ; instrument size & name
|
|
mov esi,[ebp+loadxm_tmp] ; firstsampleoffset = tmp[0]
|
|
mov dl,[ebp+loadxm_tmp27]
|
|
sub esi,33
|
|
test dl,dl
|
|
jz loadxm_inst_ok
|
|
if CHK4VALIDITY
|
|
xor eax,eax
|
|
cmp DWORD PTR [ebp+loadxm_tmp29],41
|
|
sbb ecx,ecx
|
|
not ecx
|
|
or edx,ecx
|
|
cmp dl,16
|
|
ja loadxm_R ; if(numsamples > 16) goto error
|
|
endif
|
|
mov edx,208
|
|
lea eax,[ebx+FMUSIC_INSTRUMENT.keymap]
|
|
sub esi,edx
|
|
; buf : EAX
|
|
; size : EDX
|
|
call [uFMOD_fread]
|
|
loadxm_inst_ok:
|
|
xor ecx,ecx
|
|
xchg eax,esi
|
|
inc ecx ; SEEK_CUR
|
|
; pos : EAX
|
|
; org : ECX
|
|
; !org : Z
|
|
call uFMOD_lseek
|
|
lea edx,[ebx+FMUSIC_INSTRUMENT.VOLfade]
|
|
xor eax,eax
|
|
mov cx,[edx]
|
|
shl ecx,1
|
|
cmp BYTE PTR [edx+FMUSIC_INSTRUMENT.VOLnumpoints-FMUSIC_INSTRUMENT.VOLfade],2
|
|
mov [edx],cx ; iptr->VOLfade *= 2
|
|
jnb ladxm_voltype_ok
|
|
mov BYTE PTR [edx+FMUSIC_INSTRUMENT.VOLtype-FMUSIC_INSTRUMENT.VOLfade],al
|
|
ladxm_voltype_ok:
|
|
cmp BYTE PTR [edx+FMUSIC_INSTRUMENT.PANnumpoints-FMUSIC_INSTRUMENT.VOLfade],2
|
|
jnb loadxm_PANtype_ok
|
|
mov BYTE PTR [edx+FMUSIC_INSTRUMENT.PANtype-FMUSIC_INSTRUMENT.VOLfade],al
|
|
loadxm_PANtype_ok:
|
|
cmp [ebp+loadxm_tmp27],al
|
|
je loadx_for_loadsamp_end
|
|
mov [ebp+loadxm_numpat],eax
|
|
mov [ebp+loadxm_fnumpat],ebx ; FMUSIC_INSTRUMENT.sample
|
|
loadxm_for_samp:
|
|
lea eax,[ebp+loadxm_sample_2]
|
|
mov edx,[ebp+loadxm_tmp29]
|
|
; buf : EAX
|
|
; size : EDX
|
|
call [uFMOD_fread]
|
|
mov esi,[ebp+loadxm_s0loopstart]
|
|
mov edi,[ebp+loadxm_s0looplen]
|
|
mov al,[ebp+loadxm_s0bytes]
|
|
mov ecx,eax
|
|
shr eax,4 ; sample[0].bytes >>= 4
|
|
and al,1 ; [b 4] : 8/16 bit sample data
|
|
mov [ebp+loadxm_s0bytes],al
|
|
jz loadxm_s0bytes_ok
|
|
shr DWORD PTR [ebp+loadxm_sample_2],1
|
|
shr esi,1
|
|
shr edi,1
|
|
loadxm_s0bytes_ok:
|
|
mov eax,[ebp+loadxm_sample_2]
|
|
cmp eax,esi
|
|
jg loadxm_loopstart_ok
|
|
mov esi,eax
|
|
loadxm_loopstart_ok:
|
|
lea edx,[esi+edi]
|
|
sub edx,eax
|
|
js loadxm_looplen_ok
|
|
sub edi,edx
|
|
loadxm_looplen_ok:
|
|
and ecx,3 ; [b 0-1] : loop type
|
|
jz loadxm_reset_sample
|
|
test edi,edi
|
|
jnz loadxm_s0loop_ok
|
|
loadxm_reset_sample:
|
|
xor esi,esi
|
|
xor ecx,ecx
|
|
mov edi,eax
|
|
loadxm_s0loop_ok:
|
|
mov [ebp+loadxm_s0loopstart],esi
|
|
mov [ebp+loadxm_s0looplen],edi
|
|
mov [ebp+loadxm_s0loopmode],cl
|
|
lea eax,[eax+eax+26] ; sample[0].length*2+SIZE FSOUND_SAMPLE+4
|
|
; numbytes : EAX
|
|
call alloc
|
|
mov ecx,[ebp+loadxm_fnumpat]
|
|
mov [ecx],eax
|
|
; memcpy(iptr->sample[count2],sample,sizeof(FSOUND_SAMPLE))
|
|
inc DWORD PTR [ebp+loadxm_numpat]
|
|
add DWORD PTR [ebp+loadxm_fnumpat],4
|
|
push 5
|
|
xchg eax,edi
|
|
mov eax,[ebp+loadxm_numpat]
|
|
pop ecx
|
|
cmp al,[ebp+loadxm_tmp27]
|
|
lea esi,[ebp+loadxm_sample_2]
|
|
rep movsd
|
|
jb loadxm_for_samp
|
|
; Load sample data
|
|
mov [ebp+loadxm_numpat],ecx
|
|
; ebx <- FMUSIC_INSTRUMENT.sample
|
|
loadx_for_loadsamp:
|
|
mov esi,[ebx+ecx*4]
|
|
xor eax,eax
|
|
mov edx,[esi]
|
|
mov ch,[esi+FSOUND_SAMPLE.Resved]
|
|
mov cl,[esi+FSOUND_SAMPLE.bytes]
|
|
if CHK4VALIDITY
|
|
test edx,0FFC00000h
|
|
jnz loadxm_R
|
|
endif
|
|
add esi,FSOUND_SAMPLE.buff
|
|
if ADPCM_ON
|
|
cmp ch,0ADh ; ModPlug 4-bit ADPCM
|
|
jne loadxm_regular_samp
|
|
inc edx
|
|
mov edi,esi
|
|
sar edx,1
|
|
push ebx
|
|
push edx
|
|
lea edx,[edx+edx*2]
|
|
add edi,edx ; ptr = buff+compressed_length*3
|
|
; Read in the compression table
|
|
lea edx,[eax+16] ; edx = 16
|
|
lea eax,[ebp+loadxm_sample_2]
|
|
mov ebx,eax
|
|
; buf : EAX
|
|
; size : EDX
|
|
call [uFMOD_fread]
|
|
; Read in the sample data
|
|
pop edx
|
|
mov eax,edi
|
|
; buf : EAX
|
|
; size : EDX
|
|
call [uFMOD_fread]
|
|
; Decompress sample data
|
|
mov edx,esi
|
|
xor ecx,ecx ; delta
|
|
loadxm_unpack_loop:
|
|
cmp edx,edi
|
|
jge loadxm_unpack_ok
|
|
mov al,[edi]
|
|
mov ah,al
|
|
and al,0Fh
|
|
xlatb
|
|
shr ah,4
|
|
inc edi
|
|
add ch,al
|
|
mov al,ah
|
|
xlatb
|
|
add al,ch
|
|
shl eax,24
|
|
or ecx,eax
|
|
mov [edx],ecx
|
|
shr ecx,16 ; ch <- delta
|
|
add edx,4
|
|
jmp loadxm_unpack_loop
|
|
loadxm_unpack_ok:
|
|
pop ebx
|
|
jmp loadxm_chk_loop_bidi
|
|
loadxm_regular_samp:
|
|
endif
|
|
shl edx,cl ; sptr->length << sptr->bytes
|
|
mov eax,esi
|
|
; buf : EAX
|
|
; size : EDX
|
|
call [uFMOD_fread]
|
|
mov ecx,DWORD PTR [esi+FSOUND_SAMPLE._length-FSOUND_SAMPLE.buff]
|
|
lea edi,[ecx+esi] ; buff = sptr->buff+sptr->length
|
|
lea eax,[edi+ecx] ; ptr = buff+sptr->length
|
|
xor edx,edx
|
|
cmp BYTE PTR [esi+FSOUND_SAMPLE.bytes-FSOUND_SAMPLE.buff],dl
|
|
jne loadxm_16bit_ok
|
|
; Promote to 16 bits
|
|
loadxm_to16bits:
|
|
dec eax
|
|
dec edi
|
|
dec eax
|
|
mov dh,[edi]
|
|
cmp eax,edi
|
|
mov [eax],dx
|
|
ja loadxm_to16bits
|
|
xor edx,edx
|
|
loadxm_16bit_ok:
|
|
mov eax,esi
|
|
; Do delta conversion
|
|
loadxm_do_delta_conv:
|
|
add dx,[eax]
|
|
mov [eax],dx
|
|
dec ecx
|
|
lea eax,[eax+2]
|
|
jg loadxm_do_delta_conv
|
|
js loadxm_loops_ok
|
|
loadxm_chk_loop_bidi:
|
|
mov eax,DWORD PTR [esi+FSOUND_SAMPLE.looplen-FSOUND_SAMPLE.buff]
|
|
mov ecx,DWORD PTR [esi+FSOUND_SAMPLE.loopstart-FSOUND_SAMPLE.buff]
|
|
add eax,ecx
|
|
cmp BYTE PTR [esi+FSOUND_SAMPLE.loopmode-FSOUND_SAMPLE.buff],2 ; LOOP_BIDI
|
|
lea eax,[esi+eax*2]
|
|
jnz loadxm_chk_loop_normal
|
|
mov cx,[eax-2]
|
|
jmp loadxm_fix_loop
|
|
loadxm_chk_loop_normal:
|
|
cmp BYTE PTR [esi+FSOUND_SAMPLE.loopmode-FSOUND_SAMPLE.buff],1 ; LOOP_NORMAL
|
|
jnz loadxm_loops_ok
|
|
mov cx,WORD PTR [esi+ecx*2]
|
|
loadxm_fix_loop:
|
|
mov [eax],cx
|
|
loadxm_loops_ok:
|
|
inc DWORD PTR [ebp+loadxm_numpat]
|
|
mov ecx,[ebp+loadxm_numpat]
|
|
cmp cl,[ebp+loadxm_tmp27]
|
|
jb loadx_for_loadsamp
|
|
loadx_for_loadsamp_end:
|
|
add ebx,FMUSIC_INSTRUMENT_size
|
|
dec BYTE PTR [ebp+loadxm_count1]
|
|
jnz loadxm_for_instrs
|
|
loadxm_ret1:
|
|
inc eax
|
|
loadxm_R:
|
|
pop ebx
|
|
donote_R:
|
|
leave
|
|
ret
|
|
|
|
DoNote:
|
|
; mod+36 = ESI
|
|
var_mod equ -4
|
|
donote_sptr equ -8
|
|
donote_jumpflag equ -10
|
|
donote_porta equ -12
|
|
donote_oldpan equ -16
|
|
donote_currtick equ -20
|
|
donote_oldfreq equ -24
|
|
donote_iptr equ -28
|
|
; Point our note pointer to the correct pattern buffer, and to the
|
|
; correct offset in this buffer indicated by row and number of channels
|
|
mov eax,[esi+FMUSIC_MODULE.order-36]
|
|
push ebp
|
|
movzx ebx,BYTE PTR [eax+esi+FMUSIC_MODULE.orderlist-36]
|
|
mov ebp,esp
|
|
mov eax,[esi+FMUSIC_MODULE.row-36]
|
|
lea ebx,[ecx+ebx*FMUSIC_PATTERN_size]
|
|
mov ecx,[esi+FMUSIC_MODULE.numchannels-36]
|
|
if PATTERNBREAK_ON
|
|
if PATTERNJUMP_ON
|
|
mov BYTE PTR [ebp+donote_jumpflag],ch
|
|
endif
|
|
endif
|
|
mul ecx
|
|
lea edi,[eax+eax*4] ; x SIZE FMUSIC_NOTE
|
|
push esi
|
|
add edi,[ebx+FMUSIC_PATTERN.data] ; mod->pattern[mod->orderlist[mod->order]].data+(mod->row*mod->numchannels)
|
|
sub esp,24
|
|
; Loop through each channel in the row
|
|
shl ecx,7 ; x FMUSIC_CHANNEL_size
|
|
jz donote_R
|
|
push esi
|
|
mov esi,[esi+FMUSIC_MODULE.uFMOD_Ch-36]
|
|
push ebx
|
|
inc esi
|
|
inc esi
|
|
add ecx,esi
|
|
donote_for_channels:
|
|
push ecx
|
|
mov bl,[edi+FMUSIC_NOTE.eparam]
|
|
mov al,[edi+FMUSIC_NOTE.effect]
|
|
and ebx,0Fh
|
|
cmp al,FMUSIC_XM_PORTATO
|
|
je donote_doporta
|
|
cmp al,FMUSIC_XM_PORTATOVOLSLIDE
|
|
donote_doporta:
|
|
setz [ebp+donote_porta]
|
|
; First store note and instrument number if there was one
|
|
mov cl,[edi+FMUSIC_NOTE.number]
|
|
jz donote_rem_note
|
|
dec cl
|
|
js donote_rem_inst
|
|
mov [esi+FMUSIC_CHANNEL.inst-2],cl ; remember the instrument #
|
|
donote_rem_inst:
|
|
mov cl,[edi] ; get current note
|
|
dec ecx
|
|
cmp cl,96
|
|
jae donote_rem_note
|
|
mov [esi+FMUSIC_CHANNEL.note-2],cl ; remember the note
|
|
donote_rem_note:
|
|
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.inst-2]
|
|
mov eax,[ebp+var_mod]
|
|
imul ecx,FMUSIC_INSTRUMENT_size
|
|
add ecx,[eax+FMUSIC_MODULE.instrument-36]
|
|
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.note-2]
|
|
cdq
|
|
mov al,[eax+ecx+FMUSIC_INSTRUMENT.keymap]
|
|
cmp al,16
|
|
mov [ebp+donote_iptr],ecx
|
|
jae donote_set_sptr
|
|
mov edx,[ecx+eax*4+FMUSIC_INSTRUMENT.sample]
|
|
donote_set_sptr:
|
|
test edx,edx
|
|
jnz donote_valid_sptr
|
|
mov edx,OFFSET DummySamp
|
|
donote_valid_sptr:
|
|
mov [ebp+donote_sptr],edx
|
|
if NOTEDELAY_ON
|
|
mov ecx,[esi+FMUSIC_CHANNEL.freq-2]
|
|
mov eax,[esi+FMUSIC_CHANNEL.volume-2]
|
|
mov [ebp+donote_oldfreq],ecx
|
|
mov ecx,[esi+FMUSIC_CHANNEL.pan-2]
|
|
mov [ebp+donote_currtick],eax
|
|
mov [ebp+donote_oldpan],ecx
|
|
endif
|
|
if TREMOLO_ON
|
|
; if there is no more tremolo, set volume to volume + last tremolo delta
|
|
mov al,[edi+FMUSIC_NOTE.effect]
|
|
cmp al,FMUSIC_XM_TREMOLO
|
|
je donote_tremolo_vol
|
|
cmp BYTE PTR [esi+FMUSIC_CHANNEL.recenteffect-2],FMUSIC_XM_TREMOLO
|
|
jne donote_tremolo_vol
|
|
mov ecx,[esi+FMUSIC_CHANNEL.voldelta-2]
|
|
add [esi+FMUSIC_CHANNEL.volume-2],ecx
|
|
donote_tremolo_vol:
|
|
mov [esi+FMUSIC_CHANNEL.recenteffect-2],al
|
|
endif
|
|
xor ecx,ecx
|
|
mov [esi+FMUSIC_CHANNEL.voldelta-2],ecx
|
|
mov [esi+FMUSIC_CHANNEL.freqdelta-2],ecx
|
|
mov BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME_OR_FREQ
|
|
; PROCESS NOTE
|
|
mov cl,[edi] ; note
|
|
dec ecx
|
|
cmp cl,96
|
|
jae donote_note_ok
|
|
; get note according to relative note
|
|
movsx eax,BYTE PTR [edx+FSOUND_SAMPLE.relative]
|
|
add ecx,eax
|
|
mov eax,[ebp+var_mod]
|
|
mov [esi+FMUSIC_CHANNEL.realnote-2],cl
|
|
; Get period according to realnote and finetune
|
|
test BYTE PTR [eax+FMUSIC_MODULE.flags-36],1
|
|
je donote_flagsn1
|
|
mov eax,[ebp+donote_sptr]
|
|
movsx eax,BYTE PTR [eax+FSOUND_SAMPLE.finetune]
|
|
cdq
|
|
shl ecx,6
|
|
sub eax,edx
|
|
sar eax,1
|
|
lea eax,[ecx+eax-7680]
|
|
neg eax
|
|
if AMIGAPERIODS_ON
|
|
jmp donote_chk_porta
|
|
donote_flagsn1:
|
|
xchg eax,ecx ; note : EAX
|
|
mov ecx,[ebp+donote_sptr] ; [sptr] : ECX
|
|
; ESI != 0
|
|
call AmigaPeriod
|
|
donote_chk_porta:
|
|
mov [esi+FMUSIC_CHANNEL.period-2],eax
|
|
else
|
|
mov [esi+FMUSIC_CHANNEL.period-2],eax
|
|
donote_flagsn1:
|
|
mov eax,[esi+FMUSIC_CHANNEL.period-2]
|
|
endif
|
|
; Frequency only changes if there are no portamento effects
|
|
cmp BYTE PTR [ebp+donote_porta],0
|
|
jne donote_freq_ok
|
|
mov [esi+FMUSIC_CHANNEL.freq-2],eax
|
|
donote_freq_ok:
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_TRIGGER
|
|
donote_note_ok:
|
|
; PROCESS INSTRUMENT NUMBER
|
|
cmp BYTE PTR [edi+FMUSIC_NOTE.number],0
|
|
je donote_zcptr_ok
|
|
mov eax,[ebp+donote_sptr]
|
|
; DESCRIPTION: Reset current channel
|
|
push edi
|
|
push 9
|
|
movzx ecx,BYTE PTR [eax+FSOUND_SAMPLE.defvol]
|
|
mov [esi+FMUSIC_CHANNEL.volume-2],ecx
|
|
pop ecx
|
|
movzx eax,BYTE PTR [eax+FSOUND_SAMPLE.defpan]
|
|
mov [esi+FMUSIC_CHANNEL.pan-2],eax
|
|
push 64
|
|
xor eax,eax
|
|
pop DWORD PTR [esi+FMUSIC_CHANNEL.envvol-2]
|
|
push 32
|
|
lea edi,[esi+FMUSIC_CHANNEL.envvoltick-2]
|
|
pop DWORD PTR [esi+FMUSIC_CHANNEL.envpan-2]
|
|
mov DWORD PTR [esi+FMUSIC_CHANNEL.fadeoutvol-2],65536
|
|
; memset(&cptr->envvoltick,0,36)
|
|
rep stosd
|
|
; Retrigger tremolo and vibrato waveforms
|
|
mov cl,[esi+FMUSIC_CHANNEL.wavecontrol-2]
|
|
pop edi
|
|
cmp cl,4Fh
|
|
jge z_tremolopos_ok
|
|
mov BYTE PTR [esi+FMUSIC_CHANNEL.tremolopos-2],al ; = 0
|
|
z_tremolopos_ok:
|
|
test cl,0Ch
|
|
jnz z_vibpos_ok
|
|
mov BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2],al ; = 0
|
|
z_vibpos_ok:
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME_OR_PAN
|
|
donote_zcptr_ok:
|
|
if VOLUMEBYTE_ON
|
|
; PROCESS VOLUME BYTE
|
|
movzx edx,BYTE PTR [edi+FMUSIC_NOTE.uvolume]
|
|
; volume : EDX
|
|
; cptr+2 : ESI
|
|
call VolByte
|
|
endif
|
|
; PROCESS KEY OFF
|
|
cmp BYTE PTR [edi],97 ; note
|
|
jae donote_set_keyoff
|
|
cmp BYTE PTR [edi+FMUSIC_NOTE.effect],FMUSIC_XM_KEYOFF
|
|
jne donote_keyoff_ok
|
|
donote_set_keyoff:
|
|
inc BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2]
|
|
donote_keyoff_ok:
|
|
; PROCESS ENVELOPES
|
|
if VOLUMEENVELOPE_ON
|
|
mov ecx,[ebp+donote_iptr]
|
|
test BYTE PTR [ecx+FMUSIC_INSTRUMENT.VOLtype],1
|
|
jz donote_no_voltype
|
|
mov al,FMUSIC_VOLUME
|
|
; cptr+2 : ESI
|
|
; env_iptr : ECX
|
|
; control : AL
|
|
call Envelope
|
|
jmp donote_volenv_ok
|
|
donote_no_voltype:
|
|
endif
|
|
cmp BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2],0
|
|
je donote_volenv_ok
|
|
and DWORD PTR [esi+FMUSIC_CHANNEL.envvol-2],0
|
|
donote_volenv_ok:
|
|
if PANENVELOPE_ON
|
|
mov ecx,[ebp+donote_iptr]
|
|
test BYTE PTR [ecx+FMUSIC_INSTRUMENT.PANtype],1
|
|
je donote_no_pantype
|
|
mov al,FMUSIC_PAN
|
|
; cptr+2 : ESI
|
|
; env_iptr : ECX
|
|
; control : AL
|
|
call Envelope
|
|
donote_no_pantype:
|
|
endif
|
|
; PROCESS VOLUME FADEOUT
|
|
cmp BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2],0
|
|
mov ecx,[ebp+donote_iptr]
|
|
je donote_fadevol_ok
|
|
movzx eax,WORD PTR [ecx+FMUSIC_INSTRUMENT.VOLfade]
|
|
sub [esi+FMUSIC_CHANNEL.fadeoutvol-2],eax
|
|
jns donote_fadevol_ok
|
|
and DWORD PTR [esi+FMUSIC_CHANNEL.fadeoutvol-2],0
|
|
donote_fadevol_ok:
|
|
; PROCESS TICK 0 EFFECTS
|
|
movzx eax,BYTE PTR [edi+FMUSIC_NOTE.effect]
|
|
dec eax ; skip FMUSIC_XM_ARPEGGIO
|
|
movzx edx,BYTE PTR [edi+FMUSIC_NOTE.eparam]
|
|
if EXTRAFINEPORTA_ON
|
|
cmp al,32
|
|
else
|
|
if TREMOR_ON
|
|
cmp al,28
|
|
else
|
|
if MULTIRETRIG_ON
|
|
cmp al,26
|
|
else
|
|
if PANSLIDE_ON
|
|
cmp al,24
|
|
else
|
|
if SETENVELOPEPOS_ON
|
|
cmp al,20
|
|
else
|
|
if GLOBALVOLSLIDE_ON
|
|
cmp al,16
|
|
else
|
|
if SETGLOBALVOLUME_ON
|
|
cmp al,15
|
|
else
|
|
if SETSPEED_ON
|
|
cmp al,14
|
|
else
|
|
cmp al,13
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
ja donote_s1_brk
|
|
test edx,edx
|
|
call DWORD PTR [eax*4+S1_TBL]
|
|
donote_s1_brk:
|
|
if INSTRUMENTVIBRATO_ON
|
|
push DWORD PTR [ebp+donote_iptr]
|
|
endif
|
|
push DWORD PTR [ebp+donote_sptr]
|
|
; cptr+2 : ESI
|
|
call DoFlags
|
|
sub esi,-(FMUSIC_CHANNEL_size)
|
|
pop ecx
|
|
add edi,FMUSIC_NOTE_size
|
|
cmp esi,ecx
|
|
jl donote_for_channels
|
|
pop ebx
|
|
pop esi
|
|
leave
|
|
S1_r:
|
|
ret
|
|
S1_TBL:
|
|
if PORTAUP_OR_DOWN_ON
|
|
dd S1_C1
|
|
dd S1_C1
|
|
else
|
|
dd S1_r
|
|
dd S1_r
|
|
endif
|
|
if PORTATO_ON
|
|
dd S1_C3
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if VIBRATO_ON
|
|
dd S1_C4
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if PORTATOVOLSLIDE_ON
|
|
dd S1_C5
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if VIBRATOVOLSLIDE_ON
|
|
dd S1_C6
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if TREMOLO_ON
|
|
dd S1_C7
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if SETPANPOSITION_ON
|
|
dd S1_C8
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if SETSAMPLEOFFSET_ON
|
|
dd S1_C9
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if VOLUMESLIDE_ON
|
|
dd S1_C10
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if PATTERNJUMP_ON
|
|
dd S1_C11
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if SETVOLUME_ON
|
|
dd S1_C12
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if PATTERNBREAK_ON
|
|
dd S1_C13
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_C14
|
|
if EXTRAFINEPORTA_ON
|
|
if SETSPEED_ON
|
|
dd S1_C15
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if SETGLOBALVOLUME_ON
|
|
dd S1_C16
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if GLOBALVOLSLIDE_ON
|
|
dd S1_C17
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r ; unassigned effect ordinal [18]
|
|
dd S1_r ; unassigned effect ordinal [19]
|
|
dd S1_r ; skip FMUSIC_XM_KEYOFF
|
|
if SETENVELOPEPOS_ON
|
|
dd S1_C21
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r ; unassigned effect ordinal [22]
|
|
dd S1_r ; unassigned effect ordinal [23]
|
|
dd S1_r ; unassigned effect ordinal [24]
|
|
if PANSLIDE_ON
|
|
dd S1_C25
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r ; unassigned effect ordinal [26]
|
|
if MULTIRETRIG_ON
|
|
dd S1_C27
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r ; unassigned effect ordinal [28]
|
|
if TREMOR_ON
|
|
dd S1_C29
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r ; unassigned effect ordinal [30]
|
|
dd S1_r ; unassigned effect ordinal [31]
|
|
dd S1_r ; unassigned effect ordinal [32]
|
|
dd S1_C33
|
|
else
|
|
if TREMOR_ON
|
|
if SETSPEED_ON
|
|
dd S1_C15
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if SETGLOBALVOLUME_ON
|
|
dd S1_C16
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if GLOBALVOLSLIDE_ON
|
|
dd S1_C17
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
dd S1_r
|
|
dd S1_r
|
|
if SETENVELOPEPOS_ON
|
|
dd S1_C21
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
dd S1_r
|
|
dd S1_r
|
|
if PANSLIDE_ON
|
|
dd S1_C25
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
if MULTIRETRIG_ON
|
|
dd S1_C27
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
dd S1_C29
|
|
else
|
|
if MULTIRETRIG_ON
|
|
if SETSPEED_ON
|
|
dd S1_C15
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if SETGLOBALVOLUME_ON
|
|
dd S1_C16
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if GLOBALVOLSLIDE_ON
|
|
dd S1_C17
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
dd S1_r
|
|
dd S1_r
|
|
if SETENVELOPEPOS_ON
|
|
dd S1_C21
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
dd S1_r
|
|
dd S1_r
|
|
if PANSLIDE_ON
|
|
dd S1_C25
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
dd S1_C27
|
|
else
|
|
if PANSLIDE_ON
|
|
if SETSPEED_ON
|
|
dd S1_C15
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if SETGLOBALVOLUME_ON
|
|
dd S1_C16
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if GLOBALVOLSLIDE_ON
|
|
dd S1_C17
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
dd S1_r
|
|
dd S1_r
|
|
if SETENVELOPEPOS_ON
|
|
dd S1_C21
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
dd S1_r
|
|
dd S1_r
|
|
dd S1_C25
|
|
else
|
|
if SETENVELOPEPOS_ON
|
|
if SETSPEED_ON
|
|
dd S1_C15
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if SETGLOBALVOLUME_ON
|
|
dd S1_C16
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if GLOBALVOLSLIDE_ON
|
|
dd S1_C17
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_r
|
|
dd S1_r
|
|
dd S1_r
|
|
dd S1_C21
|
|
else
|
|
if GLOBALVOLSLIDE_ON
|
|
if SETSPEED_ON
|
|
dd S1_C15
|
|
else
|
|
dd S1_r
|
|
endif
|
|
if SETGLOBALVOLUME_ON
|
|
dd S1_C16
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_C17
|
|
else
|
|
if SETGLOBALVOLUME_ON
|
|
if SETSPEED_ON
|
|
dd S1_C15
|
|
else
|
|
dd S1_r
|
|
endif
|
|
dd S1_C16
|
|
else
|
|
if SETSPEED_ON
|
|
dd S1_C15
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
if PORTAUP_OR_DOWN_ON
|
|
S1_C1:
|
|
jz donote_xm_porta_end
|
|
mov [esi+FMUSIC_CHANNEL.portaupdown-2],dl
|
|
donote_xm_porta_end:
|
|
ret
|
|
endif
|
|
if PORTATO_ON
|
|
S1_C3:
|
|
jz donote_xm_portato_end
|
|
mov [esi+FMUSIC_CHANNEL.portaspeed-2],dl
|
|
donote_xm_portato_end:
|
|
if PORTATOVOLSLIDE_ON
|
|
jmp donote_xm_portavolsl_end
|
|
else
|
|
mov eax,[esi+FMUSIC_CHANNEL.period-2]
|
|
and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER_OR_FRQ
|
|
mov [esi+FMUSIC_CHANNEL.portatarget-2],eax
|
|
ret
|
|
endif
|
|
endif
|
|
if PORTATOVOLSLIDE_ON
|
|
S1_C5:
|
|
jz donote_xm_portavolsl_end
|
|
mov [esi+FMUSIC_CHANNEL.volslide-2],dl
|
|
donote_xm_portavolsl_end:
|
|
mov eax,[esi+FMUSIC_CHANNEL.period-2]
|
|
and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER_OR_FRQ
|
|
mov [esi+FMUSIC_CHANNEL.portatarget-2],eax
|
|
ret
|
|
endif
|
|
if VIBRATO_ON
|
|
S1_C4:
|
|
shr edx,4
|
|
jz donote_vib_x_ok
|
|
mov [esi+FMUSIC_CHANNEL.vibspeed-2],dl
|
|
donote_vib_x_ok:
|
|
test ebx,ebx
|
|
jz donote_vib_y_ok
|
|
mov BYTE PTR [esi+FMUSIC_CHANNEL.vibdepth-2],bl
|
|
donote_vib_y_ok:
|
|
if VIBRATOVOLSLIDE_ON
|
|
xor eax,eax
|
|
else
|
|
; cptr+2 : ESI
|
|
jmp Vibrato
|
|
endif
|
|
endif
|
|
if VIBRATOVOLSLIDE_ON
|
|
S1_C6:
|
|
jz donote_xm_vibvolsl_end
|
|
mov [esi+FMUSIC_CHANNEL.volslide-2],dl
|
|
donote_xm_vibvolsl_end:
|
|
; cptr+2 : ESI
|
|
jmp Vibrato
|
|
endif
|
|
if TREMOLO_ON
|
|
S1_C7:
|
|
shr edx,4
|
|
jz donote_trem_x_ok
|
|
mov [esi+FMUSIC_CHANNEL.tremolospeed-2],dl
|
|
donote_trem_x_ok:
|
|
test ebx,ebx
|
|
jz donote_trem_y_ok
|
|
mov [esi+FMUSIC_CHANNEL.tremolodepth-2],bl
|
|
donote_trem_y_ok:
|
|
ret
|
|
endif
|
|
if SETPANPOSITION_ON
|
|
if PANSLIDE_ON
|
|
else
|
|
S1_C8:
|
|
mov [esi+FMUSIC_CHANNEL.pan-2],edx
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
|
|
ret
|
|
endif
|
|
endif
|
|
if SETSAMPLEOFFSET_ON
|
|
S1_C9:
|
|
shl edx,8
|
|
jz donote_soffset_ok
|
|
mov [esi+FMUSIC_CHANNEL.sampleoffset-2],edx
|
|
donote_soffset_ok:
|
|
mov ecx,[ebp+donote_sptr]
|
|
mov edx,[ecx+FSOUND_SAMPLE.loopstart]
|
|
add edx,[ecx+FSOUND_SAMPLE.looplen]
|
|
mov eax,[esi+FMUSIC_CHANNEL.sampleoffset-2]
|
|
cmp eax,edx
|
|
mov ecx,[esi+FMUSIC_CHANNEL.cptr-2]
|
|
jb donote_set_offset
|
|
xor eax,eax
|
|
and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER
|
|
mov [ecx+FSOUND_CHANNEL.mixpos],eax
|
|
mov [ecx+FSOUND_CHANNEL.mixposlo],eax
|
|
donote_set_offset:
|
|
mov [ecx+FSOUND_CHANNEL.fsampleoffset],eax
|
|
ret
|
|
endif
|
|
if VOLUMESLIDE_ON
|
|
S1_C10:
|
|
jz donote_volslide_ok
|
|
mov [esi+FMUSIC_CHANNEL.volslide-2],dl
|
|
donote_volslide_ok:
|
|
ret
|
|
endif
|
|
if PATTERNJUMP_ON
|
|
S1_C11:
|
|
mov eax,[ebp+var_mod]
|
|
and DWORD PTR [eax+FMUSIC_MODULE.nextrow-36],0
|
|
mov [eax+FMUSIC_MODULE.nextorder-36],edx
|
|
if PATTERNBREAK_ON
|
|
inc BYTE PTR [ebp+donote_jumpflag]
|
|
donote_set_nextord:
|
|
endif
|
|
movzx ecx,WORD PTR [eax+FMUSIC_MODULE.numorders-36]
|
|
cmp [eax+FMUSIC_MODULE.nextorder-36],ecx
|
|
jl donote_nextorder_ok
|
|
and DWORD PTR [eax+FMUSIC_MODULE.nextorder-36],0
|
|
donote_nextorder_ok:
|
|
ret
|
|
endif
|
|
if PATTERNBREAK_ON
|
|
S1_C13:
|
|
shr edx,4
|
|
lea edx,[edx+edx*4]
|
|
lea ecx,[ebx+edx*2] ; paramx*10+paramy
|
|
mov eax,[ebp+var_mod]
|
|
mov [eax+FMUSIC_MODULE.nextrow-36],ecx
|
|
if PATTERNJUMP_ON
|
|
cmp BYTE PTR [ebp+donote_jumpflag],0
|
|
jne donote_nextorder_ok
|
|
endif
|
|
mov ecx,[eax+FMUSIC_MODULE.order-36]
|
|
inc ecx
|
|
mov [eax+FMUSIC_MODULE.nextorder-36],ecx
|
|
if PATTERNJUMP_ON
|
|
jmp donote_set_nextord
|
|
else
|
|
movzx ecx,WORD PTR [eax+FMUSIC_MODULE.numorders-36]
|
|
cmp [eax+FMUSIC_MODULE.nextorder-36],ecx
|
|
jl donote_jump_pat
|
|
and DWORD PTR [eax+FMUSIC_MODULE.nextorder-36],0
|
|
donote_jump_pat:
|
|
ret
|
|
endif
|
|
endif
|
|
if SETSPEED_ON
|
|
S1_C15:
|
|
cmp dl,20h
|
|
mov ecx,edx
|
|
jae donote_setbpm
|
|
mov eax,[ebp+var_mod]
|
|
mov [eax+FMUSIC_MODULE.speed-36],ecx
|
|
ret
|
|
donote_setbpm:
|
|
; bpm : ECX
|
|
jmp SetBPM
|
|
endif
|
|
if GLOBALVOLSLIDE_ON
|
|
S1_C17:
|
|
jz donote_globalvsl_ok
|
|
mov ecx,[ebp+var_mod]
|
|
mov [ecx+FMUSIC_MODULE.globalvsl-36],dl
|
|
donote_globalvsl_ok:
|
|
ret
|
|
endif
|
|
if SETENVELOPEPOS_ON
|
|
S1_C21:
|
|
test BYTE PTR [ecx+FMUSIC_INSTRUMENT.VOLtype],1
|
|
je donote_envelope_r
|
|
lea ebx,[ecx+FMUSIC_INSTRUMENT.VOLPoints+4]
|
|
; Search and reinterpolate new envelope position
|
|
movzx ecx,BYTE PTR [ecx+FMUSIC_INSTRUMENT.VOLnumpoints]
|
|
xor eax,eax
|
|
cmp dx,[ebx]
|
|
jbe donote_env_endwhile
|
|
donote_envwhile:
|
|
cmp eax,ecx ; if(currpos == iptr->VOLnumpoints) break
|
|
je donote_env_endwhile
|
|
inc eax
|
|
cmp dx,[ebx+eax*4] ; if(current->eparam > iptr->VOLPoints[(currpos+1)<<1]) break
|
|
ja donote_envwhile
|
|
donote_env_endwhile:
|
|
mov [esi+FMUSIC_CHANNEL.envvolpos-2],eax
|
|
; if it is at the last position, abort the envelope and continue last volume
|
|
dec ecx
|
|
cmp eax,ecx
|
|
setnl [esi+FMUSIC_CHANNEL.envvolstopped-2]
|
|
jl donote_env_continue
|
|
movzx eax,WORD PTR [ebx+ecx*4-2]
|
|
mov [esi+FMUSIC_CHANNEL.envvol-2],eax ; cptr->envvol = iptr->VOLPoints[((iptr->VOLnumpoints-1)<<1)+1]
|
|
donote_envelope_r:
|
|
ret
|
|
donote_env_continue:
|
|
mov [esi+FMUSIC_CHANNEL.envvoltick-2],edx
|
|
mov ecx,[ebx+eax*4-4] ; get tick at this point + VOL at this point
|
|
mov edx,ecx
|
|
movzx ecx,cx
|
|
mov [ebp+donote_currtick],ecx
|
|
mov ecx,[ebx+eax*4] ; get tick at next point + VOL at next point
|
|
mov eax,ecx
|
|
movzx ecx,cx
|
|
xor dx,dx
|
|
; interpolate 2 points to find delta step
|
|
sub ecx,[ebp+donote_currtick]
|
|
push edx
|
|
jz donote_no_tickdiff
|
|
xor ax,ax
|
|
sub eax,edx
|
|
cdq
|
|
idiv ecx
|
|
xchg eax,ecx
|
|
donote_no_tickdiff:
|
|
mov [esi+FMUSIC_CHANNEL.envvoldelta-2],ecx
|
|
mov eax,[esi+FMUSIC_CHANNEL.envvoltick-2]
|
|
sub eax,[ebp+donote_currtick]
|
|
imul ecx
|
|
pop edx
|
|
add eax,edx
|
|
mov [esi+FMUSIC_CHANNEL.envvolfrac-2],eax
|
|
sar eax,16
|
|
mov [esi+FMUSIC_CHANNEL.envvol-2],eax
|
|
inc DWORD PTR [esi+FMUSIC_CHANNEL.envvolpos-2]
|
|
ret
|
|
endif
|
|
if PANSLIDE_ON
|
|
S1_C25:
|
|
jz donote_panslide_ok
|
|
mov [esi+FMUSIC_CHANNEL.panslide-2],dl
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
|
|
donote_panslide_ok:
|
|
ret
|
|
endif
|
|
if MULTIRETRIG_ON
|
|
S1_C27:
|
|
jz donote_multiretrig_ok
|
|
shr edx,4
|
|
mov dh,bl
|
|
mov WORD PTR [esi+FMUSIC_CHANNEL.retrigx-2],dx
|
|
donote_multiretrig_ok:
|
|
ret
|
|
endif
|
|
if TREMOR_ON
|
|
S1_C29:
|
|
jz donote_do_tremor
|
|
shr edx,4
|
|
mov dh,bl
|
|
mov WORD PTR [esi+FMUSIC_CHANNEL.tremoron-2],dx
|
|
donote_do_tremor:
|
|
; cptr : ESI
|
|
jmp Tremor
|
|
endif
|
|
if EXTRAFINEPORTA_ON
|
|
S1_C33:
|
|
shr edx,4
|
|
dec edx
|
|
jnz donote_paramx_n1
|
|
test ebx,ebx
|
|
jz donote_paramy_z1
|
|
mov [esi+FMUSIC_CHANNEL.xtraportaup-2],bl
|
|
donote_paramy_z1:
|
|
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.xtraportaup-2]
|
|
sub [esi+FMUSIC_CHANNEL.freq-2],eax
|
|
donote_paramx_n1:
|
|
dec edx
|
|
jnz donote_paramx_n2
|
|
test ebx,ebx
|
|
jz donote_paramy_z2
|
|
mov [esi+FMUSIC_CHANNEL.xtraportadown-2],bl
|
|
donote_paramy_z2:
|
|
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.xtraportadown-2]
|
|
add [esi+FMUSIC_CHANNEL.freq-2],eax
|
|
donote_paramx_n2:
|
|
endif
|
|
S2_r:
|
|
ret
|
|
S1_C14:
|
|
shr edx,4
|
|
dec edx ; skip FMUSIC_XM_SETFILTER
|
|
if FINEPORTAUP_ON
|
|
else
|
|
dec edx
|
|
endif
|
|
if PATTERNDELAY_ON
|
|
cmp dl,13
|
|
else
|
|
if NOTEDELAY_ON
|
|
cmp dl,12
|
|
else
|
|
if FINEVOLUMESLIDE_ON
|
|
cmp dl,10
|
|
else
|
|
if SETPANPOSITION16_ON
|
|
cmp dl,7
|
|
else
|
|
if SETTREMOLOWAVE_ON
|
|
cmp dl,6
|
|
else
|
|
if PATTERNLOOP_ON
|
|
cmp dl,5
|
|
else
|
|
cmp dl,4
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
if FINEPORTAUP_ON
|
|
ja S2_r
|
|
else
|
|
jae S2_r
|
|
endif
|
|
donote_do_special:
|
|
test ebx,ebx
|
|
jmp DWORD PTR [edx*4+S2_TBL]
|
|
S2_TBL:
|
|
if FINEPORTAUP_ON
|
|
dd S2_C1
|
|
endif
|
|
if FINEPORTADOWN_ON
|
|
dd S2_C2
|
|
else
|
|
dd S2_r
|
|
endif
|
|
dd S2_r ; skip FMUSIC_XM_SETGLISSANDO
|
|
if SETVIBRATOWAVE_ON
|
|
dd S2_C4
|
|
else
|
|
dd S2_r
|
|
endif
|
|
if SETFINETUNE_ON
|
|
dd S2_C5
|
|
else
|
|
dd S2_r
|
|
endif
|
|
if PATTERNDELAY_ON
|
|
if PATTERNLOOP_ON
|
|
dd S2_C6
|
|
else
|
|
dd S2_r
|
|
endif
|
|
if SETTREMOLOWAVE_ON
|
|
dd S2_C7
|
|
else
|
|
dd S2_r
|
|
endif
|
|
if SETPANPOSITION16_ON
|
|
dd S2_C8
|
|
else
|
|
dd S2_r
|
|
endif
|
|
dd S2_r ; skip FMUSIC_XM_RETRIG
|
|
if FINEVOLUMESLIDE_ON
|
|
dd S2_C10
|
|
dd S2_C11
|
|
else
|
|
dd S2_r
|
|
dd S2_r
|
|
endif
|
|
dd S2_r ; skip FMUSIC_XM_NOTECUT
|
|
if NOTEDELAY_ON
|
|
dd S2_C13
|
|
else
|
|
dd S2_r
|
|
endif
|
|
dd S2_C14
|
|
else
|
|
if NOTEDELAY_ON
|
|
if PATTERNLOOP_ON
|
|
dd S2_C6
|
|
else
|
|
dd S2_r
|
|
endif
|
|
if SETTREMOLOWAVE_ON
|
|
dd S2_C7
|
|
else
|
|
dd S2_r
|
|
endif
|
|
if SETPANPOSITION16_ON
|
|
dd S2_C8
|
|
else
|
|
dd S2_r
|
|
endif
|
|
dd S2_r ; skip FMUSIC_XM_RETRIG
|
|
if FINEVOLUMESLIDE_ON
|
|
dd S2_C10
|
|
dd S2_C11
|
|
else
|
|
dd S2_r
|
|
dd S2_r
|
|
endif
|
|
dd S2_r
|
|
dd S2_C13
|
|
else
|
|
if FINEVOLUMESLIDE_ON
|
|
if PATTERNLOOP_ON
|
|
dd S2_C6
|
|
else
|
|
dd S2_r
|
|
endif
|
|
if SETTREMOLOWAVE_ON
|
|
dd S2_C7
|
|
else
|
|
dd S2_r
|
|
endif
|
|
if SETPANPOSITION16_ON
|
|
dd S2_C8
|
|
else
|
|
dd S2_r
|
|
endif
|
|
dd S2_r
|
|
dd S2_C10
|
|
dd S2_C11
|
|
else
|
|
if SETPANPOSITION16_ON
|
|
if PATTERNLOOP_ON
|
|
dd S2_C6
|
|
else
|
|
dd S2_r
|
|
endif
|
|
if SETTREMOLOWAVE_ON
|
|
dd S2_C7
|
|
else
|
|
dd S2_r
|
|
endif
|
|
dd S2_C8
|
|
else
|
|
if SETTREMOLOWAVE_ON
|
|
if PATTERNLOOP_ON
|
|
dd S2_C6
|
|
else
|
|
dd S2_r
|
|
endif
|
|
dd S2_C7
|
|
else
|
|
if PATTERNLOOP_ON
|
|
dd S2_C6
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
if FINEPORTAUP_ON
|
|
S2_C1:
|
|
jz donote_finepup_ok
|
|
mov [esi+FMUSIC_CHANNEL.fineportaup-2],bl
|
|
donote_finepup_ok:
|
|
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.fineportaup-2]
|
|
shl eax,2
|
|
sub [esi+FMUSIC_CHANNEL.freq-2],eax
|
|
ret
|
|
endif
|
|
if FINEPORTADOWN_ON
|
|
S2_C2:
|
|
jz donote_finepdown_ok
|
|
mov [esi+FMUSIC_CHANNEL.fineportadown-2],bl
|
|
donote_finepdown_ok:
|
|
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.fineportadown-2]
|
|
shl eax,2
|
|
add [esi+FMUSIC_CHANNEL.freq-2],eax
|
|
ret
|
|
endif
|
|
if SETVIBRATOWAVE_ON
|
|
S2_C4:
|
|
and BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],0F0h
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],bl
|
|
ret
|
|
endif
|
|
if SETFINETUNE_ON
|
|
S2_C5:
|
|
mov eax,[ebp+donote_sptr]
|
|
mov [eax+FSOUND_SAMPLE.finetune],bl
|
|
ret
|
|
endif
|
|
if PATTERNLOOP_ON
|
|
S2_C6:
|
|
jnz donote_not_paramy
|
|
mov eax,[ebp+var_mod]
|
|
mov eax,[eax+FMUSIC_MODULE.row-36]
|
|
mov [esi+FMUSIC_CHANNEL.patlooprow-2],eax
|
|
ret
|
|
donote_not_paramy:
|
|
mov cl,[esi+FMUSIC_CHANNEL.patloopno-2]
|
|
dec cl
|
|
jns donote_patloopno_ok
|
|
mov ecx,ebx
|
|
donote_patloopno_ok:
|
|
mov [esi+FMUSIC_CHANNEL.patloopno-2],cl
|
|
jz donote_patloopno_end
|
|
mov eax,[esi+FMUSIC_CHANNEL.patlooprow-2]
|
|
mov ecx,[ebp+var_mod]
|
|
mov [ecx+FMUSIC_MODULE.nextrow-36],eax
|
|
donote_patloopno_end:
|
|
ret
|
|
endif
|
|
if SETTREMOLOWAVE_ON
|
|
S2_C7:
|
|
and BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],0Fh
|
|
shl ebx,4
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],bl
|
|
ret
|
|
endif
|
|
if SETPANPOSITION16_ON
|
|
S2_C8:
|
|
shl ebx,4
|
|
mov [esi+FMUSIC_CHANNEL.pan-2],ebx
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
|
|
ret
|
|
endif
|
|
if FINEVOLUMESLIDE_ON
|
|
S2_C10:
|
|
neg ebx
|
|
S2_C11:
|
|
jz donote_finevols_ok
|
|
mov [esi+FMUSIC_CHANNEL.finevslup-2],bl
|
|
donote_finevols_ok:
|
|
movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.finevslup-2]
|
|
sub [esi+FMUSIC_CHANNEL.volume-2],eax
|
|
ret
|
|
endif
|
|
if NOTEDELAY_ON
|
|
S2_C13:
|
|
mov eax,[ebp+donote_oldfreq]
|
|
mov edx,[ebp+donote_currtick]
|
|
mov [esi+FMUSIC_CHANNEL.freq-2],eax
|
|
mov eax,[ebp+donote_oldpan]
|
|
mov [esi+FMUSIC_CHANNEL.pan-2],eax
|
|
mov BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],0
|
|
if SETVOLUME_ON
|
|
else
|
|
mov [esi+FMUSIC_CHANNEL.volume-2],edx
|
|
ret
|
|
endif
|
|
endif
|
|
if SETVOLUME_ON
|
|
S1_C12:
|
|
mov [esi+FMUSIC_CHANNEL.volume-2],edx
|
|
ret
|
|
endif
|
|
if PATTERNDELAY_ON
|
|
S2_C14:
|
|
mov ecx,[ebp+var_mod]
|
|
imul ebx,DWORD PTR [ecx+FMUSIC_MODULE.speed-36]
|
|
mov [ecx+FMUSIC_MODULE.patterndelay-36],ebx
|
|
ret
|
|
endif
|
|
|
|
DoEffs:
|
|
; mod+36 = ESI
|
|
; var_mod equ -4
|
|
doeff_current equ -8
|
|
; Point our note pointer to the correct pattern buffer, and to the
|
|
; correct offset in this buffer indicated by row and number of channels
|
|
mov eax,[esi+FMUSIC_MODULE.order-36]
|
|
push ebp
|
|
mov bl,[eax+esi+FMUSIC_MODULE.orderlist-36]
|
|
mov eax,[esi+FMUSIC_MODULE.row-36]
|
|
mul DWORD PTR [esi+FMUSIC_MODULE.numchannels-36]
|
|
lea eax,[eax+eax*4] ; x SIZE FMUSIC_NOTE
|
|
mov ebp,esp
|
|
; mod->pattern[mod->orderlist[mod->order]].data+(mod->row*mod->numchannels)
|
|
add eax,[ecx+ebx*FMUSIC_PATTERN_size+FMUSIC_PATTERN.data]
|
|
push esi ; -> var_mod
|
|
push eax ; -> doeff_current
|
|
mov eax,[esi+FMUSIC_MODULE.numchannels-36]
|
|
shl eax,7 ; x FMUSIC_CHANNEL_size
|
|
push esi
|
|
mov esi,[esi+FMUSIC_MODULE.uFMOD_Ch-36]
|
|
inc esi
|
|
inc esi
|
|
add eax,esi
|
|
doeff_for_channels:
|
|
push eax
|
|
movzx edi,BYTE PTR [esi+FMUSIC_CHANNEL.inst-2]
|
|
mov edx,[ebp+var_mod]
|
|
imul edi,FMUSIC_INSTRUMENT_size
|
|
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.note-2]
|
|
add edi,[edx+FMUSIC_MODULE.instrument-36]
|
|
cdq
|
|
mov al,[eax+edi+FMUSIC_INSTRUMENT.keymap]
|
|
cmp al,16
|
|
jae doeff_set_sptr
|
|
mov edx,[edi+eax*4+FMUSIC_INSTRUMENT.sample]
|
|
doeff_set_sptr:
|
|
test edx,edx
|
|
jnz doeff_valid_sptr
|
|
mov edx,OFFSET DummySamp
|
|
doeff_valid_sptr:
|
|
xor ebx,ebx
|
|
if INSTRUMENTVIBRATO_ON
|
|
push edi ; iptr
|
|
endif
|
|
push edx ; sptr
|
|
mov [esi+FMUSIC_CHANNEL.voldelta-2],ebx
|
|
mov [esi+FMUSIC_CHANNEL.freqdelta-2],ebx
|
|
mov [esi+FMUSIC_CHANNEL.notectrl-2],bl
|
|
; PROCESS ENVELOPES
|
|
if VOLUMEENVELOPE_ON
|
|
test BYTE PTR [edi+FMUSIC_INSTRUMENT.VOLtype],1
|
|
je doeff_no_voltype
|
|
mov al,FMUSIC_VOLUME
|
|
mov ecx,edi
|
|
; cptr+2 : ESI
|
|
; env_iptr : ECX
|
|
; control : AL
|
|
call Envelope
|
|
doeff_no_voltype:
|
|
endif
|
|
if PANENVELOPE_ON
|
|
test BYTE PTR [edi+FMUSIC_INSTRUMENT.PANtype],1
|
|
je doeff_no_pantype
|
|
mov al,FMUSIC_PAN
|
|
mov ecx,edi
|
|
; cptr+2 : ESI
|
|
; env_iptr : ECX
|
|
; control : AL
|
|
call Envelope
|
|
doeff_no_pantype:
|
|
endif
|
|
; PROCESS VOLUME FADEOUT
|
|
cmp [esi+FMUSIC_CHANNEL.keyoff-2],bl
|
|
je doeff_fadevol_ok
|
|
movzx eax,WORD PTR [edi+FMUSIC_INSTRUMENT.VOLfade]
|
|
sub [esi+FMUSIC_CHANNEL.fadeoutvol-2],eax
|
|
jns doeff_fadevol_ns
|
|
mov [esi+FMUSIC_CHANNEL.fadeoutvol-2],ebx
|
|
doeff_fadevol_ns:
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
doeff_fadevol_ok:
|
|
if VOLUMEBYTE_ON
|
|
mov eax,[ebp+doeff_current]
|
|
movzx eax,BYTE PTR [eax+FMUSIC_NOTE.uvolume]
|
|
mov ecx,eax
|
|
shr eax,4
|
|
and cl,0Fh
|
|
sub al,6
|
|
jz doeff_case_vol6
|
|
dec eax
|
|
jz doeff_case_vol7
|
|
if VIBRATO_ON
|
|
sub al,4
|
|
jz doeff_case_volB
|
|
dec eax
|
|
dec eax
|
|
else
|
|
sub al,6
|
|
endif
|
|
jz doeff_case_volD
|
|
dec eax
|
|
if PORTATO_ON
|
|
jz doeff_case_volE
|
|
dec eax
|
|
jnz doeff_volbyte_end
|
|
; cptr+2 : ESI
|
|
call Portamento
|
|
jmp doeff_volbyte_end
|
|
else
|
|
jnz doeff_volbyte_end
|
|
endif
|
|
doeff_case_volE:
|
|
neg ecx
|
|
doeff_case_volD:
|
|
sub [esi+FMUSIC_CHANNEL.pan-2],ecx
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
|
|
jmp doeff_volbyte_end
|
|
if VIBRATO_ON
|
|
doeff_case_volB:
|
|
mov [esi+FMUSIC_CHANNEL.vibdepth-2],cl
|
|
; cptr+2 : ESI
|
|
call Vibrato
|
|
jmp doeff_volbyte_end
|
|
endif
|
|
doeff_case_vol6:
|
|
neg ecx
|
|
doeff_case_vol7:
|
|
add [esi+FMUSIC_CHANNEL.volume-2],ecx
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
doeff_volbyte_end:
|
|
endif ; VOLUMEBYTE_ON
|
|
mov edx,[ebp+doeff_current]
|
|
movzx ebx,BYTE PTR [edx+FMUSIC_NOTE.eparam]
|
|
mov ecx,ebx
|
|
and ebx,0Fh ; grab the effect parameter y
|
|
movzx eax,BYTE PTR [edx+FMUSIC_NOTE.effect]
|
|
shr cl,4 ; grab the effect parameter x
|
|
if ARPEGGIO_ON
|
|
else
|
|
dec eax
|
|
endif
|
|
if TREMOR_ON
|
|
cmp al,29
|
|
else
|
|
if MULTIRETRIG_ON
|
|
cmp al,27
|
|
else
|
|
if PANSLIDE_ON
|
|
cmp al,25
|
|
else
|
|
if GLOBALVOLSLIDE_ON
|
|
cmp al,17
|
|
else
|
|
if RETRIG_ON
|
|
cmp al,14
|
|
else
|
|
if NOTECUT_ON
|
|
cmp al,14
|
|
else
|
|
if NOTEDELAY_ON
|
|
cmp al,14
|
|
else
|
|
cmp al,10
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
if ARPEGGIO_ON
|
|
ja doeff_s3_brk
|
|
else
|
|
jae doeff_s3_brk
|
|
endif
|
|
call DWORD PTR [eax*4+S3_TBL]
|
|
doeff_s3_brk:
|
|
; cptr+2 : ESI
|
|
call DoFlags
|
|
sub esi,-(FMUSIC_CHANNEL_size)
|
|
pop eax
|
|
add DWORD PTR [ebp+doeff_current],FMUSIC_NOTE_size
|
|
cmp esi,eax
|
|
jl doeff_for_channels
|
|
pop esi
|
|
doeff_R:
|
|
leave
|
|
S3_r:
|
|
ret
|
|
S3_TBL:
|
|
if ARPEGGIO_ON
|
|
dd S3_C0
|
|
endif
|
|
if PORTAUP_ON
|
|
dd S3_C1
|
|
else
|
|
dd S3_r
|
|
endif
|
|
if PORTADOWN_ON
|
|
dd S3_C2
|
|
else
|
|
dd S3_r
|
|
endif
|
|
if PORTATO_ON
|
|
; cptr+2 : ESI
|
|
dd Portamento
|
|
else
|
|
dd S3_r
|
|
endif
|
|
if VIBRATO_ON
|
|
; cptr+2 : ESI
|
|
dd Vibrato
|
|
else
|
|
dd S3_r
|
|
endif
|
|
if PORTATOVOLSLIDE_ON
|
|
dd S3_C5
|
|
else
|
|
dd S3_r
|
|
endif
|
|
if VIBRATOVOLSLIDE_ON
|
|
dd S3_C6
|
|
else
|
|
dd S3_r
|
|
endif
|
|
if TREMOLO_ON
|
|
; cptr+2 : ESI
|
|
dd Tremolo
|
|
else
|
|
dd S3_r
|
|
endif
|
|
dd S3_r ; skip FMUSIC_XM_SETPANPOSITION
|
|
dd S3_r ; skip FMUSIC_XM_SETSAMPLEOFFSET
|
|
if VOLUMESLIDE_ON
|
|
dd S3_C10
|
|
else
|
|
dd S3_r
|
|
endif
|
|
if TREMOR_ON
|
|
dd S3_r ; skip FMUSIC_XM_PATTERNJUMP
|
|
dd S3_r ; slip FMUSIC_XM_SETVOLUME
|
|
dd S3_r ; skip FMUSIC_XM_PATTERNBREAK
|
|
dd S3_C14
|
|
dd S3_r ; skip FMUSIC_XM_SETSPEED
|
|
dd S3_r ; skip FMUSIC_XM_SETGLOBALVOLUME
|
|
if GLOBALVOLSLIDE_ON
|
|
dd S3_C17
|
|
else
|
|
dd S3_r
|
|
endif
|
|
dd S3_r ; unassigned effect ordinal [18]
|
|
dd S3_r ; unassigned effect ordinal [19]
|
|
dd S3_r ; skip FMUSIC_XM_KEYOFF
|
|
dd S3_r ; skip FMUSIC_XM_SETENVELOPEPOS
|
|
dd S3_r ; unassigned effect ordinal [22]
|
|
dd S3_r ; unassigned effect ordinal [23]
|
|
dd S3_r ; unassigned effect ordinal [24]
|
|
if PANSLIDE_ON
|
|
dd S3_C25
|
|
else
|
|
dd S3_r
|
|
endif
|
|
dd S3_r ; unassigned effect ordinal [26]
|
|
if MULTIRETRIG_ON
|
|
dd S3_C27
|
|
else
|
|
dd S3_r
|
|
endif
|
|
dd S3_r ; unassigned effect ordinal [28]
|
|
; case FMUSIC_XM_TREMOR
|
|
; cptr : ESI
|
|
dd Tremor
|
|
else
|
|
if MULTIRETRIG_ON
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_C14
|
|
dd S3_r
|
|
dd S3_r
|
|
if GLOBALVOLSLIDE_ON
|
|
dd S3_C17
|
|
else
|
|
dd S3_r
|
|
endif
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
if PANSLIDE_ON
|
|
dd S3_C25
|
|
else
|
|
dd S3_r
|
|
endif
|
|
dd S3_r
|
|
dd S3_C27
|
|
else
|
|
if PANSLIDE_ON
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_C14
|
|
dd S3_r
|
|
dd S3_r
|
|
if GLOBALVOLSLIDE_ON
|
|
dd S3_C17
|
|
else
|
|
dd S3_r
|
|
endif
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_C25
|
|
else
|
|
if GLOBALVOLSLIDE_ON
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_C14
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_C17
|
|
else
|
|
if RETRIG_ON
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_C14
|
|
else
|
|
if NOTECUT_ON
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_C14
|
|
else
|
|
if NOTEDELAY_ON
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_r
|
|
dd S3_C14
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
|
|
endif
|
|
endif
|
|
if VIBRATOVOLSLIDE_ON
|
|
S3_C6:
|
|
; cptr+2 : ESI
|
|
call Vibrato
|
|
if VOLUMESLIDE_ON
|
|
if PORTATOVOLSLIDE_ON
|
|
jmp S3_C10
|
|
endif
|
|
else
|
|
mov cl,[esi+FMUSIC_CHANNEL.volslide-2]
|
|
mov eax,ecx
|
|
and eax,0Fh
|
|
shr ecx,4
|
|
jz doeff_volslide_ok
|
|
; Slide up takes precedence over down
|
|
xchg eax,ecx
|
|
neg eax
|
|
doeff_volslide_ok:
|
|
sub [esi+FMUSIC_CHANNEL.volume-2],eax
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
ret
|
|
endif
|
|
endif
|
|
if PORTATOVOLSLIDE_ON
|
|
S3_C5:
|
|
; cptr+2 : ESI
|
|
call Portamento
|
|
if VOLUMESLIDE_ON
|
|
xor ecx,ecx
|
|
else
|
|
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.volslide-2]
|
|
mov eax,ecx
|
|
and eax,0Fh
|
|
shr ecx,4
|
|
jz doeff_volslide_ok
|
|
; Slide up takes precedence over down
|
|
xchg eax,ecx
|
|
neg eax
|
|
doeff_volslide_ok:
|
|
sub [esi+FMUSIC_CHANNEL.volume-2],eax
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
ret
|
|
endif
|
|
endif
|
|
if VOLUMESLIDE_ON
|
|
S3_C10:
|
|
mov cl,[esi+FMUSIC_CHANNEL.volslide-2]
|
|
mov eax,ecx
|
|
and eax,0Fh
|
|
shr ecx,4
|
|
jz doeff_volslide_ok
|
|
; Slide up takes precedence over down
|
|
xchg eax,ecx
|
|
neg eax
|
|
doeff_volslide_ok:
|
|
sub [esi+FMUSIC_CHANNEL.volume-2],eax
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
ret
|
|
endif
|
|
if PORTADOWN_ON
|
|
S3_C2:
|
|
mov al,[esi+FMUSIC_CHANNEL.portaupdown-2]
|
|
DoFreqSlide:
|
|
mov ecx,[esi+FMUSIC_CHANNEL.freq-2]
|
|
lea ecx,[ecx+eax*4]
|
|
cmp ecx,1
|
|
jge DoFreqSlide_ok
|
|
push 1
|
|
pop ecx
|
|
DoFreqSlide_ok:
|
|
mov [esi+FMUSIC_CHANNEL.freq-2],ecx
|
|
and DWORD PTR [esi+FMUSIC_CHANNEL.freqdelta-2],0
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
|
|
ret
|
|
endif
|
|
if PORTAUP_ON
|
|
S3_C1:
|
|
mov al,[esi+FMUSIC_CHANNEL.portaupdown-2]
|
|
if PORTADOWN_ON
|
|
neg eax
|
|
jmp DoFreqSlide
|
|
else
|
|
shl eax,2
|
|
mov ecx,[esi+FMUSIC_CHANNEL.freq-2]
|
|
sub ecx,eax
|
|
cmp ecx,1
|
|
jge DoFreqSlide_ok
|
|
push 1
|
|
pop ecx
|
|
DoFreqSlide_ok:
|
|
mov [esi+FMUSIC_CHANNEL.freq-2],ecx
|
|
and DWORD PTR [esi+FMUSIC_CHANNEL.freqdelta-2],0
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
|
|
ret
|
|
endif
|
|
endif
|
|
if ARPEGGIO_ON
|
|
S3_C0:
|
|
cmp BYTE PTR [edx+FMUSIC_NOTE.eparam],ch
|
|
jbe doeff_arpeggio_ok
|
|
mov eax,[ebp+var_mod]
|
|
mov eax,[eax+FMUSIC_MODULE.tick-36]
|
|
push 3
|
|
cdq
|
|
pop edi
|
|
idiv edi
|
|
dec edx
|
|
jz doeff_arpeg_c1
|
|
dec edx
|
|
jne doeffs_enable_freq
|
|
mov ecx,ebx
|
|
doeff_arpeg_c1:
|
|
mov eax,[ebp+var_mod]
|
|
test BYTE PTR [eax+FMUSIC_MODULE.flags-36],1
|
|
je doeffs_flagsn1
|
|
doeffs_arpeggio_freqd:
|
|
shl ecx,6
|
|
mov [esi+FMUSIC_CHANNEL.freqdelta-2],ecx
|
|
if AMIGAPERIODS_ON
|
|
jmp doeffs_enable_freq
|
|
endif
|
|
doeffs_flagsn1:
|
|
if AMIGAPERIODS_ON
|
|
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.realnote-2]
|
|
mov edi,eax
|
|
add eax,ecx ; note : EAX
|
|
mov ecx,[esp+4] ; [sptr] : ECX
|
|
; ESI != 0
|
|
call AmigaPeriod
|
|
xchg eax,edi ; note : EAX
|
|
mov ecx,[esp+4] ; [sptr] : ECX
|
|
; ESI != 0
|
|
call AmigaPeriod
|
|
sub edi,eax
|
|
mov [esi+FMUSIC_CHANNEL.freqdelta-2],edi
|
|
endif
|
|
doeffs_enable_freq:
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
|
|
doeff_arpeggio_ok:
|
|
ret
|
|
endif
|
|
if MULTIRETRIG_ON
|
|
S3_C27:
|
|
mov cl,[esi+FMUSIC_CHANNEL.retrigy-2]
|
|
test ecx,ecx
|
|
jz doeff_multiretrig_ok
|
|
mov eax,[ebp+var_mod]
|
|
mov eax,[eax+FMUSIC_MODULE.tick-36]
|
|
cdq
|
|
idiv ecx
|
|
test edx,edx
|
|
jnz doeff_multiretrig_ok
|
|
mov cl,[esi+FMUSIC_CHANNEL.retrigx-2]
|
|
and ecx,0Fh
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_TRIGGER
|
|
dec ecx
|
|
mov eax,[esi+FMUSIC_CHANNEL.volume-2]
|
|
js doeff_multiretrig_ok
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
call DWORD PTR [ecx*4+S4_TBL]
|
|
mov [esi+FMUSIC_CHANNEL.volume-2],eax
|
|
S4_C2:
|
|
dec eax
|
|
S4_C1:
|
|
dec eax
|
|
doeff_multiretrig_ok:
|
|
ret
|
|
S4_C5:
|
|
sub eax,8
|
|
S4_C4:
|
|
sub eax,4
|
|
S4_C3:
|
|
sub eax,4
|
|
ret
|
|
S4_C6:
|
|
shl eax,1
|
|
push 3
|
|
cdq
|
|
pop ecx
|
|
idiv ecx
|
|
ret
|
|
S4_C14:
|
|
lea eax,[eax+eax*2]
|
|
S4_C7:
|
|
sar eax,1
|
|
ret
|
|
S4_C10:
|
|
inc eax
|
|
S4_C9:
|
|
inc eax
|
|
ret
|
|
S4_C13:
|
|
add eax,8
|
|
S4_C12:
|
|
add eax,4
|
|
S4_C11:
|
|
add eax,4
|
|
ret
|
|
S4_C15:
|
|
shl eax,1
|
|
S4_r:
|
|
ret
|
|
S4_TBL:
|
|
dd S4_C1
|
|
dd S4_C2
|
|
dd S4_C3
|
|
dd S4_C4
|
|
dd S4_C5
|
|
dd S4_C6
|
|
dd S4_C7
|
|
dd S4_r
|
|
dd S4_C9
|
|
dd S4_C10
|
|
dd S4_C11
|
|
dd S4_C12
|
|
dd S4_C13
|
|
dd S4_C14
|
|
dd S4_C15
|
|
endif
|
|
if PANSLIDE_ON
|
|
S3_C25:
|
|
mov cl,[esi+FMUSIC_CHANNEL.panslide-2]
|
|
mov eax,ecx
|
|
and eax,0Fh
|
|
mov edx,[esi+FMUSIC_CHANNEL.pan-2]
|
|
shr ecx,4
|
|
; Slide right takes precedence over left
|
|
jnz doeff_pan_slide_right
|
|
sub edx,eax
|
|
jns doeff_panslide_ok
|
|
mov edx,ecx
|
|
jmp doeff_panslide_ok
|
|
doeff_pan_slide_right:
|
|
add ecx,edx
|
|
cdq
|
|
dec dl ; edx = 255
|
|
cmp ecx,edx
|
|
jg doeff_panslide_ok
|
|
mov edx,ecx
|
|
doeff_panslide_ok:
|
|
if SETPANPOSITION_ON
|
|
S1_C8:
|
|
endif
|
|
mov [esi+FMUSIC_CHANNEL.pan-2],edx
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
|
|
ret
|
|
endif
|
|
if GLOBALVOLSLIDE_ON
|
|
S3_C17:
|
|
mov ecx,[ebp+var_mod]
|
|
mov edx,[ecx+FMUSIC_MODULE.globalvolume-36]
|
|
mov al,[ecx+FMUSIC_MODULE.globalvsl-36]
|
|
test al,0F0h
|
|
; Slide up takes precedence over down
|
|
jnz doeff_gvsl_slide_up
|
|
and eax,0Fh
|
|
sub edx,eax
|
|
jns set_global_vol
|
|
cdq
|
|
xor eax,eax
|
|
doeff_gvsl_slide_up:
|
|
shr eax,4
|
|
add edx,eax
|
|
set_global_vol:
|
|
if SETGLOBALVOLUME_ON
|
|
else
|
|
cmp edx,64
|
|
jle doeff_setglobalvol
|
|
push 64
|
|
pop edx
|
|
doeff_setglobalvol:
|
|
mov [ecx+FMUSIC_MODULE.globalvolume-36],edx
|
|
ret
|
|
endif
|
|
endif
|
|
if SETGLOBALVOLUME_ON
|
|
S1_C16:
|
|
cmp edx,64
|
|
mov ecx,[ebp+var_mod]
|
|
jle do_setglobalvol
|
|
push 64
|
|
pop edx
|
|
do_setglobalvol:
|
|
mov [ecx+FMUSIC_MODULE.globalvolume-36],edx
|
|
ret
|
|
endif
|
|
S3_C14:
|
|
if RETRIG_ON
|
|
cmp cl,FMUSIC_XM_RETRIG
|
|
je doeff_do_retrig
|
|
endif
|
|
if NOTECUT_ON
|
|
sub cl,FMUSIC_XM_NOTECUT
|
|
jz doeff_do_notecut
|
|
endif
|
|
if NOTEDELAY_ON
|
|
if NOTECUT_ON
|
|
dec cl
|
|
else
|
|
cmp cl,FMUSIC_XM_NOTEDELAY
|
|
endif
|
|
jne doeff_special_r
|
|
mov ecx,[ebp+var_mod]
|
|
xor eax,eax
|
|
cmp [ecx+FMUSIC_MODULE.tick-36],ebx
|
|
jne doeff_notectrl_z
|
|
mov edx,[esp+4]
|
|
mov DWORD PTR [esi+FMUSIC_CHANNEL.fadeoutvol-2],65536
|
|
movzx edx,BYTE PTR [edx+FSOUND_SAMPLE.defvol]
|
|
lea ecx,[eax+9]
|
|
mov [esi+FMUSIC_CHANNEL.volume-2],edx
|
|
mov edx,[esi+FMUSIC_CHANNEL.envvol-2]
|
|
lea edi,[esi+FMUSIC_CHANNEL.envvoltick-2]
|
|
cmp ecx,edx
|
|
sbb edx,edx
|
|
and edx,64
|
|
mov [esi+FMUSIC_CHANNEL.envvol-2],edx
|
|
; memset(&cptr->envvoltick,0,36)
|
|
rep stosd
|
|
; Retrigger tremolo and vibrato waveforms
|
|
mov cl,[esi+FMUSIC_CHANNEL.wavecontrol-2]
|
|
cmp cl,4Fh
|
|
jge z2_tremolopos_ok
|
|
mov BYTE PTR [esi+FMUSIC_CHANNEL.tremolopos-2],al ; = 0
|
|
z2_tremolopos_ok:
|
|
test cl,0Ch
|
|
jnz z2_vibpos_ok
|
|
mov BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2],al ; = 0
|
|
z2_vibpos_ok:
|
|
mov eax,[esi+FMUSIC_CHANNEL.period-2]
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOL_OR_FREQ_OR_TR
|
|
mov [esi+FMUSIC_CHANNEL.freq-2],eax
|
|
if VOLUMEBYTE_ON
|
|
mov eax,[ebp+doeff_current]
|
|
movzx edx,BYTE PTR [eax+FMUSIC_NOTE.uvolume]
|
|
; volume : EDX
|
|
; cptr : ESI
|
|
jmp VolByte
|
|
else
|
|
ret
|
|
endif
|
|
doeff_notectrl_z:
|
|
mov BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],al
|
|
doeff_special_r:
|
|
endif
|
|
ret
|
|
if NOTECUT_ON
|
|
doeff_do_notecut:
|
|
mov ecx,[ebp+var_mod]
|
|
cmp [ecx+FMUSIC_MODULE.tick-36],ebx
|
|
jne doeff_notecut_ok
|
|
and DWORD PTR [esi+FMUSIC_CHANNEL.volume-2],0
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
doeff_notecut_ok:
|
|
ret
|
|
endif
|
|
if RETRIG_ON
|
|
doeff_do_retrig:
|
|
test ebx,ebx
|
|
jz doeff_retrig_ok
|
|
mov eax,[ebp+var_mod]
|
|
mov eax,[eax+FMUSIC_MODULE.tick-36]
|
|
cdq
|
|
idiv ebx
|
|
test edx,edx
|
|
jne doeff_retrig_ok
|
|
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOL_OR_FREQ_OR_TR
|
|
doeff_retrig_ok:
|
|
ret
|
|
endif
|
|
|
|
; DESCRIPTION: Process sample flags
|
|
DoFlags:
|
|
; cptr+2 - ESI
|
|
flags_iptr equ 16
|
|
flags_sptr equ 12
|
|
mov ebx,esi
|
|
push esi
|
|
push edi
|
|
if INSTRUMENTVIBRATO_ON
|
|
; THIS GETS ADDED TO PREVIOUS FREQDELTAS
|
|
mov esi,[esp+flags_iptr]
|
|
xor eax,eax
|
|
movzx edx,BYTE PTR [esi+FMUSIC_INSTRUMENT.VIBtype]
|
|
lea edi,[ebx+FMUSIC_CHANNEL.ivibpos-2]
|
|
dec edx ; switch(iptr->VIBtype)
|
|
js ivib_case_0
|
|
mov al,128
|
|
jz ivib_case_1
|
|
dec edx
|
|
jz ivib_case_2
|
|
; case 3 / default
|
|
mov dl,-128 ; -128 = 384 on a 1byte scope
|
|
sub edx,[edi]
|
|
trim:
|
|
movzx edx,dl
|
|
sub eax,edx
|
|
sar eax,1 ; delta = (128-((384-cptr->ivibpos)&0xFF))>>1 (case 3)
|
|
; delta = (128-((cptr->ivibpos+128)&0xFF))>>1 (case 2)
|
|
jmp ivib_end_switch
|
|
ivib_case_2:
|
|
mov edx,[edi]
|
|
sub edx,eax
|
|
jmp trim
|
|
ivib_case_1:
|
|
cmp [edi],eax
|
|
sbb edx,edx
|
|
and edx,eax
|
|
lea eax,[edx-64] ; delta = +/- 64
|
|
jmp ivib_end_switch
|
|
ivib_case_0:
|
|
; delta = 64 sin(2 Pi x/256)
|
|
mov ecx,[edi]
|
|
mov edx,ecx
|
|
and ecx,7Fh
|
|
cmp ecx,65
|
|
adc eax,-1
|
|
xor ecx,eax
|
|
and eax,129
|
|
add ecx,eax
|
|
shr edx,8
|
|
movzx eax,BYTE PTR [OFFSET sin64+ecx]
|
|
sbb edx,edx
|
|
xor eax,edx
|
|
sub eax,edx
|
|
ivib_end_switch:
|
|
movzx edx,BYTE PTR [esi+FMUSIC_INSTRUMENT.iVIBdepth]
|
|
imul edx,eax ; delta *= iptr->iVIBdepth
|
|
movzx eax,BYTE PTR [esi+FMUSIC_INSTRUMENT.VIBsweep]
|
|
test eax,eax
|
|
jz sweep_ok
|
|
push edi
|
|
xchg eax,edi
|
|
mov eax,[ebx+FMUSIC_CHANNEL.ivibsweeppos-2]
|
|
imul edx
|
|
idiv edi
|
|
xchg eax,edx ; delta *= cptr->ivibsweeppos/iptr->VIBsweep
|
|
xchg eax,edi ; iptr->VIBsweep
|
|
pop edi
|
|
sweep_ok:
|
|
sar edx,6
|
|
add [ebx+FMUSIC_CHANNEL.freqdelta-2],edx ; cptr->freqdelta += delta>>6
|
|
mov edx,[ebx+FMUSIC_CHANNEL.ivibsweeppos-2]
|
|
inc edx
|
|
cmp edx,eax
|
|
jle sweeppos_ok
|
|
xchg eax,edx
|
|
sweeppos_ok:
|
|
movzx eax,BYTE PTR [esi+FMUSIC_INSTRUMENT.VIBrate]
|
|
add eax,[edi] ; cptr->ivibpos += iptr->VIBrate
|
|
mov [ebx+FMUSIC_CHANNEL.ivibsweeppos-2],edx
|
|
neg ah
|
|
or BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
|
|
neg ah
|
|
sbb ah,0 ; ivibpos - 256
|
|
mov [edi],eax
|
|
endif ; INSTRUMENTVIBRATO_ON
|
|
mov esi,[ebx+FMUSIC_CHANNEL.cptr-2]
|
|
test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_TRIGGER
|
|
jz no_trig
|
|
; TRIGGER: allocate a channel
|
|
cmp DWORD PTR [esi+FSOUND_CHANNEL.fsptr],0
|
|
jz no_swap
|
|
; Swap between channels to avoid sounds cutting each other off and causing a click
|
|
mov ecx,esi
|
|
sub ecx,DWORD PTR [OFFSET _mod+FMUSIC_MODULE.Channels]
|
|
shr ecx,7 ; /FSOUND_CHANNEL_size + 1
|
|
sbb edi,edi
|
|
and edi,-FSOUND_CHANNEL_size*2
|
|
lea edi,[esi+edi+FSOUND_CHANNEL_size]
|
|
push edi
|
|
; Copy the whole channel except it's trailing data
|
|
push (FSOUND_CHANNEL_size-20)/4
|
|
mov [ebx+FMUSIC_CHANNEL.cptr-2],edi
|
|
pop ecx
|
|
rep movsd
|
|
; This should cause the old channel to ramp out nicely
|
|
mov [esi+FSOUND_CHANNEL.actualvolume-FSOUND_CHANNEL.fsptr],ecx
|
|
mov [esi+FSOUND_CHANNEL.leftvolume-FSOUND_CHANNEL.fsptr],ecx
|
|
mov [esi+FSOUND_CHANNEL.rightvolume-FSOUND_CHANNEL.fsptr],ecx
|
|
pop esi
|
|
no_swap:
|
|
lea edi,[esi+FSOUND_CHANNEL.fsptr]
|
|
mov eax,[esp+flags_sptr]
|
|
stosd ; fsptr
|
|
; START THE SOUND!
|
|
xor eax,eax
|
|
mov edx,[esi+FSOUND_CHANNEL.fsampleoffset]
|
|
stosd ; mixposlo
|
|
stosd ; ramp_leftvolume
|
|
stosd ; ramp_rightvolume
|
|
stosd ; ramp_count, speeddir
|
|
mov [esi+FSOUND_CHANNEL.fsampleoffset],eax
|
|
mov [esi+FSOUND_CHANNEL.mixpos],edx
|
|
no_trig:
|
|
mov eax,[ebx+FMUSIC_CHANNEL.volume-2]
|
|
xor ecx,ecx
|
|
cdq
|
|
not edx
|
|
and eax,edx
|
|
cmp eax,64
|
|
jle volume_le64
|
|
lea eax,[ecx+64]
|
|
volume_le64:
|
|
dec cl ; ecx <- 255
|
|
mov [ebx+FMUSIC_CHANNEL.volume-2],eax
|
|
test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
|
|
jz no_volume
|
|
add eax,[ebx+FMUSIC_CHANNEL.voldelta-2] ; 6 bit (64)
|
|
imul DWORD PTR [ebx+FMUSIC_CHANNEL.envvol-2] ; 6 bit (64)
|
|
imul DWORD PTR [_mod+FMUSIC_MODULE.globalvolume] ; 6 bit (64)
|
|
imul ecx ; eax *= 255
|
|
imul DWORD PTR [ebx+FMUSIC_CHANNEL.fadeoutvol-2] ; 16 bit (65536)
|
|
; eax:edx /= (2 * 64 * 64 * 64 * 65536)
|
|
sar edx,3
|
|
mov eax,[esi+FSOUND_CHANNEL.actualpan]
|
|
mov [esi+FSOUND_CHANNEL.actualvolume],edx
|
|
mov edi,edx
|
|
imul edx
|
|
idiv ecx
|
|
mov [esi+FSOUND_CHANNEL.leftvolume],eax ; leftvolume <- volume*actualpan/255
|
|
mov eax,ecx
|
|
sub eax,[esi+FSOUND_CHANNEL.actualpan]
|
|
imul edi
|
|
idiv ecx
|
|
mov [esi+FSOUND_CHANNEL.rightvolume],eax
|
|
no_volume:
|
|
test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
|
|
jz no_pan
|
|
mov edi,128
|
|
mov eax,[ebx+FMUSIC_CHANNEL.pan-2]
|
|
sub eax,edi
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
sub edi,eax
|
|
mov eax,[ebx+FMUSIC_CHANNEL.envpan-2]
|
|
sar edi,5
|
|
sub eax,32
|
|
imul edi
|
|
add eax,[ebx+FMUSIC_CHANNEL.pan-2]
|
|
cdq
|
|
not edx
|
|
and eax,edx ; if(pan < 0) pan = 0
|
|
mov edi,[esi] ; actualvolume
|
|
cmp eax,ecx
|
|
mov edx,ecx
|
|
xchg eax,edi
|
|
jae pan_ae255
|
|
imul edi
|
|
idiv ecx
|
|
mov edx,edi
|
|
pan_ae255:
|
|
xchg eax,edx
|
|
mov [esi+FSOUND_CHANNEL.actualpan],eax
|
|
mov [esi+FSOUND_CHANNEL.leftvolume],edx
|
|
not al ; 255 - pan
|
|
imul DWORD PTR [esi] ; actualvolume
|
|
idiv ecx
|
|
mov [esi+FSOUND_CHANNEL.rightvolume],eax
|
|
no_pan:
|
|
test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
|
|
jz no_freq
|
|
mov ecx,[ebx+FMUSIC_CHANNEL.freq-2]
|
|
xor edx,edx
|
|
add ecx,[ebx+FMUSIC_CHANNEL.freqdelta-2]
|
|
lea eax,[edx+40] ; f = 40 Hz
|
|
jle freq_bounds_ok
|
|
test BYTE PTR [_mod+FMUSIC_MODULE.flags],1
|
|
jnz modflags_n1
|
|
mov eax,0DA7790h
|
|
div ecx
|
|
xor edx,edx
|
|
jmp freq_bounds_ok
|
|
modflags_n1:
|
|
mov eax,4608
|
|
sub eax,[ebx+FMUSIC_CHANNEL.freq-2]
|
|
add eax,[ebx+FMUSIC_CHANNEL.freqdelta-2]
|
|
push eax
|
|
fild DWORD PTR [esp]
|
|
fmul DWORD PTR [f0_0013]
|
|
fld st0
|
|
frndint
|
|
fsub st1,st0
|
|
fxch st1
|
|
f2xm1
|
|
fld1
|
|
faddp st1,st0
|
|
fscale
|
|
fstp st1
|
|
fmul DWORD PTR [f8363_0]
|
|
fistp DWORD PTR [esp]
|
|
pop eax ; freq = 625.271028*exp2((4608-period)/64)
|
|
freq_bounds_ok:
|
|
mov ebx,FSOUND_MixRate
|
|
div ebx
|
|
mov [esi+FSOUND_CHANNEL.speedhi],eax
|
|
div ebx
|
|
mov [esi+FSOUND_CHANNEL.speedlo],eax
|
|
no_freq:
|
|
pop edi
|
|
pop esi
|
|
if INSTRUMENTVIBRATO_ON
|
|
ret 8
|
|
else
|
|
ret 4
|
|
endif |