Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ; CORE.ASM
  2. ; --------
  3. ; uFMOD public source code release. Provided as-is.
  4.  
  5. if VIBRATO_OR_TREMOLO
  6. sin127  db 00h,0Ch,19h,25h,31h,3Ch,47h,51h,5Ah,62h,6Ah,70h,75h,7Ah,7Dh,7Eh
  7.         db 7Fh,7Eh,7Dh,7Ah,75h,70h,6Ah,62h,5Ah,51h,47h,3Ch,31h,25h,19h,0Ch
  8. endif
  9. if INSTRUMENTVIBRATO_ON
  10. sin64   db 00h,02h,03h,05h,06h,08h,09h,0Bh,0Ch,0Eh,10h,11h,13h,14h,16h,17h
  11.         db 18h,1Ah,1Bh,1Dh,1Eh,20h,21h,22h,24h,25h,26h,27h,29h,2Ah,2Bh,2Ch
  12.         db 2Dh,2Eh,2Fh,30h,31h,32h,33h,34h,35h,36h,37h,38h,38h,39h,3Ah,3Bh
  13.         db 3Bh,3Ch,3Ch,3Dh,3Dh,3Eh,3Eh,3Eh,3Fh,3Fh,3Fh,40h,40h,40h,40h,40h
  14. endif
  15. if AMIGAPERIODS_ON
  16. f0_0833 dd 8.3333336e-2
  17. f13_375 dd 1.3375e1
  18. endif
  19. f0_0013 dd 1.302083375e-3
  20. f8363_0 dd 8.3630004275e3
  21.  
  22. ; Mixer ramping
  23. Ramp:
  24. ; [arg0] - ptr. to end of buffer
  25. ; ESI    - _mod+36
  26. ; EDI    - length
  27. ; EDX    - buffer
  28.         ; LOOP THROUGH CHANNELS
  29.         mov ecx,[esi+FMUSIC_MODULE.Channels-36]
  30.         push ebx
  31.         push ebp
  32. loop_ch:
  33.         push esi
  34.         mov esi,[ecx+FSOUND_CHANNEL.fsptr] ; load the correct SAMPLE pointer for this channel
  35.         test esi,esi ; if(!fsptr) skip this channel!
  36.         jz MixExit_1
  37.         push edx ; mix buffer
  38.         push edx ; cur. mix buffer pointer
  39.         mov ebx,[ecx+FSOUND_CHANNEL.mixpos]
  40.         ; Set up a mix counter. See what will happen first, will the output buffer
  41.         ; end be reached first? or will the end of the sample be reached first? whatever
  42.         ; is smallest will be the mixcount.
  43.         push edi
  44. CalculateLoopCount:
  45.         cmp BYTE PTR [ecx+FSOUND_CHANNEL.speeddir],0
  46.         mov edx,[esi+FSOUND_SAMPLE.loopstart]
  47.         mov eax,[ecx+FSOUND_CHANNEL.mixposlo]
  48.         jne samplesleftbackwards
  49.         ; work out how many samples left from mixpos to loop end
  50.         add edx,[esi+FSOUND_SAMPLE.looplen]
  51.         sub edx,ebx
  52.         ja submixpos
  53.         mov edx,[esi+FSOUND_SAMPLE._length]
  54.         sub edx,ebx
  55. submixpos:
  56.         ; edx : samples left (loopstart+looplen-mixpos)
  57.         neg edx
  58.         neg eax
  59.         adc edx,ebx
  60. samplesleftbackwards:
  61.         ; work out how many samples left from mixpos to loop start
  62.         neg edx
  63.         add edx,ebx
  64.         js MixExit
  65.         ; edx:eax now contains number of samples left to mix
  66.         mov ebp,[ecx+FSOUND_CHANNEL.speedlo]
  67.         shrd eax,edx,5
  68.         mov ebx,[ecx+FSOUND_CHANNEL.speedhi]
  69.         shr edx,5
  70.         shrd ebp,ebx,5
  71.         jnz speedok ; divide by 0 check
  72.         mov ebp,FREQ_40HZ_p
  73.         mov DWORD PTR [ecx+FSOUND_CHANNEL.speedlo],FREQ_40HZ_f
  74. speedok:
  75.         div ebp
  76.         xor ebp,ebp
  77.         neg edx
  78.         adc eax,ebp
  79.         jz DoOutputbuffEnd
  80.         mov ebx,OFFSET uFMOD_fopen
  81.         cmp eax,edi
  82.         ; set a flag to say mix will end when end of output buffer is reached
  83.         seta [ebx-22]   ; mix_endflag
  84.         jae staywithoutputbuffend
  85.         xchg eax,edi
  86. staywithoutputbuffend:
  87. if RAMP_NONE
  88. else
  89.         movzx eax,WORD PTR [ecx+FSOUND_CHANNEL.ramp_count]
  90.         ; VOLUME RAMP SETUP
  91.         ; Reasons to ramp
  92.         ; 1 volume change
  93.         ; 2 sample starts (just treat as volume change - 0 to volume)
  94.         ; 3 sample ends (ramp last n number of samples from volume to 0)
  95.         ; now if the volume has changed, make end condition equal a volume ramp
  96.         test eax,eax
  97. endif
  98.         mov edx,[ecx+FSOUND_CHANNEL.leftvolume]
  99.         mov ebp,[ecx+FSOUND_CHANNEL.rightvolume]
  100. if RAMP_NONE
  101.         mov [ecx+FSOUND_CHANNEL.ramp_leftvolume],ebp
  102.         mov [ecx+FSOUND_CHANNEL.ramp_rightvolume],edx
  103. else
  104.         mov [ebx-16],edi ; mmf+4 <- remember mix count before modifying it
  105.         jz volumerampstart
  106.         ; if it tries to continue an old ramp, but the target has changed,
  107.         ; set up a new ramp
  108.         cmp dx,[ecx+FSOUND_CHANNEL.ramp_lefttarget]
  109.         jne volumerampstart
  110.         cmp bp,[ecx+FSOUND_CHANNEL.ramp_righttarget]
  111.         je volumerampclamp ; restore old ramp
  112. volumerampstart:
  113.         ; SETUP NEW RAMP
  114.         mov [ecx+FSOUND_CHANNEL.ramp_lefttarget],dx
  115.         shl edx,volumeramps_pow
  116.         sub edx,[ecx+FSOUND_CHANNEL.ramp_leftvolume]
  117.         xor eax,eax
  118.         sar edx,volumeramps_pow
  119.         mov DWORD PTR [ecx+FSOUND_CHANNEL.ramp_leftspeed],edx
  120.         jz novolumerampL
  121.         mov al,volumerampsteps
  122. novolumerampL:
  123.         mov [ecx+FSOUND_CHANNEL.ramp_righttarget],bp
  124.         shl ebp,volumeramps_pow
  125.         sub ebp,[ecx+FSOUND_CHANNEL.ramp_rightvolume]
  126.         sar ebp,volumeramps_pow
  127.         mov DWORD PTR [ecx+FSOUND_CHANNEL.ramp_rightspeed],ebp
  128.         jz novolumerampR
  129.         mov al,volumerampsteps
  130. novolumerampR:
  131.         test eax,eax
  132.         mov [ecx+FSOUND_CHANNEL.ramp_count],ax
  133.         jz volumerampend
  134. volumerampclamp:
  135.         cmp edi,eax
  136.         jbe volumerampend ; dont clamp mixcount
  137.         mov edi,eax
  138. volumerampend:
  139.         mov eax,[ecx+FSOUND_CHANNEL.ramp_leftspeed]
  140.         mov [ebx],eax    ; ramp_leftspeed
  141.         mov eax,[ecx+FSOUND_CHANNEL.ramp_rightspeed]
  142.         mov [ebx+4],eax  ; ramp_rightspeed
  143. endif
  144.         mov [ebx-20],edi ; mmf
  145.         ; SET UP ALL OF THE REGISTERS HERE FOR THE INNER LOOP
  146.         ; edx : speed
  147.         ; ebx : mixpos
  148.         ; ebp : speed low
  149.         ; esi : destination pointer
  150.         ; edi : counter
  151.         mov ebx,[ecx+FSOUND_CHANNEL.mixpos]
  152.         lea ebx,[ebx*2+esi+FSOUND_SAMPLE.buff]
  153.         push esi
  154.         cmp BYTE PTR [ecx+FSOUND_CHANNEL.speeddir],0
  155.         mov esi,[esp+8] ; <- cur. mix buffer
  156.         mov edx,[ecx+FSOUND_CHANNEL.speedhi]
  157.         mov ebp,[ecx+FSOUND_CHANNEL.speedlo]
  158.         je MixLoop16
  159.         ; neg edx:ebp
  160.         neg ebp
  161.         not edx
  162.         sbb edx,-1
  163.         align 4
  164. MixLoop16:
  165.         push edi
  166.         push edx
  167.         movsx edi,WORD PTR [ebx]
  168.         movsx eax,WORD PTR [ebx+2]
  169.         mov edx,[ecx+FSOUND_CHANNEL.mixposlo]
  170.         sub eax,edi
  171.         shr edx,1 ; force unsigned
  172.         imul edx
  173.         shl edi,volumeramps_pow-1
  174.         shld edx,eax,volumeramps_pow
  175.         add edx,edi
  176. if RAMP_NONE
  177.         mov eax,edx
  178.         imul edx,[ecx+FSOUND_CHANNEL.ramp_rightvolume]
  179.         add [esi],edx
  180.         imul DWORD PTR [ecx+FSOUND_CHANNEL.ramp_leftvolume]
  181.         add [esi+4],eax
  182. else
  183.         xchg eax,edx
  184.         mov edi,eax
  185.         imul DWORD PTR [ecx+FSOUND_CHANNEL.ramp_rightvolume]
  186.         shrd eax,edx,volumeramps_pow-1
  187.         rol edx,1
  188.         and edx,1
  189.         add eax,edx
  190.         sar eax,1
  191.         add [esi],eax
  192.         xchg eax,edi
  193.         imul DWORD PTR [ecx+FSOUND_CHANNEL.ramp_leftvolume]
  194.         shrd eax,edx,volumeramps_pow-1
  195.         rol edx,1
  196.         and edx,1
  197.         add eax,edx
  198.         mov edi,[uFMOD_fread]
  199.         sar eax,1
  200.         add [esi+4],eax
  201.         mov edx,[uFMOD_fopen]
  202.         add [ecx+FSOUND_CHANNEL.ramp_rightvolume],edi ; + cur_ramp_rightspeed
  203.         add [ecx+FSOUND_CHANNEL.ramp_leftvolume],edx  ; + cur_ramp_leftspeed
  204. endif
  205.         pop edx
  206.         xor eax,eax
  207.         add [ecx+FSOUND_CHANNEL.mixposlo],ebp
  208.         pop edi
  209.         adc eax,edx
  210.         add esi,8
  211.         dec edi
  212.         lea ebx,[ebx+eax*2]
  213.         jnz MixLoop16
  214.         mov edi,[esp+20h] ; find out how many OUTPUT samples left to mix
  215.         mov [esp+8],esi   ; update cur. mix buffer
  216.         sub edi,esi
  217.         shr edi,3         ; edi <- # of samples left
  218.         pop esi           ; esi <- sample pointer
  219.         lea eax,[esi+FSOUND_SAMPLE.buff]
  220.         sub ebx,eax
  221.         shr ebx,1
  222.         mov [ecx+FSOUND_CHANNEL.mixpos],ebx
  223. if RAMP_NONE
  224.         xor edx,edx
  225. else
  226.         ; DID A VOLUME RAMP JUST HAPPEN?
  227.         movzx edx,WORD PTR [ecx+FSOUND_CHANNEL.ramp_count]
  228.         test edx,edx
  229.         jz DoOutputbuffEnd
  230.         mov eax,[mmf]
  231.         cdq
  232.         sub [ecx+FSOUND_CHANNEL.ramp_count],ax
  233.         ; if(!rampcount) a ramp has FINISHED, so finish the rest of the mix
  234.         jnz DoOutputbuffEnd
  235.         sub eax,[mmf+4]
  236.         ; clear out the ramp speeds
  237.         mov [ecx+FSOUND_CHANNEL.ramp_leftspeed],edx
  238.         neg eax
  239.         mov [ecx+FSOUND_CHANNEL.ramp_rightspeed],edx
  240.         ; is it 0 because ramp ended only? or both ended together?
  241.         ; if sample ended together with ramp... problems... loop isn't handled
  242.         sbb edx,edx
  243.         ; start again and continue rest of mix
  244.         test edi,edx
  245.         jnz CalculateLoopCount ; dont start again if nothing left
  246.         xor edx,edx
  247. endif
  248. DoOutputbuffEnd:
  249.         cmp [mix_endflag],dl
  250.         jne MixExit
  251.         movzx eax,BYTE PTR [esi+FSOUND_SAMPLE.loopmode]
  252.         ; SWITCH ON LOOP MODE TYPE
  253.         dec eax ; check for normal loop (FSOUND_LOOP_NORMAL = 1)
  254.         jnz CheckBidiLoop
  255.         mov eax,[esi+FSOUND_SAMPLE.loopstart]
  256.         mov ebp,[esi+FSOUND_SAMPLE.looplen]
  257.         add eax,ebp
  258.         cmp ebx,eax
  259.         jbe rewind_ok
  260.         sub ebx,eax
  261.         xchg eax,ebx
  262.         div ebp
  263. rewind_ok:
  264.         sub ebp,edx
  265.         sub ebx,ebp
  266.         jmp ChkLoop_OK
  267. CheckBidiLoop:
  268.         dec eax ; FSOUND_LOOP_BIDI = 2
  269.         neg eax
  270.         adc edx,-1
  271.         and [ecx+FSOUND_CHANNEL.mixposlo],edx
  272.         and [ecx+FSOUND_CHANNEL.mixpos],edx
  273.         and [ecx+FSOUND_CHANNEL.fsptr],edx
  274.         jz MixExit
  275.         cmp [ecx+FSOUND_CHANNEL.speeddir],al ; FSOUND_MIXDIR_FORWARDS
  276.         je BidiForward
  277. BidiBackwards:
  278.         mov eax,[esi+FSOUND_SAMPLE.loopstart]
  279.         neg ebp
  280.         dec eax
  281.         sub ebp,1
  282.         dec BYTE PTR [ecx+FSOUND_CHANNEL.speeddir] ; set FSOUND_MIXDIR_FORWARDS
  283.         sbb eax,ebx
  284.         mov ebx,[esi+FSOUND_SAMPLE.loopstart]
  285.         add ebx,eax
  286.         cmp eax,[esi+FSOUND_SAMPLE.looplen]
  287.         jl BidiFinish
  288. BidiForward:
  289.         mov eax,[esi+FSOUND_SAMPLE.loopstart]
  290.         add eax,[esi+FSOUND_SAMPLE.looplen]
  291.         lea edx,[eax-1]
  292.         sbb eax,ebx
  293.         neg ebp
  294.         xchg eax,ebx
  295.         sub ebp,1
  296.         adc ebx,edx
  297.         inc BYTE PTR [ecx+FSOUND_CHANNEL.speeddir] ; go backwards
  298.         cmp ebx,[esi+FSOUND_SAMPLE.loopstart]
  299.         jl BidiBackwards
  300. BidiFinish:
  301.         mov [ecx+FSOUND_CHANNEL.mixposlo],ebp
  302. ChkLoop_OK:
  303.         test edi,edi
  304.         mov [ecx+FSOUND_CHANNEL.mixpos],ebx
  305.         jnz CalculateLoopCount
  306. MixExit:
  307.         pop edi
  308.         pop eax ; discard cur. mix buffer pointer
  309.         pop edx
  310. MixExit_1:
  311.         add ecx,FSOUND_CHANNEL_size
  312.         pop esi
  313.         cmp ecx,[esi+FMUSIC_MODULE.uFMOD_Ch-36]
  314.         jl loop_ch
  315.         pop ebp
  316.         pop ebx
  317.         ret
  318.  
  319. if AMIGAPERIODS_ON
  320. AmigaPeriod:
  321. ; [sptr] in ECX
  322. ; note   in EAX
  323. ; ESI != 0
  324.         mov edx,132
  325.         push edi
  326.         sub edx,eax
  327.         push esi
  328.         test eax,eax
  329.         push edx
  330.         movsx eax,BYTE PTR [ecx+FSOUND_SAMPLE.finetune]
  331.         mov edi,edx
  332.         jz _do_inc
  333.         cdq
  334.         shl edx,1
  335. _do_inc:
  336.         inc edx
  337. exp2:
  338.         fild DWORD PTR [esp]
  339.         fmul DWORD PTR [f0_0833] ; /12.0f
  340.         fld st0
  341.         frndint
  342.         fsub st1,st0
  343.         fxch st1
  344.         f2xm1
  345.         fld1
  346.         faddp st1,st0
  347.         fscale
  348.         fstp st1
  349.         fmul DWORD PTR [f13_375] ; *13.375f
  350.         fistp DWORD PTR [esp]
  351.         test esi,esi
  352.         pop ecx
  353.         jz exp2_end
  354.         sub edi,edx
  355.         push edi
  356.         xor esi,esi
  357.         mov edi,ecx
  358.         jmp exp2
  359. exp2_end:
  360.         sub ecx,edi
  361.         test edx,edx
  362.         jns _do_imul
  363.         neg ecx
  364. _do_imul:
  365.         imul ecx
  366.         and edx,127 ; +2^7-1
  367.         add eax,edx
  368.         sar eax,7
  369.         pop esi
  370.         add eax,edi
  371.         pop edi
  372.         ret
  373. endif ; AMIGAPERIODS_ON
  374.  
  375. ; DESCRIPTION: To carry out a vibrato at a certain depth and speed
  376. if VIBRATO_OR_VOLSLIDE
  377.         if TREMOLO_ON
  378.         VibratoOrTremolo:
  379.         ; cptr+2 = ESI
  380.                 movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2]
  381.                 mov al,[esi+FMUSIC_CHANNEL.wavecontrol-2]
  382.                 mov edx,ecx
  383.                 add dl,[esi+FMUSIC_CHANNEL.vibspeed-2]
  384.                 and edx,3Fh
  385.                 and eax,3 ; switch(cptr->wavecontrol&3)
  386.                 mov [esi+FMUSIC_CHANNEL.vibpos-2],dl
  387.                 jz vibrato_c0
  388.                 ; C2 : Sqare wave
  389.                 rol ecx,27
  390.                 sbb edx,edx
  391.                 xor edx,7Fh
  392.                 or edx,1
  393.                 dec eax
  394.                 jnz vibrato_default
  395.                 ; C1 : Triangle wave (ramp down)
  396.                 shr edx,24
  397.                 ror ecx,23
  398.                 add edx,ecx
  399.                 neg edx
  400.                 jmp vibrato_default
  401.         vibrato_c0:
  402.                 ; C0 : Sine wave
  403.                 ; delta = 127 sin(2 Pi x/64)
  404.                 mov eax,ecx
  405.                 and ecx,1Fh
  406.                 shr eax,6
  407.                 movzx edx,BYTE PTR [OFFSET sin127+ecx]
  408.                 sbb eax,eax
  409.                 xor edx,eax
  410.                 sub edx,eax
  411.         vibrato_default:
  412.                 movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.vibdepth-2]
  413.                 imul edx  ; delta *= cptr->vibdepth
  414.                 sar eax,5
  415.                 ret
  416.         endif
  417.  
  418. Vibrato:
  419. ; cptr+2 = ESI
  420.         if TREMOLO_ON
  421.                 call VibratoOrTremolo
  422.                 sar eax,1
  423.         else
  424.                 movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2]
  425.                 mov al,[esi+FMUSIC_CHANNEL.wavecontrol-2]
  426.                 mov edx,ecx
  427.                 add dl,[esi+FMUSIC_CHANNEL.vibspeed-2]
  428.                 and edx,3Fh
  429.                 and eax,3 ; switch(cptr->wavecontrol&3)
  430.                 mov [esi+FMUSIC_CHANNEL.vibpos-2],dl
  431.                 jz vibrato_c0
  432.                 ; C2 : Sqare wave
  433.                 rol ecx,27
  434.                 sbb edx,edx
  435.                 xor edx,7Fh
  436.                 or edx,1
  437.                 dec eax
  438.                 jnz vibrato_default
  439.                 ; C1 : Triangle wave (ramp down)
  440.                 shr edx,24
  441.                 ror ecx,23
  442.                 add edx,ecx
  443.                 neg edx
  444.                 jmp vibrato_default
  445.         vibrato_c0:
  446.                 ; C0 : Sine wave
  447.                 ; delta = 127 sin(2 Pi x/64)
  448.                 mov eax,ecx
  449.                 and ecx,1Fh
  450.                 shr eax,6
  451.                 movzx edx,BYTE PTR [OFFSET sin127+ecx]
  452.                 sbb eax,eax
  453.                 xor edx,eax
  454.                 sub edx,eax
  455.         vibrato_default:
  456.                 movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.vibdepth-2]
  457.                 imul edx  ; delta *= cptr->vibdepth
  458.                 sar eax,6
  459.         endif
  460.         mov [esi+FMUSIC_CHANNEL.freqdelta-2],eax
  461.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
  462.         ret
  463. endif ; VIBRATO_OR_VOLSLIDE
  464.  
  465. if TREMOLO_ON
  466. Tremolo:
  467. ; cptr+2 = ESI
  468.         if VIBRATO_OR_VOLSLIDE
  469.                 push esi
  470.                 add esi,FMUSIC_CHANNEL.tremolopos-FMUSIC_CHANNEL.vibpos
  471.                 call VibratoOrTremolo
  472.                 pop esi
  473.         else
  474.                 movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.tremolopos-2]
  475.                 mov al,[esi+FMUSIC_CHANNEL.wavecontrol-2]
  476.                 mov edx,ecx
  477.                 add dl,[esi+FMUSIC_CHANNEL.tremolospeed-2]
  478.                 and edx,3Fh
  479.                 and eax,3 ; switch(cptr->wavecontrol&3)
  480.                 mov [esi+FMUSIC_CHANNEL.tremolopos-2],dl
  481.                 jz tremolo_c0
  482.                 ; C2 : Sqare wave
  483.                 rol ecx,27
  484.                 sbb edx,edx
  485.                 xor edx,7Fh
  486.                 or edx,1
  487.                 dec eax
  488.                 jnz tremolo_default
  489.                 ; C1 : Triangle wave (ramp down)
  490.                 shr edx,24
  491.                 ror ecx,23
  492.                 add edx,ecx
  493.                 neg edx
  494.                 jmp tremolo_default
  495.         tremolo_c0:
  496.                 ; C0 : Sine wave
  497.                 ; delta = 127 sin(2 Pi x/64)
  498.                 mov eax,ecx
  499.                 and ecx,1Fh
  500.                 shr eax,6
  501.                 movzx edx,BYTE PTR [OFFSET sin127+ecx]
  502.                 sbb eax,eax
  503.                 xor edx,eax
  504.                 sub edx,eax
  505.         tremolo_default:
  506.                 movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.tremolodepth-2]
  507.                 imul edx
  508.                 sar eax,5
  509.         endif
  510.         mov [esi+FMUSIC_CHANNEL.voldelta-2],eax
  511.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  512.         ret
  513. endif ; TREMOLO_ON
  514.  
  515. if PORTATO_OR_VOLSLIDE
  516. Portamento:
  517. ; cptr+2 = ESI
  518.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
  519.         mov eax,[esi+FMUSIC_CHANNEL.freq-2]
  520.         mov ecx,[esi+FMUSIC_CHANNEL.portatarget-2]
  521.         movzx edx,BYTE PTR [esi+FMUSIC_CHANNEL.portaspeed-2]
  522.         shl edx,2
  523.         sub eax,ecx
  524.         jg porta_do_sub
  525.         add eax,edx
  526.         jg _do_trim
  527.         jmp _no_trim
  528. porta_do_sub:
  529.         sub eax,edx
  530.         jl _do_trim
  531. _no_trim:
  532.         add ecx,eax
  533. _do_trim:
  534.         mov [esi+FMUSIC_CHANNEL.freq-2],ecx
  535.         ret
  536. endif ; PORTATO_OR_VOLSLIDE
  537.  
  538. if VOLUME_OR_PANENVELOPE
  539. Envelope:
  540. ; cptr+2   = ESI
  541. ; env_iptr = ECX
  542. ; control  = AL
  543. env_type     equ -4
  544. envstopped   equ -8
  545. envdelta     equ -12
  546. env_value    equ -16
  547. valfrac      equ -20
  548. ; env_tick     = -24
  549. sustain_l2   equ -26
  550. sustain_l1   equ -27
  551. sustain_loop equ -28
  552. env_next     equ -32
  553. env_pos      equ -36
  554.         push edi
  555.         push ebx
  556.         push ebp
  557.         mov ebp,esp
  558.         ; Initialize local vars with PAN/VOL data
  559.         lea edi,[ecx+FMUSIC_INSTRUMENT.PANPoints]
  560.         xor ebx,ebx
  561. if PANENVELOPE_ON
  562.         mov edx,DWORD PTR [edi+FMUSIC_INSTRUMENT.PANsustain-FMUSIC_INSTRUMENT.PANPoints]
  563.         mov [ebp+sustain_loop],edx ; load PANsustain, PANLoopStart and PANLoopEnd
  564.         mov cl,BYTE PTR [edi+FMUSIC_INSTRUMENT.PANtype-FMUSIC_INSTRUMENT.PANPoints]
  565.         movzx edx,BYTE PTR [edi+FMUSIC_INSTRUMENT.PANnumpoints-FMUSIC_INSTRUMENT.PANPoints]
  566. endif
  567.         or [esi+FMUSIC_CHANNEL.notectrl-2],al ; cptr->notectrl |= control
  568. if PANENVELOPE_ON
  569.         if VOLUMEENVELOPE_ON
  570.                 cmp al,FMUSIC_VOLUME ; is it FMUSIC_VOLUME or FMUSIC_PAN?
  571.         endif
  572.         lea eax,[esi+FMUSIC_CHANNEL.envpanstopped-2]
  573. endif
  574. if VOLUMEENVELOPE_ON
  575.         if PANENVELOPE_ON
  576.                 jnz pan_or_vol_ok
  577.         endif
  578.         ; control = FMUSIC_VOLUME
  579.         add ebx,FMUSIC_CHANNEL.envvol-FMUSIC_CHANNEL.envpan
  580.         mov eax,DWORD PTR [edi+FMUSIC_INSTRUMENT.VOLsustain-FMUSIC_INSTRUMENT.PANPoints]
  581.         mov [ebp+sustain_loop],eax ; load VOLsustain, VOLLoopStart and VOLLoopEnd
  582.         mov cl,BYTE PTR [edi+FMUSIC_INSTRUMENT.VOLtype-FMUSIC_INSTRUMENT.PANPoints]
  583.         movzx edx,BYTE PTR [edi+FMUSIC_INSTRUMENT.VOLnumpoints-FMUSIC_INSTRUMENT.PANPoints]
  584.         lea eax,[esi+FMUSIC_CHANNEL.envvolstopped-2]
  585.         add edi,FMUSIC_INSTRUMENT.VOLPoints-FMUSIC_INSTRUMENT.PANPoints
  586. pan_or_vol_ok:
  587. endif
  588.         cmp BYTE PTR [eax],dh
  589.         jne goto_envelope_ret
  590.         push ecx      ; -> env_type
  591.         push eax      ; -> envstopped
  592.         lea ecx,[esi+ebx+FMUSIC_CHANNEL.envpanpos-2]
  593.         lea eax,[esi+ebx+FMUSIC_CHANNEL.envpandelta-2]
  594.         push eax      ; -> envdelta
  595.         lea eax,[esi+ebx+FMUSIC_CHANNEL.envpan-2]
  596.         push eax      ; -> env_value
  597.         lea eax,[esi+ebx+FMUSIC_CHANNEL.envpanfrac-2]
  598.         lea ebx,[esi+ebx+FMUSIC_CHANNEL.envpantick-2]
  599.         push eax      ; -> valfrac
  600.         mov eax,[ecx]
  601.         cmp eax,edx   ; if(*pos>=numpoints) envelop out of bound
  602.         push ebx      ; -> env_tick
  603.         jge envelope_done
  604.         movzx eax,WORD PTR [edi+eax*4]
  605.         cmp [ebx],eax ; if(*tick == points[(*pos)<<1]) we are at the correct tick for the position
  606.         jnz add_envdelta
  607.         test BYTE PTR [ebp+env_type],FMUSIC_ENVELOPE_LOOP
  608.         jz loop_ok
  609.         movzx eax,BYTE PTR [ebp+sustain_l2]
  610.         cmp [ecx],eax
  611.         jnz loop_ok   ; if((type&FMUSIC_ENVELOPE_LOOP) && *pos == loopend) handle loop
  612.         movzx eax,BYTE PTR [ebp+sustain_l1]
  613.         mov [ecx],eax ; *pos = loopstart
  614.         movzx eax,WORD PTR [edi+eax*4]
  615.         mov [ebx],eax ; *tick = points[(*pos)<<1]
  616. loop_ok:
  617.         mov eax,[ecx]
  618.         mov [ebp+env_pos],eax
  619.         lea eax,[edi+eax*4]
  620.         dec edx
  621.         movzx ebx,WORD PTR [eax] ; get tick at this point
  622.         cmp [ecx],edx
  623.         mov edx,[eax+4]
  624.         mov edi,edx
  625.         movzx eax,WORD PTR [eax+2]
  626.         mov [ebp+env_next],edx ; get tick at next point
  627.         mov edx,[ebp+env_value]
  628.         mov [edx],eax ; *value = points[(currpos<<1)+1]
  629.         jne env_continue
  630.         ; if it is at the last position, abort the envelope and continue last value
  631.         mov eax,[ebp+envstopped]
  632.         inc BYTE PTR [eax] ; *envstopped = TRUE
  633. goto_envelope_ret:
  634.         jmp Envelope_Ret
  635. env_continue:
  636.         shl eax,16
  637.         sub edi,eax
  638.         xchg eax,edi
  639.         xor ax,ax
  640.         ; sustain
  641.         test BYTE PTR [ebp+env_type],FMUSIC_ENVELOPE_SUSTAIN
  642.         jz not_sustain
  643.         movzx edx,BYTE PTR [ebp+sustain_loop]
  644.         cmp [ebp+env_pos],edx
  645.         jne not_sustain
  646.         cmp BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2],al
  647.         je Envelope_Ret
  648. not_sustain:
  649.         ; interpolate 2 points to find delta step
  650.         inc DWORD PTR [ecx] ; (*pos)++
  651.         mov ecx,[ebp+valfrac]
  652.         mov [ecx],edi ; *valfrac = curr
  653.         mov edi,[ebp+envdelta]
  654.         movzx ecx,WORD PTR [ebp+env_next]
  655.         and DWORD PTR [edi],0 ; *envdelta = 0
  656.         sub ecx,ebx
  657.         jz envelope_done
  658.         cdq
  659.         idiv ecx
  660.         mov [edi],eax ; *envdelta = (next-curr)/(nexttick-currtick)
  661.         jmp envelope_done
  662. add_envdelta:
  663.         ; interpolate
  664.         mov eax,[ebp+envdelta]
  665.         mov ecx,[eax]
  666.         mov eax,[ebp+valfrac]
  667.         add [eax],ecx ; *valfrac += *envdelta
  668. envelope_done:
  669.         pop edx ; <- env_tick
  670.         pop eax ; <- valfrac
  671.         pop ecx ; <- env_value
  672.         mov eax,[eax]
  673.         inc DWORD PTR [edx] ; (*tick)++
  674.         sar eax,16
  675.         mov [ecx],eax ; *value = *valfrac >> 16
  676. Envelope_Ret:
  677.         leave
  678.         pop ebx
  679.         pop edi
  680.         ret
  681. endif ; VOLUME_OR_PANENVELOPE
  682.  
  683. if VOLUMEBYTE_ON
  684. VolByte:
  685. ; volume = EDX
  686. ; cptr+2 = ESI
  687.         sub edx,16
  688.         jb switch_volume
  689.         cmp edx,40h
  690.         ja switch_volume
  691.         ; if(volume >= 0x10 && volume <= 0x50)
  692.         mov [esi+FMUSIC_CHANNEL.volume-2],edx
  693. switch_volume:
  694.         mov eax,edx
  695.         and edx,0Fh
  696.         shr eax,4 ; switch(volume>>4)
  697.         sub eax,5
  698.         jz case_6
  699.         dec eax
  700.         jz case_7
  701.         dec eax
  702.         jz case_6
  703.         dec eax
  704.         jz case_7
  705.         sub eax,2
  706.         jbe case_AB
  707.         dec eax
  708.         jz case_C
  709.         dec eax
  710.         jz case_D
  711.         dec eax
  712.         jz case_E
  713.         dec eax
  714.         jnz vol_default
  715.         ; case 0xF
  716.         test edx,edx
  717.         jz vol_z
  718.         shl dl,4
  719.         mov [esi+FMUSIC_CHANNEL.portaspeed-2],dl
  720. vol_z:
  721.         and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER
  722. if PORTATO_OR_VOLSLIDE
  723.         mov eax,[esi+FMUSIC_CHANNEL.period-2]
  724.         mov [esi+FMUSIC_CHANNEL.portatarget-2],eax ; cptr->portatarget = cptr->period
  725. endif
  726. vol_default:
  727.         ret
  728. case_6: ; / case 8
  729.         neg edx
  730. case_7: ; / case 9
  731.         add [esi+FMUSIC_CHANNEL.volume-2],edx
  732.         ret
  733. case_AB:
  734.         mov [esi+eax+FMUSIC_CHANNEL.vibspeed-1],dl
  735.         ret
  736. case_C:
  737.         shl edx,4
  738.         mov [esi+FMUSIC_CHANNEL.pan-2],edx
  739.         xchg eax,edx
  740. case_D:
  741.         neg edx
  742. case_E:
  743.         add [esi+FMUSIC_CHANNEL.pan-2],edx
  744.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
  745.         ret
  746. endif ; VOLUMEBYTE_ON
  747.  
  748. if TREMOR_ON
  749. Tremor:
  750. ; cptr+2 = ESI
  751.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  752.         mov dx,WORD PTR [esi+FMUSIC_CHANNEL.tremorpos-2]
  753.         cmp dl,dh
  754.         jbe inc_pos
  755.         mov ecx,[esi+FMUSIC_CHANNEL.volume-2]
  756.         neg ecx
  757.         mov [esi+FMUSIC_CHANNEL.voldelta-2],ecx
  758. inc_pos:
  759.         add dh,[esi+FMUSIC_CHANNEL.tremoroff-2]
  760.         cmp dl,dh
  761.         jbe Tremor_Ret
  762.         mov dl,-1
  763. Tremor_Ret:
  764.         inc dl
  765.         mov [esi+FMUSIC_CHANNEL.tremorpos-2],dl
  766.         ret
  767. endif ; TREMOR_ON
  768.  
  769. SetBPM:
  770. ; bpm = ECX
  771.         test ecx,ecx
  772.         mov eax,FSOUND_MixRate*5/2
  773.         jz SetBPM_Ret
  774.         cdq
  775.         div ecx
  776. SetBPM_Ret:
  777.         mov DWORD PTR [_mod+FMUSIC_MODULE.mixer_samplespertick],eax
  778.         ret
  779.  
  780. ; Loads an XM stream into memory. Returns non-zero on success.
  781. LoadXM:
  782. loadxm_count1      equ -4
  783. loadxm_numpat      equ -8
  784. loadxm_fnumpat     equ -12
  785. loadxm_count2      equ -16
  786. loadxm_skip        equ -20
  787. loadxm_s0loopmode  equ -38
  788. loadxm_s0bytes     equ -42
  789. loadxm_s0looplen   equ -48
  790. loadxm_s0loopstart equ -52
  791. loadxm_sample_2    equ -56
  792. loadxm_pat_size    equ -63
  793. loadxm_pat         equ -68
  794. loadxm_tmp29       equ -91
  795. loadxm_tmp27       equ -93
  796. loadxm_tmp         equ -120
  797.         mov eax,OFFSET _mod
  798.         push ebp
  799.         mov esi,eax
  800.         mov ebp,esp
  801.         mov edx,FMUSIC_MODULE_size
  802.         ; buf  : EAX
  803.         ; size : EDX
  804.         call [uFMOD_fread]
  805.         xor ecx,ecx
  806.         mov eax,[esi+FMUSIC_MODULE.mixer_samplespertick]
  807.         push ecx ; -> loadxm_count1
  808.         ; GOTO PATTERN DATA
  809.         lea eax,[eax+60]
  810.         ; pos  : EAX
  811.         ; org  : ECX
  812.         ; !org : Z
  813.         call uFMOD_lseek
  814.         add esp,-116
  815.         push ebx
  816.         ; SAVE TRACK TITLE
  817. if INFO_API_ON
  818.         push 20 ; a title has max. 20 chars
  819.         lea edx,[esi+17]
  820.         mov edi,OFFSET szTtl
  821. if UCODE
  822.         xor eax,eax
  823. endif
  824.         pop ecx
  825. loadxm_ttl:
  826.         mov al,[edx]
  827.         inc edx
  828.         cmp al,20h ; copy only printable chars
  829.         jl loadxm_ttl_ok
  830. if UCODE
  831.         stosw
  832. else
  833.         stosb
  834. endif
  835. loadxm_ttl_ok:
  836.         dec ecx
  837.         jnz loadxm_ttl
  838.         xchg eax,ecx
  839.         stosd
  840. else
  841.         xor eax,eax
  842. endif
  843.         ; COUNT NUM. OF PATTERNS
  844.         movzx ecx,WORD PTR [esi+FMUSIC_MODULE.numorders]
  845.         movzx ebx,WORD PTR [esi+FMUSIC_MODULE.numpatternsmem]
  846.         neg ebx
  847.         mov edi,esi
  848.         sbb edx,edx
  849.         and ecx,edx
  850.         neg ebx
  851.         dec ecx
  852.         movzx edx,dl
  853.         mov [ebp+loadxm_fnumpat],ebx
  854. if CHK4VALIDITY
  855.         cmp ecx,edx
  856.         ja loadxm_R
  857. endif
  858. loadxm_for_pats:
  859.         mov dl,[esi+FMUSIC_MODULE.orderlist]
  860.         cmp edx,eax
  861.         jbe loadxm_for_continue
  862.         xchg eax,edx
  863. loadxm_for_continue:
  864.         inc esi
  865.         dec ecx
  866.         jns loadxm_for_pats
  867.         mov [ebp+loadxm_numpat],eax
  868.         inc eax
  869.         mov esi,edi
  870.         ; ALLOCATE THE PATTERN ARRAY (whatever is bigger: fnumpat or numpat) & CHANNEL POOL
  871.         cmp eax,ebx
  872.         jae loadxm_pats_ok2
  873.         xchg eax,ebx
  874. loadxm_pats_ok2:
  875.         movzx ecx,BYTE PTR [esi+FMUSIC_MODULE.numinsts]
  876.         imul ecx,FMUSIC_INSTRUMENT_size
  877.         mov [esi+FMUSIC_MODULE.numpatternsmem],ax
  878.         lea edi,[ecx+eax*FMUSIC_PATTERN_size]
  879.         mov eax,edi
  880.         sub edi,ecx
  881.         movzx ecx,BYTE PTR [esi+FMUSIC_MODULE.numchannels_xm]
  882. if CHK4VALIDITY
  883.         cmp ecx,64
  884.         jle loadxm_numchan_ok
  885.         xor ecx,ecx
  886. loadxm_numchan_ok:
  887. endif
  888.         mov [esi+FMUSIC_MODULE.numchannels],ecx
  889.         mov ebx,ecx
  890.         shl ebx,7 ; *FSOUND_CHANNEL_size*2 == *FMUSIC_CHANNEL_size
  891. if CHK4VALIDITY
  892.         jz loadxm_R
  893. endif
  894.         mov [ebp+loadxm_count2],ecx
  895.         lea eax,[eax+ebx*2]
  896.         ; numbytes : EAX
  897.         call alloc
  898.         lea edx,[eax+ebx]
  899.         mov [esi+FMUSIC_MODULE.Channels],eax
  900.         mov [esi+FMUSIC_MODULE.uFMOD_Ch],edx
  901.         mov ebx,FMUSIC_CHANNEL_size ; = FSOUND_CHANNEL_size*2
  902. loop_2:
  903.         mov BYTE PTR [eax+FSOUND_CHANNEL.speedhi],1
  904.         mov [edx+FMUSIC_CHANNEL.cptr],eax
  905.         add eax,ebx
  906.         add edx,ebx
  907.         dec DWORD PTR [ebp+loadxm_count2]
  908.         jnz loop_2
  909.         mov [esi],edx ; FMUSIC_MODULE.pattern
  910.         add edi,edx
  911.         movzx ecx,WORD PTR [esi+FMUSIC_MODULE.defaultbpm]
  912.         mov [esi+FMUSIC_MODULE.instrument],edi
  913.         mov edi,edx
  914.         ; bpm : ECX
  915.         call SetBPM
  916.         push 64
  917.         movzx ecx,WORD PTR [esi+FMUSIC_MODULE.defaultspeed]
  918.         pop DWORD PTR [esi+FMUSIC_MODULE.globalvolume]
  919.         mov [esi+FMUSIC_MODULE.speed],ecx
  920.         ; ALLOCATE INSTRUMENT ARRAY
  921.         mov eax,[ebp+loadxm_fnumpat]
  922.         ; READ & UNPACK PATTERNS
  923. loadxm_load_pats:
  924.         push 9
  925.         lea eax,[ebp+loadxm_pat]
  926.         pop edx
  927.         ; buf  : EAX
  928.         ; size : EDX
  929.         call [uFMOD_fread]
  930.         ; ALLOCATE PATTERN BUFFER
  931.         mov eax,[ebp+loadxm_pat_size] ; length of pattern & packed pattern size
  932.         mov ecx,[esi+FMUSIC_MODULE.numchannels]
  933.         cmp eax,10000h
  934.         mov [edi],eax
  935.         movzx eax,ax
  936.         jb loadxm_ldpats_continue ; skip an empty pattern
  937. if CHK4VALIDITY
  938.         cmp eax,257
  939.         sbb edx,edx
  940.         and eax,edx
  941.         jz loadxm_R
  942. endif
  943.         mul ecx
  944.         mov [ebp+loadxm_count2],eax
  945.         lea eax,[eax+eax*4] ; x SIZE FMUSIC_NOTE
  946.         ; numbytes : EAX
  947.         call alloc
  948.         mov [edi+FMUSIC_PATTERN.data],eax
  949.         xchg eax,ebx
  950. loadxm_for_rowsxchan:
  951.         push esi
  952.         mov esi,[uFMOD_fread]
  953.         xor edx,edx
  954.         lea eax,[ebp+loadxm_skip]
  955.         inc edx
  956.         ; buf  : EAX
  957.         ; size : EDX
  958.         call esi ; uFMOD_fread
  959.         movzx edx,BYTE PTR [ebp+loadxm_skip]
  960.         test dl,80h
  961.         jz loadxm_noskip
  962.         and edx,1
  963.         jz loadxm_nonote
  964.         mov eax,ebx ; &nptr->note
  965.         ; buf  : EAX
  966.         ; size : EDX
  967.         call esi ; uFMOD_fread
  968. loadxm_nonote:
  969.         test BYTE PTR [ebp+loadxm_skip],2
  970.         jz loadxm_nonumber
  971.         xor edx,edx
  972.         lea eax,[ebx+1] ; &nptr->number
  973.         inc edx
  974.         ; buf  : EAX
  975.         ; size : EDX
  976.         call esi ; uFMOD_fread
  977. loadxm_nonumber:
  978.         test BYTE PTR [ebp+loadxm_skip],4
  979.         jz loadxm_novolume
  980.         xor edx,edx
  981.         lea eax,[ebx+2] ; &nptr->volume
  982.         inc edx
  983.         ; buf  : EAX
  984.         ; size : EDX
  985.         call esi ; uFMOD_fread
  986. loadxm_novolume:
  987.         test BYTE PTR [ebp+loadxm_skip],8
  988.         jz loadxm_noeffect
  989.         xor edx,edx
  990.         lea eax,[ebx+3] ; &nptr->effect
  991.         inc edx
  992.         ; buf  : EAX
  993.         ; size : EDX
  994.         call esi ; uFMOD_fread
  995. loadxm_noeffect:
  996.         test BYTE PTR [ebp+loadxm_skip],16
  997.         jz loadxm_isnote97
  998.         xor edx,edx
  999.         lea eax,[ebx+4] ; &nptr->eparam
  1000.         inc edx
  1001.         jmp loadxm_skip_read
  1002. loadxm_noskip:
  1003.         test edx,edx
  1004.         jz loadxm_skip_z
  1005.         mov [ebx],dl
  1006. loadxm_skip_z:
  1007.         lea eax,[ebx+1]
  1008.         mov dl,4
  1009. loadxm_skip_read:
  1010.         ; buf  : EAX
  1011.         ; size : EDX
  1012.         call esi ; uFMOD_fread
  1013. loadxm_isnote97:
  1014.         pop esi
  1015.         inc ebx
  1016.         mov dl,BYTE PTR [esi+FMUSIC_MODULE.numinsts]
  1017.         cmp [ebx],dl
  1018.         jbe loadxm_number_ok
  1019.         mov BYTE PTR [ebx],0
  1020. loadxm_number_ok:
  1021.         add ebx,4
  1022.         dec DWORD PTR [ebp+loadxm_count2]
  1023.         jnz loadxm_for_rowsxchan
  1024. loadxm_ldpats_continue:
  1025.         inc DWORD PTR [ebp+loadxm_count1]
  1026.         mov eax,[ebp+loadxm_fnumpat]
  1027.         add edi,8
  1028.         cmp eax,[ebp+loadxm_count1]
  1029.         ja loadxm_load_pats
  1030.         ; allocate and clean out any extra patterns
  1031.         mov ecx,[ebp+loadxm_numpat]
  1032.         cmp ecx,eax
  1033.         jb loadxm_extrapats_ok
  1034.         mov ebx,[esi] ; FMUSIC_MODULE.pattern
  1035.         mov eax,[esi+FMUSIC_MODULE.numchannels]
  1036.         push esi
  1037.         lea esi,[ebx+ecx*FMUSIC_PATTERN_size]
  1038.         lea edi,[eax+eax*4]
  1039.         shl edi,6 ; numchannels*64*SIZE FMUSIC_NOTE
  1040. loadxm_for_extrapats:
  1041.         dec DWORD PTR [ebp+loadxm_numpat]
  1042.         mov eax,edi
  1043.         mov BYTE PTR [esi],64 ; pptr->rows = 64
  1044.         ; Allocate memory for pattern buffer
  1045.         ; numbytes : EAX
  1046.         call alloc
  1047.         mov [esi+FMUSIC_PATTERN.data],eax
  1048.         sub esi,FMUSIC_PATTERN_size
  1049.         mov eax,[ebp+loadxm_fnumpat]
  1050.         cmp [ebp+loadxm_numpat],eax
  1051.         jae loadxm_for_extrapats
  1052.         pop esi
  1053. loadxm_extrapats_ok:
  1054.         xor eax,eax
  1055.         mov [esi+FMUSIC_MODULE.mixer_samplesleft],eax
  1056.         mov [esi+FMUSIC_MODULE.tick],eax
  1057. if PATTERNDELAY_ON
  1058.         lea edi,[esi+FMUSIC_MODULE.patterndelay]
  1059.         stosd
  1060. else
  1061.         lea edi,[esi+FMUSIC_MODULE.nextorder]
  1062. endif
  1063.         stosd
  1064.         stosd
  1065.         ; Load instrument information
  1066.         mov al,BYTE PTR [esi+FMUSIC_MODULE.numinsts]
  1067.         test al,al
  1068.         jz loadxm_ret1
  1069.         mov [ebp+loadxm_count1],al
  1070.         mov ebx,[esi+FMUSIC_MODULE.instrument]
  1071. loadxm_for_instrs:
  1072.         push 33
  1073.         lea eax,[ebp+loadxm_tmp]
  1074.         pop edx
  1075.         ; buf  : EAX
  1076.         ; size : EDX
  1077.         call [uFMOD_fread] ; instrument size & name
  1078.         mov esi,[ebp+loadxm_tmp] ; firstsampleoffset = tmp[0]
  1079.         mov dl,[ebp+loadxm_tmp27]
  1080.         sub esi,33
  1081.         test dl,dl
  1082.         jz loadxm_inst_ok
  1083. if CHK4VALIDITY
  1084.         xor eax,eax
  1085.         cmp DWORD PTR [ebp+loadxm_tmp29],41
  1086.         sbb ecx,ecx
  1087.         not ecx
  1088.         or edx,ecx
  1089.         cmp dl,16
  1090.         ja loadxm_R ; if(numsamples > 16) goto error
  1091. endif
  1092.         mov edx,208
  1093.         lea eax,[ebx+FMUSIC_INSTRUMENT.keymap]
  1094.         sub esi,edx
  1095.         ; buf  : EAX
  1096.         ; size : EDX
  1097.         call [uFMOD_fread]
  1098. loadxm_inst_ok:
  1099.         xor ecx,ecx
  1100.         xchg eax,esi
  1101.         inc ecx ; SEEK_CUR
  1102.         ; pos  : EAX
  1103.         ; org  : ECX
  1104.         ; !org : Z
  1105.         call uFMOD_lseek
  1106.         lea edx,[ebx+FMUSIC_INSTRUMENT.VOLfade]
  1107.         xor eax,eax
  1108.         mov cx,[edx]
  1109.         shl ecx,1
  1110.         cmp BYTE PTR [edx+FMUSIC_INSTRUMENT.VOLnumpoints-FMUSIC_INSTRUMENT.VOLfade],2
  1111.         mov [edx],cx ; iptr->VOLfade *= 2
  1112.         jnb ladxm_voltype_ok
  1113.         mov BYTE PTR [edx+FMUSIC_INSTRUMENT.VOLtype-FMUSIC_INSTRUMENT.VOLfade],al
  1114. ladxm_voltype_ok:
  1115.         cmp BYTE PTR [edx+FMUSIC_INSTRUMENT.PANnumpoints-FMUSIC_INSTRUMENT.VOLfade],2
  1116.         jnb loadxm_PANtype_ok
  1117.         mov BYTE PTR [edx+FMUSIC_INSTRUMENT.PANtype-FMUSIC_INSTRUMENT.VOLfade],al
  1118. loadxm_PANtype_ok:
  1119.         cmp [ebp+loadxm_tmp27],al
  1120.         je loadx_for_loadsamp_end
  1121.         mov [ebp+loadxm_numpat],eax
  1122.         mov [ebp+loadxm_fnumpat],ebx ; FMUSIC_INSTRUMENT.sample
  1123. loadxm_for_samp:
  1124.         lea eax,[ebp+loadxm_sample_2]
  1125.         mov edx,[ebp+loadxm_tmp29]
  1126.         ; buf  : EAX
  1127.         ; size : EDX
  1128.         call [uFMOD_fread]
  1129.         mov esi,[ebp+loadxm_s0loopstart]
  1130.         mov edi,[ebp+loadxm_s0looplen]
  1131.         mov al,[ebp+loadxm_s0bytes]
  1132.         mov ecx,eax
  1133.         shr eax,4 ; sample[0].bytes >>= 4
  1134.         and al,1  ; [b 4] : 8/16 bit sample data
  1135.         mov [ebp+loadxm_s0bytes],al
  1136.         jz loadxm_s0bytes_ok
  1137.         shr DWORD PTR [ebp+loadxm_sample_2],1
  1138.         shr esi,1
  1139.         shr edi,1
  1140. loadxm_s0bytes_ok:
  1141.         mov eax,[ebp+loadxm_sample_2]
  1142.         cmp eax,esi
  1143.         jg loadxm_loopstart_ok
  1144.         mov esi,eax
  1145. loadxm_loopstart_ok:
  1146.         lea edx,[esi+edi]
  1147.         sub edx,eax
  1148.         js loadxm_looplen_ok
  1149.         sub edi,edx
  1150. loadxm_looplen_ok:
  1151.         and ecx,3 ; [b 0-1] : loop type
  1152.         jz loadxm_reset_sample
  1153.         test edi,edi
  1154.         jnz loadxm_s0loop_ok
  1155. loadxm_reset_sample:
  1156.         xor esi,esi
  1157.         xor ecx,ecx
  1158.         mov edi,eax
  1159. loadxm_s0loop_ok:
  1160.         mov [ebp+loadxm_s0loopstart],esi
  1161.         mov [ebp+loadxm_s0looplen],edi
  1162.         mov [ebp+loadxm_s0loopmode],cl
  1163.         lea eax,[eax+eax+26] ; sample[0].length*2+SIZE FSOUND_SAMPLE+4
  1164.         ; numbytes : EAX
  1165.         call alloc
  1166.         mov ecx,[ebp+loadxm_fnumpat]
  1167.         mov [ecx],eax
  1168.         ; memcpy(iptr->sample[count2],sample,sizeof(FSOUND_SAMPLE))
  1169.         inc DWORD PTR [ebp+loadxm_numpat]
  1170.         add DWORD PTR [ebp+loadxm_fnumpat],4
  1171.         push 5
  1172.         xchg eax,edi
  1173.         mov eax,[ebp+loadxm_numpat]
  1174.         pop ecx
  1175.         cmp al,[ebp+loadxm_tmp27]
  1176.         lea esi,[ebp+loadxm_sample_2]
  1177.         rep movsd
  1178.         jb loadxm_for_samp
  1179.         ; Load sample data
  1180.         mov [ebp+loadxm_numpat],ecx
  1181.         ; ebx <- FMUSIC_INSTRUMENT.sample
  1182. loadx_for_loadsamp:
  1183.         mov esi,[ebx+ecx*4]
  1184.         xor eax,eax
  1185.         mov edx,[esi]
  1186.         mov ch,[esi+FSOUND_SAMPLE.Resved]
  1187.         mov cl,[esi+FSOUND_SAMPLE.bytes]
  1188. if CHK4VALIDITY
  1189.         test edx,0FFC00000h
  1190.         jnz loadxm_R
  1191. endif
  1192.         add esi,FSOUND_SAMPLE.buff
  1193. if ADPCM_ON
  1194.         cmp ch,0ADh ; ModPlug 4-bit ADPCM
  1195.         jne loadxm_regular_samp
  1196.         inc edx
  1197.         mov edi,esi
  1198.         sar edx,1
  1199.         push ebx
  1200.         push edx
  1201.         lea edx,[edx+edx*2]
  1202.         add edi,edx ; ptr = buff+compressed_length*3
  1203.         ; Read in the compression table
  1204.         lea edx,[eax+16] ; edx = 16
  1205.         lea eax,[ebp+loadxm_sample_2]
  1206.         mov ebx,eax
  1207.         ; buf  : EAX
  1208.         ; size : EDX
  1209.         call [uFMOD_fread]
  1210.         ; Read in the sample data
  1211.         pop edx
  1212.         mov eax,edi
  1213.         ; buf  : EAX
  1214.         ; size : EDX
  1215.         call [uFMOD_fread]
  1216.         ; Decompress sample data
  1217.         mov edx,esi
  1218.         xor ecx,ecx ; delta
  1219. loadxm_unpack_loop:
  1220.         cmp edx,edi
  1221.         jge loadxm_unpack_ok
  1222.         mov al,[edi]
  1223.         mov ah,al
  1224.         and al,0Fh
  1225.         xlatb
  1226.         shr ah,4
  1227.         inc edi
  1228.         add ch,al
  1229.         mov al,ah
  1230.         xlatb
  1231.         add al,ch
  1232.         shl eax,24
  1233.         or ecx,eax
  1234.         mov [edx],ecx
  1235.         shr ecx,16 ; ch <- delta
  1236.         add edx,4
  1237.         jmp loadxm_unpack_loop
  1238. loadxm_unpack_ok:
  1239.         pop ebx
  1240.         jmp loadxm_chk_loop_bidi
  1241. loadxm_regular_samp:
  1242. endif
  1243.         shl edx,cl ; sptr->length << sptr->bytes
  1244.         mov eax,esi
  1245.         ; buf  : EAX
  1246.         ; size : EDX
  1247.         call [uFMOD_fread]
  1248.         mov ecx,DWORD PTR [esi+FSOUND_SAMPLE._length-FSOUND_SAMPLE.buff]
  1249.         lea edi,[ecx+esi] ; buff = sptr->buff+sptr->length
  1250.         lea eax,[edi+ecx] ; ptr  = buff+sptr->length
  1251.         xor edx,edx
  1252.         cmp BYTE PTR [esi+FSOUND_SAMPLE.bytes-FSOUND_SAMPLE.buff],dl
  1253.         jne loadxm_16bit_ok
  1254.         ; Promote to 16 bits
  1255. loadxm_to16bits:
  1256.         dec eax
  1257.         dec edi
  1258.         dec eax
  1259.         mov dh,[edi]
  1260.         cmp eax,edi
  1261.         mov [eax],dx
  1262.         ja loadxm_to16bits
  1263.         xor edx,edx
  1264. loadxm_16bit_ok:
  1265.         mov eax,esi
  1266.         ; Do delta conversion
  1267. loadxm_do_delta_conv:
  1268.         add dx,[eax]
  1269.         mov [eax],dx
  1270.         dec ecx
  1271.         lea eax,[eax+2]
  1272.         jg loadxm_do_delta_conv
  1273.         js loadxm_loops_ok
  1274. loadxm_chk_loop_bidi:
  1275.         mov eax,DWORD PTR [esi+FSOUND_SAMPLE.looplen-FSOUND_SAMPLE.buff]
  1276.         mov ecx,DWORD PTR [esi+FSOUND_SAMPLE.loopstart-FSOUND_SAMPLE.buff]
  1277.         add eax,ecx
  1278.         cmp BYTE PTR [esi+FSOUND_SAMPLE.loopmode-FSOUND_SAMPLE.buff],2 ; LOOP_BIDI
  1279.         lea eax,[esi+eax*2]
  1280.         jnz loadxm_chk_loop_normal
  1281.         mov cx,[eax-2]
  1282.         jmp loadxm_fix_loop
  1283. loadxm_chk_loop_normal:
  1284.         cmp BYTE PTR [esi+FSOUND_SAMPLE.loopmode-FSOUND_SAMPLE.buff],1 ; LOOP_NORMAL
  1285.         jnz loadxm_loops_ok
  1286.         mov cx,WORD PTR [esi+ecx*2]
  1287. loadxm_fix_loop:
  1288.         mov [eax],cx
  1289. loadxm_loops_ok:
  1290.         inc DWORD PTR [ebp+loadxm_numpat]
  1291.         mov ecx,[ebp+loadxm_numpat]
  1292.         cmp cl,[ebp+loadxm_tmp27]
  1293.         jb loadx_for_loadsamp
  1294. loadx_for_loadsamp_end:
  1295.         add ebx,FMUSIC_INSTRUMENT_size
  1296.         dec BYTE PTR [ebp+loadxm_count1]
  1297.         jnz loadxm_for_instrs
  1298. loadxm_ret1:
  1299.         inc eax
  1300. loadxm_R:
  1301.         pop ebx
  1302. donote_R:
  1303.         leave
  1304.         ret
  1305.  
  1306. DoNote:
  1307. ; mod+36 = ESI
  1308. var_mod         equ -4
  1309. donote_sptr     equ -8
  1310. donote_jumpflag equ -10
  1311. donote_porta    equ -12
  1312. donote_oldpan   equ -16
  1313. donote_currtick equ -20
  1314. donote_oldfreq  equ -24
  1315. donote_iptr     equ -28
  1316.         ; Point our note pointer to the correct pattern buffer, and to the
  1317.         ; correct offset in this buffer indicated by row and number of channels
  1318.         mov eax,[esi+FMUSIC_MODULE.order-36]
  1319.         push ebp
  1320.         movzx ebx,BYTE PTR [eax+esi+FMUSIC_MODULE.orderlist-36]
  1321.         mov ebp,esp
  1322.         mov eax,[esi+FMUSIC_MODULE.row-36]
  1323.         lea ebx,[ecx+ebx*FMUSIC_PATTERN_size]
  1324.         mov ecx,[esi+FMUSIC_MODULE.numchannels-36]
  1325. if PATTERNBREAK_ON
  1326.         if PATTERNJUMP_ON
  1327.                 mov BYTE PTR [ebp+donote_jumpflag],ch
  1328.         endif
  1329. endif
  1330.         mul ecx
  1331.         lea edi,[eax+eax*4] ; x SIZE FMUSIC_NOTE
  1332.         push esi
  1333.         add edi,[ebx+FMUSIC_PATTERN.data] ; mod->pattern[mod->orderlist[mod->order]].data+(mod->row*mod->numchannels)
  1334.         sub esp,24
  1335.         ; Loop through each channel in the row
  1336.         shl ecx,7 ; x FMUSIC_CHANNEL_size
  1337.         jz donote_R
  1338.         push esi
  1339.         mov esi,[esi+FMUSIC_MODULE.uFMOD_Ch-36]
  1340.         push ebx
  1341.         inc esi
  1342.         inc esi
  1343.         add ecx,esi
  1344. donote_for_channels:
  1345.         push ecx
  1346.         mov bl,[edi+FMUSIC_NOTE.eparam]
  1347.         mov al,[edi+FMUSIC_NOTE.effect]
  1348.         and ebx,0Fh
  1349.         cmp al,FMUSIC_XM_PORTATO
  1350.         je donote_doporta
  1351.         cmp al,FMUSIC_XM_PORTATOVOLSLIDE
  1352. donote_doporta:
  1353.         setz [ebp+donote_porta]
  1354.         ; First store note and instrument number if there was one
  1355.         mov cl,[edi+FMUSIC_NOTE.number]
  1356.         jz donote_rem_note
  1357.         dec cl
  1358.         js donote_rem_inst
  1359.         mov [esi+FMUSIC_CHANNEL.inst-2],cl ; remember the instrument #
  1360. donote_rem_inst:
  1361.         mov cl,[edi] ; get current note
  1362.         dec ecx
  1363.         cmp cl,96
  1364.         jae donote_rem_note
  1365.         mov [esi+FMUSIC_CHANNEL.note-2],cl ; remember the note
  1366. donote_rem_note:
  1367.         movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.inst-2]
  1368.         mov eax,[ebp+var_mod]
  1369.         imul ecx,FMUSIC_INSTRUMENT_size
  1370.         add ecx,[eax+FMUSIC_MODULE.instrument-36]
  1371.         movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.note-2]
  1372.         cdq
  1373.         mov al,[eax+ecx+FMUSIC_INSTRUMENT.keymap]
  1374.         cmp al,16
  1375.         mov [ebp+donote_iptr],ecx
  1376.         jae donote_set_sptr
  1377.         mov edx,[ecx+eax*4+FMUSIC_INSTRUMENT.sample]
  1378. donote_set_sptr:
  1379.         test edx,edx
  1380.         jnz donote_valid_sptr
  1381.         mov edx,OFFSET DummySamp
  1382. donote_valid_sptr:
  1383.         mov [ebp+donote_sptr],edx
  1384. if NOTEDELAY_ON
  1385.         mov ecx,[esi+FMUSIC_CHANNEL.freq-2]
  1386.         mov eax,[esi+FMUSIC_CHANNEL.volume-2]
  1387.         mov [ebp+donote_oldfreq],ecx
  1388.         mov ecx,[esi+FMUSIC_CHANNEL.pan-2]
  1389.         mov [ebp+donote_currtick],eax
  1390.         mov [ebp+donote_oldpan],ecx
  1391. endif
  1392. if TREMOLO_ON
  1393.         ; if there is no more tremolo, set volume to volume + last tremolo delta
  1394.         mov al,[edi+FMUSIC_NOTE.effect]
  1395.         cmp al,FMUSIC_XM_TREMOLO
  1396.         je donote_tremolo_vol
  1397.         cmp BYTE PTR [esi+FMUSIC_CHANNEL.recenteffect-2],FMUSIC_XM_TREMOLO
  1398.         jne donote_tremolo_vol
  1399.         mov ecx,[esi+FMUSIC_CHANNEL.voldelta-2]
  1400.         add [esi+FMUSIC_CHANNEL.volume-2],ecx
  1401. donote_tremolo_vol:
  1402.         mov [esi+FMUSIC_CHANNEL.recenteffect-2],al
  1403. endif
  1404.         xor ecx,ecx
  1405.         mov [esi+FMUSIC_CHANNEL.voldelta-2],ecx
  1406.         mov [esi+FMUSIC_CHANNEL.freqdelta-2],ecx
  1407.         mov BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME_OR_FREQ
  1408.         ; PROCESS NOTE
  1409.         mov cl,[edi] ; note
  1410.         dec ecx
  1411.         cmp cl,96
  1412.         jae donote_note_ok
  1413.         ; get note according to relative note
  1414.         movsx eax,BYTE PTR [edx+FSOUND_SAMPLE.relative]
  1415.         add ecx,eax
  1416.         mov eax,[ebp+var_mod]
  1417.         mov [esi+FMUSIC_CHANNEL.realnote-2],cl
  1418.         ; Get period according to realnote and finetune
  1419.         test BYTE PTR [eax+FMUSIC_MODULE.flags-36],1
  1420.         je donote_flagsn1
  1421.         mov eax,[ebp+donote_sptr]
  1422.         movsx eax,BYTE PTR [eax+FSOUND_SAMPLE.finetune]
  1423.         cdq
  1424.         shl ecx,6
  1425.         sub eax,edx
  1426.         sar eax,1
  1427.         lea eax,[ecx+eax-7680]
  1428.         neg eax
  1429. if AMIGAPERIODS_ON
  1430.         jmp donote_chk_porta
  1431. donote_flagsn1:
  1432.         xchg eax,ecx              ; note   : EAX
  1433.         mov ecx,[ebp+donote_sptr] ; [sptr] : ECX
  1434.         ; ESI != 0
  1435.         call AmigaPeriod
  1436. donote_chk_porta:
  1437.         mov [esi+FMUSIC_CHANNEL.period-2],eax
  1438. else
  1439.         mov [esi+FMUSIC_CHANNEL.period-2],eax
  1440. donote_flagsn1:
  1441.         mov eax,[esi+FMUSIC_CHANNEL.period-2]
  1442. endif
  1443.         ; Frequency only changes if there are no portamento effects
  1444.         cmp BYTE PTR [ebp+donote_porta],0
  1445.         jne donote_freq_ok
  1446.         mov [esi+FMUSIC_CHANNEL.freq-2],eax
  1447. donote_freq_ok:
  1448.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_TRIGGER
  1449. donote_note_ok:
  1450.         ; PROCESS INSTRUMENT NUMBER
  1451.         cmp BYTE PTR [edi+FMUSIC_NOTE.number],0
  1452.         je donote_zcptr_ok
  1453.         mov eax,[ebp+donote_sptr]
  1454.         ; DESCRIPTION: Reset current channel
  1455.         push edi
  1456.         push 9
  1457.         movzx ecx,BYTE PTR [eax+FSOUND_SAMPLE.defvol]
  1458.         mov [esi+FMUSIC_CHANNEL.volume-2],ecx
  1459.         pop ecx
  1460.         movzx eax,BYTE PTR [eax+FSOUND_SAMPLE.defpan]
  1461.         mov [esi+FMUSIC_CHANNEL.pan-2],eax
  1462.         push 64
  1463.         xor eax,eax
  1464.         pop DWORD PTR [esi+FMUSIC_CHANNEL.envvol-2]
  1465.         push 32
  1466.         lea edi,[esi+FMUSIC_CHANNEL.envvoltick-2]
  1467.         pop DWORD PTR [esi+FMUSIC_CHANNEL.envpan-2]
  1468.         mov DWORD PTR [esi+FMUSIC_CHANNEL.fadeoutvol-2],65536
  1469.         ; memset(&cptr->envvoltick,0,36)
  1470.         rep stosd
  1471.         ; Retrigger tremolo and vibrato waveforms
  1472.         mov cl,[esi+FMUSIC_CHANNEL.wavecontrol-2]
  1473.         pop edi
  1474.         cmp cl,4Fh
  1475.         jge z_tremolopos_ok
  1476.         mov BYTE PTR [esi+FMUSIC_CHANNEL.tremolopos-2],al ; = 0
  1477. z_tremolopos_ok:
  1478.         test cl,0Ch
  1479.         jnz z_vibpos_ok
  1480.         mov BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2],al ; = 0
  1481. z_vibpos_ok:
  1482.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME_OR_PAN
  1483. donote_zcptr_ok:
  1484. if VOLUMEBYTE_ON
  1485.         ; PROCESS VOLUME BYTE
  1486.         movzx edx,BYTE PTR [edi+FMUSIC_NOTE.uvolume]
  1487.         ; volume : EDX
  1488.         ; cptr+2 : ESI
  1489.         call VolByte
  1490. endif
  1491.         ; PROCESS KEY OFF
  1492.         cmp BYTE PTR [edi],97 ; note
  1493.         jae donote_set_keyoff
  1494.         cmp BYTE PTR [edi+FMUSIC_NOTE.effect],FMUSIC_XM_KEYOFF
  1495.         jne donote_keyoff_ok
  1496. donote_set_keyoff:
  1497.         inc BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2]
  1498. donote_keyoff_ok:
  1499.         ; PROCESS ENVELOPES
  1500. if VOLUMEENVELOPE_ON
  1501.         mov ecx,[ebp+donote_iptr]
  1502.         test BYTE PTR [ecx+FMUSIC_INSTRUMENT.VOLtype],1
  1503.         jz donote_no_voltype
  1504.         mov al,FMUSIC_VOLUME
  1505.         ; cptr+2   : ESI
  1506.         ; env_iptr : ECX
  1507.         ; control  : AL
  1508.         call Envelope
  1509.         jmp donote_volenv_ok
  1510. donote_no_voltype:
  1511. endif
  1512.         cmp BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2],0
  1513.         je donote_volenv_ok
  1514.         and DWORD PTR [esi+FMUSIC_CHANNEL.envvol-2],0
  1515. donote_volenv_ok:
  1516. if PANENVELOPE_ON
  1517.         mov ecx,[ebp+donote_iptr]
  1518.         test BYTE PTR [ecx+FMUSIC_INSTRUMENT.PANtype],1
  1519.         je donote_no_pantype
  1520.         mov al,FMUSIC_PAN
  1521.         ; cptr+2   : ESI
  1522.         ; env_iptr : ECX
  1523.         ; control  : AL
  1524.         call Envelope
  1525. donote_no_pantype:
  1526. endif
  1527.         ; PROCESS VOLUME FADEOUT
  1528.         cmp BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2],0
  1529.         mov ecx,[ebp+donote_iptr]
  1530.         je donote_fadevol_ok
  1531.         movzx eax,WORD PTR [ecx+FMUSIC_INSTRUMENT.VOLfade]
  1532.         sub [esi+FMUSIC_CHANNEL.fadeoutvol-2],eax
  1533.         jns donote_fadevol_ok
  1534.         and DWORD PTR [esi+FMUSIC_CHANNEL.fadeoutvol-2],0
  1535. donote_fadevol_ok:
  1536.         ; PROCESS TICK 0 EFFECTS
  1537.         movzx eax,BYTE PTR [edi+FMUSIC_NOTE.effect]
  1538.         dec eax ; skip FMUSIC_XM_ARPEGGIO
  1539.         movzx edx,BYTE PTR [edi+FMUSIC_NOTE.eparam]
  1540. if EXTRAFINEPORTA_ON
  1541.         cmp al,32
  1542. else
  1543.         if TREMOR_ON
  1544.                 cmp al,28
  1545.         else
  1546.                 if MULTIRETRIG_ON
  1547.                         cmp al,26
  1548.                 else
  1549.                         if PANSLIDE_ON
  1550.                                 cmp al,24
  1551.                         else
  1552.                                 if SETENVELOPEPOS_ON
  1553.                                         cmp al,20
  1554.                                 else
  1555.                                         if GLOBALVOLSLIDE_ON
  1556.                                                 cmp al,16
  1557.                                         else
  1558.                                                 if SETGLOBALVOLUME_ON
  1559.                                                         cmp al,15
  1560.                                                 else
  1561.                                                         if SETSPEED_ON
  1562.                                                                 cmp al,14
  1563.                                                         else
  1564.                                                                 cmp al,13
  1565.                                                         endif
  1566.                                                 endif
  1567.                                         endif
  1568.                                 endif
  1569.                         endif
  1570.                 endif
  1571.         endif
  1572. endif
  1573.         ja donote_s1_brk
  1574.         test edx,edx
  1575.         call DWORD PTR [eax*4+S1_TBL]
  1576. donote_s1_brk:
  1577. if INSTRUMENTVIBRATO_ON
  1578.         push DWORD PTR [ebp+donote_iptr]
  1579. endif
  1580.         push DWORD PTR [ebp+donote_sptr]
  1581.         ; cptr+2 : ESI
  1582.         call DoFlags
  1583.         sub esi,-(FMUSIC_CHANNEL_size)
  1584.         pop ecx
  1585.         add edi,FMUSIC_NOTE_size
  1586.         cmp esi,ecx
  1587.         jl donote_for_channels
  1588.         pop ebx
  1589.         pop esi
  1590.         leave
  1591. S1_r:
  1592.         ret
  1593. S1_TBL:
  1594. if PORTAUP_OR_DOWN_ON
  1595.         dd S1_C1
  1596.         dd S1_C1
  1597. else
  1598.         dd S1_r
  1599.         dd S1_r
  1600. endif
  1601. if PORTATO_ON
  1602.         dd S1_C3
  1603. else
  1604.         dd S1_r
  1605. endif
  1606. if VIBRATO_ON
  1607.         dd S1_C4
  1608. else
  1609.         dd S1_r
  1610. endif
  1611. if PORTATOVOLSLIDE_ON
  1612.         dd S1_C5
  1613. else
  1614.         dd S1_r
  1615. endif
  1616. if VIBRATOVOLSLIDE_ON
  1617.         dd S1_C6
  1618. else
  1619.         dd S1_r
  1620. endif
  1621. if TREMOLO_ON
  1622.         dd S1_C7
  1623. else
  1624.         dd S1_r
  1625. endif
  1626. if SETPANPOSITION_ON
  1627.         dd S1_C8
  1628. else
  1629.         dd S1_r
  1630. endif
  1631. if SETSAMPLEOFFSET_ON
  1632.         dd S1_C9
  1633. else
  1634.         dd S1_r
  1635. endif
  1636. if VOLUMESLIDE_ON
  1637.         dd S1_C10
  1638. else
  1639.         dd S1_r
  1640. endif
  1641. if PATTERNJUMP_ON
  1642.         dd S1_C11
  1643. else
  1644.         dd S1_r
  1645. endif
  1646. if SETVOLUME_ON
  1647.         dd S1_C12
  1648. else
  1649.         dd S1_r
  1650. endif
  1651. if PATTERNBREAK_ON
  1652.         dd S1_C13
  1653. else
  1654.         dd S1_r
  1655. endif
  1656.         dd S1_C14
  1657. if EXTRAFINEPORTA_ON
  1658.         if SETSPEED_ON
  1659.                 dd S1_C15
  1660.         else
  1661.                 dd S1_r
  1662.         endif
  1663.         if SETGLOBALVOLUME_ON
  1664.                 dd S1_C16
  1665.         else
  1666.                 dd S1_r
  1667.         endif
  1668.         if GLOBALVOLSLIDE_ON
  1669.                 dd S1_C17
  1670.         else
  1671.                 dd S1_r
  1672.         endif
  1673.         dd S1_r ; unassigned effect ordinal [18]
  1674.         dd S1_r ; unassigned effect ordinal [19]
  1675.         dd S1_r ; skip FMUSIC_XM_KEYOFF
  1676.         if SETENVELOPEPOS_ON
  1677.                 dd S1_C21
  1678.         else
  1679.                 dd S1_r
  1680.         endif
  1681.         dd S1_r ; unassigned effect ordinal [22]
  1682.         dd S1_r ; unassigned effect ordinal [23]
  1683.         dd S1_r ; unassigned effect ordinal [24]
  1684.         if PANSLIDE_ON
  1685.                 dd S1_C25
  1686.         else
  1687.                 dd S1_r
  1688.         endif
  1689.         dd S1_r ; unassigned effect ordinal [26]
  1690.         if MULTIRETRIG_ON
  1691.                 dd S1_C27
  1692.         else
  1693.                 dd S1_r
  1694.         endif
  1695.         dd S1_r ; unassigned effect ordinal [28]
  1696.         if TREMOR_ON
  1697.                 dd S1_C29
  1698.         else
  1699.                 dd S1_r
  1700.         endif
  1701.         dd S1_r ; unassigned effect ordinal [30]
  1702.         dd S1_r ; unassigned effect ordinal [31]
  1703.         dd S1_r ; unassigned effect ordinal [32]
  1704.         dd S1_C33
  1705. else
  1706.         if TREMOR_ON
  1707.                 if SETSPEED_ON
  1708.                         dd S1_C15
  1709.                 else
  1710.                         dd S1_r
  1711.                 endif
  1712.                 if SETGLOBALVOLUME_ON
  1713.                         dd S1_C16
  1714.                 else
  1715.                         dd S1_r
  1716.                 endif
  1717.                 if GLOBALVOLSLIDE_ON
  1718.                         dd S1_C17
  1719.                 else
  1720.                         dd S1_r
  1721.                 endif
  1722.                 dd S1_r
  1723.                 dd S1_r
  1724.                 dd S1_r
  1725.                 if SETENVELOPEPOS_ON
  1726.                         dd S1_C21
  1727.                 else
  1728.                         dd S1_r
  1729.                 endif
  1730.                 dd S1_r
  1731.                 dd S1_r
  1732.                 dd S1_r
  1733.                 if PANSLIDE_ON
  1734.                         dd S1_C25
  1735.                 else
  1736.                         dd S1_r
  1737.                 endif
  1738.                 dd S1_r
  1739.                 if MULTIRETRIG_ON
  1740.                         dd S1_C27
  1741.                 else
  1742.                         dd S1_r
  1743.                 endif
  1744.                 dd S1_r
  1745.                 dd S1_C29
  1746.         else
  1747.                 if MULTIRETRIG_ON
  1748.                         if SETSPEED_ON
  1749.                                 dd S1_C15
  1750.                         else
  1751.                                 dd S1_r
  1752.                         endif
  1753.                         if SETGLOBALVOLUME_ON
  1754.                                 dd S1_C16
  1755.                         else
  1756.                                 dd S1_r
  1757.                         endif
  1758.                         if GLOBALVOLSLIDE_ON
  1759.                                 dd S1_C17
  1760.                         else
  1761.                                 dd S1_r
  1762.                         endif
  1763.                         dd S1_r
  1764.                         dd S1_r
  1765.                         dd S1_r
  1766.                         if SETENVELOPEPOS_ON
  1767.                                 dd S1_C21
  1768.                         else
  1769.                                 dd S1_r
  1770.                         endif
  1771.                         dd S1_r
  1772.                         dd S1_r
  1773.                         dd S1_r
  1774.                         if PANSLIDE_ON
  1775.                                 dd S1_C25
  1776.                         else
  1777.                                 dd S1_r
  1778.                         endif
  1779.                         dd S1_r
  1780.                         dd S1_C27
  1781.                 else
  1782.                         if PANSLIDE_ON
  1783.                                 if SETSPEED_ON
  1784.                                         dd S1_C15
  1785.                                 else
  1786.                                         dd S1_r
  1787.                                 endif
  1788.                                 if SETGLOBALVOLUME_ON
  1789.                                         dd S1_C16
  1790.                                 else
  1791.                                         dd S1_r
  1792.                                 endif
  1793.                                 if GLOBALVOLSLIDE_ON
  1794.                                         dd S1_C17
  1795.                                 else
  1796.                                         dd S1_r
  1797.                                 endif
  1798.                                 dd S1_r
  1799.                                 dd S1_r
  1800.                                 dd S1_r
  1801.                                 if SETENVELOPEPOS_ON
  1802.                                         dd S1_C21
  1803.                                 else
  1804.                                         dd S1_r
  1805.                                 endif
  1806.                                 dd S1_r
  1807.                                 dd S1_r
  1808.                                 dd S1_r
  1809.                                 dd S1_C25
  1810.                         else
  1811.                                 if SETENVELOPEPOS_ON
  1812.                                         if SETSPEED_ON
  1813.                                                 dd S1_C15
  1814.                                         else
  1815.                                                 dd S1_r
  1816.                                         endif
  1817.                                         if SETGLOBALVOLUME_ON
  1818.                                                 dd S1_C16
  1819.                                         else
  1820.                                                 dd S1_r
  1821.                                         endif
  1822.                                         if GLOBALVOLSLIDE_ON
  1823.                                                 dd S1_C17
  1824.                                         else
  1825.                                                 dd S1_r
  1826.                                         endif
  1827.                                         dd S1_r
  1828.                                         dd S1_r
  1829.                                         dd S1_r
  1830.                                         dd S1_C21
  1831.                                 else
  1832.                                         if GLOBALVOLSLIDE_ON
  1833.                                                 if SETSPEED_ON
  1834.                                                         dd S1_C15
  1835.                                                 else
  1836.                                                         dd S1_r
  1837.                                                 endif
  1838.                                                 if SETGLOBALVOLUME_ON
  1839.                                                         dd S1_C16
  1840.                                                 else
  1841.                                                         dd S1_r
  1842.                                                 endif
  1843.                                                 dd S1_C17
  1844.                                         else
  1845.                                                 if SETGLOBALVOLUME_ON
  1846.                                                         if SETSPEED_ON
  1847.                                                                 dd S1_C15
  1848.                                                         else
  1849.                                                                 dd S1_r
  1850.                                                         endif
  1851.                                                         dd S1_C16
  1852.                                                 else
  1853.                                                         if SETSPEED_ON
  1854.                                                                 dd S1_C15
  1855.                                                         endif
  1856.                                                 endif
  1857.                                         endif
  1858.                                 endif
  1859.                         endif
  1860.                 endif
  1861.         endif
  1862. endif
  1863. if PORTAUP_OR_DOWN_ON
  1864. S1_C1:
  1865.         jz donote_xm_porta_end
  1866.         mov [esi+FMUSIC_CHANNEL.portaupdown-2],dl
  1867. donote_xm_porta_end:
  1868.         ret
  1869. endif
  1870. if PORTATO_ON
  1871. S1_C3:
  1872.         jz donote_xm_portato_end
  1873.         mov [esi+FMUSIC_CHANNEL.portaspeed-2],dl
  1874. donote_xm_portato_end:
  1875. if PORTATOVOLSLIDE_ON
  1876.         jmp donote_xm_portavolsl_end
  1877. else
  1878.         mov eax,[esi+FMUSIC_CHANNEL.period-2]
  1879.         and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER_OR_FRQ
  1880.         mov [esi+FMUSIC_CHANNEL.portatarget-2],eax
  1881.         ret
  1882. endif
  1883. endif
  1884. if PORTATOVOLSLIDE_ON
  1885. S1_C5:
  1886.         jz donote_xm_portavolsl_end
  1887.         mov [esi+FMUSIC_CHANNEL.volslide-2],dl
  1888. donote_xm_portavolsl_end:
  1889.         mov eax,[esi+FMUSIC_CHANNEL.period-2]
  1890.         and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER_OR_FRQ
  1891.         mov [esi+FMUSIC_CHANNEL.portatarget-2],eax
  1892.         ret
  1893. endif
  1894. if VIBRATO_ON
  1895. S1_C4:
  1896.         shr edx,4
  1897.         jz donote_vib_x_ok
  1898.         mov [esi+FMUSIC_CHANNEL.vibspeed-2],dl
  1899. donote_vib_x_ok:
  1900.         test ebx,ebx
  1901.         jz donote_vib_y_ok
  1902.         mov BYTE PTR [esi+FMUSIC_CHANNEL.vibdepth-2],bl
  1903. donote_vib_y_ok:
  1904. if VIBRATOVOLSLIDE_ON
  1905.         xor eax,eax
  1906. else
  1907.         ; cptr+2 : ESI
  1908.         jmp Vibrato
  1909. endif
  1910. endif
  1911. if VIBRATOVOLSLIDE_ON
  1912. S1_C6:
  1913.         jz donote_xm_vibvolsl_end
  1914.         mov [esi+FMUSIC_CHANNEL.volslide-2],dl
  1915. donote_xm_vibvolsl_end:
  1916.         ; cptr+2 : ESI
  1917.         jmp Vibrato
  1918. endif
  1919. if TREMOLO_ON
  1920. S1_C7:
  1921.         shr edx,4
  1922.         jz donote_trem_x_ok
  1923.         mov [esi+FMUSIC_CHANNEL.tremolospeed-2],dl
  1924. donote_trem_x_ok:
  1925.         test ebx,ebx
  1926.         jz donote_trem_y_ok
  1927.         mov [esi+FMUSIC_CHANNEL.tremolodepth-2],bl
  1928. donote_trem_y_ok:
  1929.         ret
  1930. endif
  1931. if SETPANPOSITION_ON
  1932. if PANSLIDE_ON
  1933. else
  1934.         S1_C8:
  1935.                 mov [esi+FMUSIC_CHANNEL.pan-2],edx
  1936.                 or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
  1937.                 ret
  1938.         endif
  1939. endif
  1940. if SETSAMPLEOFFSET_ON
  1941. S1_C9:
  1942.         shl edx,8
  1943.         jz donote_soffset_ok
  1944.         mov [esi+FMUSIC_CHANNEL.sampleoffset-2],edx
  1945. donote_soffset_ok:
  1946.         mov ecx,[ebp+donote_sptr]
  1947.         mov edx,[ecx+FSOUND_SAMPLE.loopstart]
  1948.         add edx,[ecx+FSOUND_SAMPLE.looplen]
  1949.         mov eax,[esi+FMUSIC_CHANNEL.sampleoffset-2]
  1950.         cmp eax,edx
  1951.         mov ecx,[esi+FMUSIC_CHANNEL.cptr-2]
  1952.         jb donote_set_offset
  1953.         xor eax,eax
  1954.         and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER
  1955.         mov [ecx+FSOUND_CHANNEL.mixpos],eax
  1956.         mov [ecx+FSOUND_CHANNEL.mixposlo],eax
  1957. donote_set_offset:
  1958.         mov [ecx+FSOUND_CHANNEL.fsampleoffset],eax
  1959.         ret
  1960. endif
  1961. if VOLUMESLIDE_ON
  1962. S1_C10:
  1963.         jz donote_volslide_ok
  1964.         mov [esi+FMUSIC_CHANNEL.volslide-2],dl
  1965. donote_volslide_ok:
  1966.         ret
  1967. endif
  1968. if PATTERNJUMP_ON
  1969. S1_C11:
  1970.         mov eax,[ebp+var_mod]
  1971.         and DWORD PTR [eax+FMUSIC_MODULE.nextrow-36],0
  1972.         mov [eax+FMUSIC_MODULE.nextorder-36],edx
  1973. if PATTERNBREAK_ON
  1974.         inc BYTE PTR [ebp+donote_jumpflag]
  1975. donote_set_nextord:
  1976. endif
  1977.         movzx ecx,WORD PTR [eax+FMUSIC_MODULE.numorders-36]
  1978.         cmp [eax+FMUSIC_MODULE.nextorder-36],ecx
  1979.         jl donote_nextorder_ok
  1980.         and DWORD PTR [eax+FMUSIC_MODULE.nextorder-36],0
  1981. donote_nextorder_ok:
  1982.         ret
  1983. endif
  1984. if PATTERNBREAK_ON
  1985. S1_C13:
  1986.         shr edx,4
  1987.         lea edx,[edx+edx*4]
  1988.         lea ecx,[ebx+edx*2] ; paramx*10+paramy
  1989.         mov eax,[ebp+var_mod]
  1990.         mov [eax+FMUSIC_MODULE.nextrow-36],ecx
  1991. if PATTERNJUMP_ON
  1992.         cmp BYTE PTR [ebp+donote_jumpflag],0
  1993.         jne donote_nextorder_ok
  1994. endif
  1995.         mov ecx,[eax+FMUSIC_MODULE.order-36]
  1996.         inc ecx
  1997.         mov [eax+FMUSIC_MODULE.nextorder-36],ecx
  1998. if PATTERNJUMP_ON
  1999.         jmp donote_set_nextord
  2000. else
  2001.         movzx ecx,WORD PTR [eax+FMUSIC_MODULE.numorders-36]
  2002.         cmp [eax+FMUSIC_MODULE.nextorder-36],ecx
  2003.         jl donote_jump_pat
  2004.         and DWORD PTR [eax+FMUSIC_MODULE.nextorder-36],0
  2005. donote_jump_pat:
  2006.         ret
  2007. endif
  2008. endif
  2009. if SETSPEED_ON
  2010. S1_C15:
  2011.         cmp dl,20h
  2012.         mov ecx,edx
  2013.         jae donote_setbpm
  2014.         mov eax,[ebp+var_mod]
  2015.         mov [eax+FMUSIC_MODULE.speed-36],ecx
  2016.         ret
  2017. donote_setbpm:
  2018.         ; bpm : ECX
  2019.         jmp SetBPM
  2020. endif
  2021. if GLOBALVOLSLIDE_ON
  2022. S1_C17:
  2023.         jz donote_globalvsl_ok
  2024.         mov ecx,[ebp+var_mod]
  2025.         mov [ecx+FMUSIC_MODULE.globalvsl-36],dl
  2026. donote_globalvsl_ok:
  2027.         ret
  2028. endif
  2029. if SETENVELOPEPOS_ON
  2030. S1_C21:
  2031.         test BYTE PTR [ecx+FMUSIC_INSTRUMENT.VOLtype],1
  2032.         je donote_envelope_r
  2033.         lea ebx,[ecx+FMUSIC_INSTRUMENT.VOLPoints+4]
  2034.         ; Search and reinterpolate new envelope position
  2035.         movzx ecx,BYTE PTR [ecx+FMUSIC_INSTRUMENT.VOLnumpoints]
  2036.         xor eax,eax
  2037.         cmp dx,[ebx]
  2038.         jbe donote_env_endwhile
  2039. donote_envwhile:
  2040.         cmp eax,ecx ; if(currpos == iptr->VOLnumpoints) break
  2041.         je donote_env_endwhile
  2042.         inc eax
  2043.         cmp dx,[ebx+eax*4] ; if(current->eparam > iptr->VOLPoints[(currpos+1)<<1]) break
  2044.         ja donote_envwhile
  2045. donote_env_endwhile:
  2046.         mov [esi+FMUSIC_CHANNEL.envvolpos-2],eax
  2047.         ; if it is at the last position, abort the envelope and continue last volume
  2048.         dec ecx
  2049.         cmp eax,ecx
  2050.         setnl [esi+FMUSIC_CHANNEL.envvolstopped-2]
  2051.         jl donote_env_continue
  2052.         movzx eax,WORD PTR [ebx+ecx*4-2]
  2053.         mov [esi+FMUSIC_CHANNEL.envvol-2],eax ; cptr->envvol = iptr->VOLPoints[((iptr->VOLnumpoints-1)<<1)+1]
  2054. donote_envelope_r:
  2055.         ret
  2056. donote_env_continue:
  2057.         mov [esi+FMUSIC_CHANNEL.envvoltick-2],edx
  2058.         mov ecx,[ebx+eax*4-4] ; get tick at this point + VOL at this point
  2059.         mov edx,ecx
  2060.         movzx ecx,cx
  2061.         mov [ebp+donote_currtick],ecx
  2062.         mov ecx,[ebx+eax*4] ; get tick at next point + VOL at next point
  2063.         mov eax,ecx
  2064.         movzx ecx,cx
  2065.         xor dx,dx
  2066.         ; interpolate 2 points to find delta step
  2067.         sub ecx,[ebp+donote_currtick]
  2068.         push edx
  2069.         jz donote_no_tickdiff
  2070.         xor ax,ax
  2071.         sub eax,edx
  2072.         cdq
  2073.         idiv ecx
  2074.         xchg eax,ecx
  2075. donote_no_tickdiff:
  2076.         mov [esi+FMUSIC_CHANNEL.envvoldelta-2],ecx
  2077.         mov eax,[esi+FMUSIC_CHANNEL.envvoltick-2]
  2078.         sub eax,[ebp+donote_currtick]
  2079.         imul ecx
  2080.         pop edx
  2081.         add eax,edx
  2082.         mov [esi+FMUSIC_CHANNEL.envvolfrac-2],eax
  2083.         sar eax,16
  2084.         mov [esi+FMUSIC_CHANNEL.envvol-2],eax
  2085.         inc DWORD PTR [esi+FMUSIC_CHANNEL.envvolpos-2]
  2086.         ret
  2087. endif
  2088. if PANSLIDE_ON
  2089. S1_C25:
  2090.         jz donote_panslide_ok
  2091.         mov [esi+FMUSIC_CHANNEL.panslide-2],dl
  2092.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
  2093. donote_panslide_ok:
  2094.         ret
  2095. endif
  2096. if MULTIRETRIG_ON
  2097. S1_C27:
  2098.         jz donote_multiretrig_ok
  2099.         shr edx,4
  2100.         mov dh,bl
  2101.         mov WORD PTR [esi+FMUSIC_CHANNEL.retrigx-2],dx
  2102. donote_multiretrig_ok:
  2103.         ret
  2104. endif
  2105. if TREMOR_ON
  2106. S1_C29:
  2107.         jz donote_do_tremor
  2108.         shr edx,4
  2109.         mov dh,bl
  2110.         mov WORD PTR [esi+FMUSIC_CHANNEL.tremoron-2],dx
  2111. donote_do_tremor:
  2112.         ; cptr : ESI
  2113.         jmp Tremor
  2114. endif
  2115. if EXTRAFINEPORTA_ON
  2116. S1_C33:
  2117.         shr edx,4
  2118.         dec edx
  2119.         jnz donote_paramx_n1
  2120.         test ebx,ebx
  2121.         jz donote_paramy_z1
  2122.         mov [esi+FMUSIC_CHANNEL.xtraportaup-2],bl
  2123. donote_paramy_z1:
  2124.         movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.xtraportaup-2]
  2125.         sub [esi+FMUSIC_CHANNEL.freq-2],eax
  2126. donote_paramx_n1:
  2127.         dec edx
  2128.         jnz donote_paramx_n2
  2129.         test ebx,ebx
  2130.         jz donote_paramy_z2
  2131.         mov [esi+FMUSIC_CHANNEL.xtraportadown-2],bl
  2132. donote_paramy_z2:
  2133.         movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.xtraportadown-2]
  2134.         add [esi+FMUSIC_CHANNEL.freq-2],eax
  2135. donote_paramx_n2:
  2136. endif
  2137. S2_r:
  2138.         ret
  2139. S1_C14:
  2140.         shr edx,4
  2141.         dec edx ; skip FMUSIC_XM_SETFILTER
  2142. if FINEPORTAUP_ON
  2143. else
  2144.         dec edx
  2145. endif
  2146. if PATTERNDELAY_ON
  2147.         cmp dl,13
  2148. else
  2149.         if NOTEDELAY_ON
  2150.                 cmp dl,12
  2151.         else
  2152.                 if FINEVOLUMESLIDE_ON
  2153.                         cmp dl,10
  2154.                 else
  2155.                         if SETPANPOSITION16_ON
  2156.                                 cmp dl,7
  2157.                         else
  2158.                                 if SETTREMOLOWAVE_ON
  2159.                                         cmp dl,6
  2160.                                 else
  2161.                                         if PATTERNLOOP_ON
  2162.                                                 cmp dl,5
  2163.                                         else
  2164.                                                 cmp dl,4
  2165.                                         endif
  2166.                                 endif
  2167.                         endif
  2168.                 endif
  2169.         endif
  2170. endif
  2171. if FINEPORTAUP_ON
  2172.         ja S2_r
  2173. else
  2174.         jae S2_r
  2175. endif
  2176. donote_do_special:
  2177.         test ebx,ebx
  2178.         jmp DWORD PTR [edx*4+S2_TBL]
  2179. S2_TBL:
  2180. if FINEPORTAUP_ON
  2181.         dd S2_C1
  2182. endif
  2183. if FINEPORTADOWN_ON
  2184.         dd S2_C2
  2185. else
  2186.         dd S2_r
  2187. endif
  2188.         dd S2_r ; skip FMUSIC_XM_SETGLISSANDO
  2189. if SETVIBRATOWAVE_ON
  2190.         dd S2_C4
  2191. else
  2192.         dd S2_r
  2193. endif
  2194. if SETFINETUNE_ON
  2195.         dd S2_C5
  2196. else
  2197.         dd S2_r
  2198. endif
  2199. if PATTERNDELAY_ON
  2200.         if PATTERNLOOP_ON
  2201.                 dd S2_C6
  2202.         else
  2203.                 dd S2_r
  2204.         endif
  2205.         if SETTREMOLOWAVE_ON
  2206.                 dd S2_C7
  2207.         else
  2208.                 dd S2_r
  2209.         endif
  2210.         if SETPANPOSITION16_ON
  2211.                 dd S2_C8
  2212.         else
  2213.                 dd S2_r
  2214.         endif
  2215.         dd S2_r ; skip FMUSIC_XM_RETRIG
  2216.         if FINEVOLUMESLIDE_ON
  2217.                 dd S2_C10
  2218.                 dd S2_C11
  2219.         else
  2220.                 dd S2_r
  2221.                 dd S2_r
  2222.         endif
  2223.         dd S2_r ; skip FMUSIC_XM_NOTECUT
  2224.         if NOTEDELAY_ON
  2225.                 dd S2_C13
  2226.         else
  2227.                 dd S2_r
  2228.         endif
  2229.         dd S2_C14
  2230. else
  2231.         if NOTEDELAY_ON
  2232.                 if PATTERNLOOP_ON
  2233.                         dd S2_C6
  2234.                 else
  2235.                         dd S2_r
  2236.                 endif
  2237.                 if SETTREMOLOWAVE_ON
  2238.                         dd S2_C7
  2239.                 else
  2240.                         dd S2_r
  2241.                 endif
  2242.                 if SETPANPOSITION16_ON
  2243.                         dd S2_C8
  2244.                 else
  2245.                         dd S2_r
  2246.                 endif
  2247.                 dd S2_r ; skip FMUSIC_XM_RETRIG
  2248.                 if FINEVOLUMESLIDE_ON
  2249.                         dd S2_C10
  2250.                         dd S2_C11
  2251.                 else
  2252.                         dd S2_r
  2253.                         dd S2_r
  2254.                 endif
  2255.                 dd S2_r
  2256.                 dd S2_C13
  2257.         else
  2258.                 if FINEVOLUMESLIDE_ON
  2259.                         if PATTERNLOOP_ON
  2260.                                 dd S2_C6
  2261.                         else
  2262.                                 dd S2_r
  2263.                         endif
  2264.                         if SETTREMOLOWAVE_ON
  2265.                                 dd S2_C7
  2266.                         else
  2267.                                 dd S2_r
  2268.                         endif
  2269.                         if SETPANPOSITION16_ON
  2270.                                 dd S2_C8
  2271.                         else
  2272.                                 dd S2_r
  2273.                         endif
  2274.                         dd S2_r
  2275.                         dd S2_C10
  2276.                         dd S2_C11
  2277.                 else
  2278.                         if SETPANPOSITION16_ON
  2279.                                 if PATTERNLOOP_ON
  2280.                                         dd S2_C6
  2281.                                 else
  2282.                                         dd S2_r
  2283.                                 endif
  2284.                                 if SETTREMOLOWAVE_ON
  2285.                                         dd S2_C7
  2286.                                 else
  2287.                                         dd S2_r
  2288.                                 endif
  2289.                                 dd S2_C8
  2290.                         else
  2291.                                 if SETTREMOLOWAVE_ON
  2292.                                         if PATTERNLOOP_ON
  2293.                                                 dd S2_C6
  2294.                                         else
  2295.                                                 dd S2_r
  2296.                                         endif
  2297.                                         dd S2_C7
  2298.                                 else
  2299.                                         if PATTERNLOOP_ON
  2300.                                                 dd S2_C6
  2301.                                         endif
  2302.                                 endif
  2303.                         endif
  2304.                 endif
  2305.         endif
  2306. endif
  2307. if FINEPORTAUP_ON
  2308. S2_C1:
  2309.         jz donote_finepup_ok
  2310.         mov [esi+FMUSIC_CHANNEL.fineportaup-2],bl
  2311. donote_finepup_ok:
  2312.         movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.fineportaup-2]
  2313.         shl eax,2
  2314.         sub [esi+FMUSIC_CHANNEL.freq-2],eax
  2315.         ret
  2316. endif
  2317. if FINEPORTADOWN_ON
  2318. S2_C2:
  2319.         jz donote_finepdown_ok
  2320.         mov [esi+FMUSIC_CHANNEL.fineportadown-2],bl
  2321. donote_finepdown_ok:
  2322.         movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.fineportadown-2]
  2323.         shl eax,2
  2324.         add [esi+FMUSIC_CHANNEL.freq-2],eax
  2325.         ret
  2326. endif
  2327. if SETVIBRATOWAVE_ON
  2328. S2_C4:
  2329.         and BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],0F0h
  2330.         or BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],bl
  2331.         ret
  2332. endif
  2333. if SETFINETUNE_ON
  2334. S2_C5:
  2335.         mov eax,[ebp+donote_sptr]
  2336.         mov [eax+FSOUND_SAMPLE.finetune],bl
  2337.         ret
  2338. endif
  2339. if PATTERNLOOP_ON
  2340. S2_C6:
  2341.         jnz donote_not_paramy
  2342.         mov eax,[ebp+var_mod]
  2343.         mov eax,[eax+FMUSIC_MODULE.row-36]
  2344.         mov [esi+FMUSIC_CHANNEL.patlooprow-2],eax
  2345.         ret
  2346. donote_not_paramy:
  2347.         mov cl,[esi+FMUSIC_CHANNEL.patloopno-2]
  2348.         dec cl
  2349.         jns donote_patloopno_ok
  2350.         mov ecx,ebx
  2351. donote_patloopno_ok:
  2352.         mov [esi+FMUSIC_CHANNEL.patloopno-2],cl
  2353.         jz donote_patloopno_end
  2354.         mov eax,[esi+FMUSIC_CHANNEL.patlooprow-2]
  2355.         mov ecx,[ebp+var_mod]
  2356.         mov [ecx+FMUSIC_MODULE.nextrow-36],eax
  2357. donote_patloopno_end:
  2358.         ret
  2359. endif
  2360. if SETTREMOLOWAVE_ON
  2361. S2_C7:
  2362.         and BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],0Fh
  2363.         shl ebx,4
  2364.         or BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],bl
  2365.         ret
  2366. endif
  2367. if SETPANPOSITION16_ON
  2368. S2_C8:
  2369.         shl ebx,4
  2370.         mov [esi+FMUSIC_CHANNEL.pan-2],ebx
  2371.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
  2372.         ret
  2373. endif
  2374. if FINEVOLUMESLIDE_ON
  2375. S2_C10:
  2376.         neg ebx
  2377. S2_C11:
  2378.         jz donote_finevols_ok
  2379.         mov [esi+FMUSIC_CHANNEL.finevslup-2],bl
  2380. donote_finevols_ok:
  2381.         movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.finevslup-2]
  2382.         sub [esi+FMUSIC_CHANNEL.volume-2],eax
  2383.         ret
  2384. endif
  2385. if NOTEDELAY_ON
  2386. S2_C13:
  2387.         mov eax,[ebp+donote_oldfreq]
  2388.         mov edx,[ebp+donote_currtick]
  2389.         mov [esi+FMUSIC_CHANNEL.freq-2],eax
  2390.         mov eax,[ebp+donote_oldpan]
  2391.         mov [esi+FMUSIC_CHANNEL.pan-2],eax
  2392.         mov BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],0
  2393. if SETVOLUME_ON
  2394. else
  2395.         mov [esi+FMUSIC_CHANNEL.volume-2],edx
  2396.         ret
  2397. endif
  2398. endif
  2399. if SETVOLUME_ON
  2400. S1_C12:
  2401.         mov [esi+FMUSIC_CHANNEL.volume-2],edx
  2402.         ret
  2403. endif
  2404. if PATTERNDELAY_ON
  2405. S2_C14:
  2406.         mov ecx,[ebp+var_mod]
  2407.         imul ebx,DWORD PTR [ecx+FMUSIC_MODULE.speed-36]
  2408.         mov [ecx+FMUSIC_MODULE.patterndelay-36],ebx
  2409.         ret
  2410. endif
  2411.  
  2412. DoEffs:
  2413. ; mod+36 = ESI
  2414. ; var_mod     equ -4
  2415. doeff_current equ -8
  2416.         ; Point our note pointer to the correct pattern buffer, and to the
  2417.         ; correct offset in this buffer indicated by row and number of channels
  2418.         mov eax,[esi+FMUSIC_MODULE.order-36]
  2419.         push ebp
  2420.         mov bl,[eax+esi+FMUSIC_MODULE.orderlist-36]
  2421.         mov eax,[esi+FMUSIC_MODULE.row-36]
  2422.         mul DWORD PTR [esi+FMUSIC_MODULE.numchannels-36]
  2423.         lea eax,[eax+eax*4] ; x SIZE FMUSIC_NOTE
  2424.         mov ebp,esp
  2425.         ; mod->pattern[mod->orderlist[mod->order]].data+(mod->row*mod->numchannels)
  2426.         add eax,[ecx+ebx*FMUSIC_PATTERN_size+FMUSIC_PATTERN.data]
  2427.         push esi ; -> var_mod
  2428.         push eax ; -> doeff_current
  2429.         mov eax,[esi+FMUSIC_MODULE.numchannels-36]
  2430.         shl eax,7 ; x FMUSIC_CHANNEL_size
  2431.         push esi
  2432.         mov esi,[esi+FMUSIC_MODULE.uFMOD_Ch-36]
  2433.         inc esi
  2434.         inc esi
  2435.         add eax,esi
  2436. doeff_for_channels:
  2437.         push eax
  2438.         movzx edi,BYTE PTR [esi+FMUSIC_CHANNEL.inst-2]
  2439.         mov edx,[ebp+var_mod]
  2440.         imul edi,FMUSIC_INSTRUMENT_size
  2441.         movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.note-2]
  2442.         add edi,[edx+FMUSIC_MODULE.instrument-36]
  2443.         cdq
  2444.         mov al,[eax+edi+FMUSIC_INSTRUMENT.keymap]
  2445.         cmp al,16
  2446.         jae doeff_set_sptr
  2447.         mov edx,[edi+eax*4+FMUSIC_INSTRUMENT.sample]
  2448. doeff_set_sptr:
  2449.         test edx,edx
  2450.         jnz doeff_valid_sptr
  2451.         mov edx,OFFSET DummySamp
  2452. doeff_valid_sptr:
  2453.         xor ebx,ebx
  2454. if INSTRUMENTVIBRATO_ON
  2455.         push edi ; iptr
  2456. endif
  2457.         push edx ; sptr
  2458.         mov [esi+FMUSIC_CHANNEL.voldelta-2],ebx
  2459.         mov [esi+FMUSIC_CHANNEL.freqdelta-2],ebx
  2460.         mov [esi+FMUSIC_CHANNEL.notectrl-2],bl
  2461.         ; PROCESS ENVELOPES
  2462. if VOLUMEENVELOPE_ON
  2463.         test BYTE PTR [edi+FMUSIC_INSTRUMENT.VOLtype],1
  2464.         je doeff_no_voltype
  2465.         mov al,FMUSIC_VOLUME
  2466.         mov ecx,edi
  2467.         ; cptr+2   : ESI
  2468.         ; env_iptr : ECX
  2469.         ; control  : AL
  2470.         call Envelope
  2471. doeff_no_voltype:
  2472. endif
  2473. if PANENVELOPE_ON
  2474.         test BYTE PTR [edi+FMUSIC_INSTRUMENT.PANtype],1
  2475.         je doeff_no_pantype
  2476.         mov al,FMUSIC_PAN
  2477.         mov ecx,edi
  2478.         ; cptr+2   : ESI
  2479.         ; env_iptr : ECX
  2480.         ; control  : AL
  2481.         call Envelope
  2482. doeff_no_pantype:
  2483. endif
  2484.         ; PROCESS VOLUME FADEOUT
  2485.         cmp [esi+FMUSIC_CHANNEL.keyoff-2],bl
  2486.         je doeff_fadevol_ok
  2487.         movzx eax,WORD PTR [edi+FMUSIC_INSTRUMENT.VOLfade]
  2488.         sub [esi+FMUSIC_CHANNEL.fadeoutvol-2],eax
  2489.         jns doeff_fadevol_ns
  2490.         mov [esi+FMUSIC_CHANNEL.fadeoutvol-2],ebx
  2491. doeff_fadevol_ns:
  2492.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  2493. doeff_fadevol_ok:
  2494. if VOLUMEBYTE_ON
  2495.         mov eax,[ebp+doeff_current]
  2496.         movzx eax,BYTE PTR [eax+FMUSIC_NOTE.uvolume]
  2497.         mov ecx,eax
  2498.         shr eax,4
  2499.         and cl,0Fh
  2500.         sub al,6
  2501.         jz doeff_case_vol6
  2502.         dec eax
  2503.         jz doeff_case_vol7
  2504. if VIBRATO_ON
  2505.         sub al,4
  2506.         jz doeff_case_volB
  2507.         dec eax
  2508.         dec eax
  2509. else
  2510.         sub al,6
  2511. endif
  2512.         jz doeff_case_volD
  2513.         dec eax
  2514. if PORTATO_ON
  2515.         jz doeff_case_volE
  2516.         dec eax
  2517.         jnz doeff_volbyte_end
  2518.         ; cptr+2 : ESI
  2519.         call Portamento
  2520.         jmp doeff_volbyte_end
  2521. else
  2522.         jnz doeff_volbyte_end
  2523. endif
  2524. doeff_case_volE:
  2525.         neg ecx
  2526. doeff_case_volD:
  2527.         sub [esi+FMUSIC_CHANNEL.pan-2],ecx
  2528.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
  2529.         jmp doeff_volbyte_end
  2530. if VIBRATO_ON
  2531. doeff_case_volB:
  2532.         mov [esi+FMUSIC_CHANNEL.vibdepth-2],cl
  2533.         ; cptr+2 : ESI
  2534.         call Vibrato
  2535.         jmp doeff_volbyte_end
  2536. endif
  2537. doeff_case_vol6:
  2538.         neg ecx
  2539. doeff_case_vol7:
  2540.         add [esi+FMUSIC_CHANNEL.volume-2],ecx
  2541.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  2542. doeff_volbyte_end:
  2543. endif ; VOLUMEBYTE_ON
  2544.         mov edx,[ebp+doeff_current]
  2545.         movzx ebx,BYTE PTR [edx+FMUSIC_NOTE.eparam]
  2546.         mov ecx,ebx
  2547.         and ebx,0Fh ; grab the effect parameter y
  2548.         movzx eax,BYTE PTR [edx+FMUSIC_NOTE.effect]
  2549.         shr cl,4    ; grab the effect parameter x
  2550. if ARPEGGIO_ON
  2551. else
  2552.         dec eax
  2553. endif
  2554. if TREMOR_ON
  2555.         cmp al,29
  2556. else
  2557.         if MULTIRETRIG_ON
  2558.                 cmp al,27
  2559.         else
  2560.                 if PANSLIDE_ON
  2561.                         cmp al,25
  2562.                 else
  2563.                         if GLOBALVOLSLIDE_ON
  2564.                                 cmp al,17
  2565.                         else
  2566.                                 if RETRIG_ON
  2567.                                         cmp al,14
  2568.                                 else
  2569.                                         if NOTECUT_ON
  2570.                                                 cmp al,14
  2571.                                         else
  2572.                                                 if NOTEDELAY_ON
  2573.                                                         cmp al,14
  2574.                                                 else
  2575.                                                         cmp al,10
  2576.                                                 endif
  2577.                                         endif
  2578.                                 endif
  2579.                         endif
  2580.                 endif
  2581.         endif
  2582. endif
  2583. if ARPEGGIO_ON
  2584.         ja doeff_s3_brk
  2585. else
  2586.         jae doeff_s3_brk
  2587. endif
  2588.         call DWORD PTR [eax*4+S3_TBL]
  2589. doeff_s3_brk:
  2590.         ; cptr+2 : ESI
  2591.         call DoFlags
  2592.         sub esi,-(FMUSIC_CHANNEL_size)
  2593.         pop eax
  2594.         add DWORD PTR [ebp+doeff_current],FMUSIC_NOTE_size
  2595.         cmp esi,eax
  2596.         jl doeff_for_channels
  2597.         pop esi
  2598. doeff_R:
  2599.         leave
  2600. S3_r:
  2601.         ret
  2602. S3_TBL:
  2603. if ARPEGGIO_ON
  2604.         dd S3_C0
  2605. endif
  2606. if PORTAUP_ON
  2607.         dd S3_C1
  2608. else
  2609.         dd S3_r
  2610. endif
  2611. if PORTADOWN_ON
  2612.         dd S3_C2
  2613. else
  2614.         dd S3_r
  2615. endif
  2616. if PORTATO_ON
  2617.         ; cptr+2 : ESI
  2618.         dd Portamento
  2619. else
  2620.         dd S3_r
  2621. endif
  2622. if VIBRATO_ON
  2623.         ; cptr+2 : ESI
  2624.         dd Vibrato
  2625. else
  2626.         dd S3_r
  2627. endif
  2628. if PORTATOVOLSLIDE_ON
  2629.         dd S3_C5
  2630. else
  2631.         dd S3_r
  2632. endif
  2633. if VIBRATOVOLSLIDE_ON
  2634.         dd S3_C6
  2635. else
  2636.         dd S3_r
  2637. endif
  2638. if TREMOLO_ON
  2639.         ; cptr+2 : ESI
  2640.         dd Tremolo
  2641. else
  2642.         dd S3_r
  2643. endif
  2644.         dd S3_r ; skip FMUSIC_XM_SETPANPOSITION
  2645.         dd S3_r ; skip FMUSIC_XM_SETSAMPLEOFFSET
  2646. if VOLUMESLIDE_ON
  2647.         dd S3_C10
  2648. else
  2649.         dd S3_r
  2650. endif
  2651. if TREMOR_ON
  2652.         dd S3_r ; skip FMUSIC_XM_PATTERNJUMP
  2653.         dd S3_r ; slip FMUSIC_XM_SETVOLUME
  2654.         dd S3_r ; skip FMUSIC_XM_PATTERNBREAK
  2655.         dd S3_C14
  2656.         dd S3_r ; skip FMUSIC_XM_SETSPEED
  2657.         dd S3_r ; skip FMUSIC_XM_SETGLOBALVOLUME
  2658.         if GLOBALVOLSLIDE_ON
  2659.                 dd S3_C17
  2660.         else
  2661.                 dd S3_r
  2662.         endif
  2663.         dd S3_r ; unassigned effect ordinal [18]
  2664.         dd S3_r ; unassigned effect ordinal [19]
  2665.         dd S3_r ; skip FMUSIC_XM_KEYOFF
  2666.         dd S3_r ; skip FMUSIC_XM_SETENVELOPEPOS
  2667.         dd S3_r ; unassigned effect ordinal [22]
  2668.         dd S3_r ; unassigned effect ordinal [23]
  2669.         dd S3_r ; unassigned effect ordinal [24]
  2670.         if PANSLIDE_ON
  2671.                 dd S3_C25
  2672.         else
  2673.                 dd S3_r
  2674.         endif
  2675.         dd S3_r ; unassigned effect ordinal [26]
  2676.         if MULTIRETRIG_ON
  2677.                 dd S3_C27
  2678.         else
  2679.                 dd S3_r
  2680.         endif
  2681.         dd S3_r ; unassigned effect ordinal [28]
  2682.         ; case FMUSIC_XM_TREMOR
  2683.         ; cptr : ESI
  2684.         dd Tremor
  2685. else
  2686.         if MULTIRETRIG_ON
  2687.                 dd S3_r
  2688.                 dd S3_r
  2689.                 dd S3_r
  2690.                 dd S3_C14
  2691.                 dd S3_r
  2692.                 dd S3_r
  2693.                 if GLOBALVOLSLIDE_ON
  2694.                         dd S3_C17
  2695.                 else
  2696.                         dd S3_r
  2697.                 endif
  2698.                 dd S3_r
  2699.                 dd S3_r
  2700.                 dd S3_r
  2701.                 dd S3_r
  2702.                 dd S3_r
  2703.                 dd S3_r
  2704.                 dd S3_r
  2705.                 if PANSLIDE_ON
  2706.                         dd S3_C25
  2707.                 else
  2708.                         dd S3_r
  2709.                 endif
  2710.                 dd S3_r
  2711.                 dd S3_C27
  2712.         else
  2713.                 if PANSLIDE_ON
  2714.                         dd S3_r
  2715.                         dd S3_r
  2716.                         dd S3_r
  2717.                         dd S3_C14
  2718.                         dd S3_r
  2719.                         dd S3_r
  2720.                         if GLOBALVOLSLIDE_ON
  2721.                                 dd S3_C17
  2722.                         else
  2723.                                 dd S3_r
  2724.                         endif
  2725.                         dd S3_r
  2726.                         dd S3_r
  2727.                         dd S3_r
  2728.                         dd S3_r
  2729.                         dd S3_r
  2730.                         dd S3_r
  2731.                         dd S3_r
  2732.                         dd S3_C25
  2733.                 else
  2734.                         if GLOBALVOLSLIDE_ON
  2735.                                 dd S3_r
  2736.                                 dd S3_r
  2737.                                 dd S3_r
  2738.                                 dd S3_C14
  2739.                                 dd S3_r
  2740.                                 dd S3_r
  2741.                                 dd S3_C17
  2742.                         else
  2743.                                 if RETRIG_ON
  2744.                                         dd S3_r
  2745.                                         dd S3_r
  2746.                                         dd S3_r
  2747.                                         dd S3_C14
  2748.                                 else
  2749.                                         if NOTECUT_ON
  2750.                                                 dd S3_r
  2751.                                                 dd S3_r
  2752.                                                 dd S3_r
  2753.                                                 dd S3_C14
  2754.                                         else
  2755.                                                 if NOTEDELAY_ON
  2756.                                                         dd S3_r
  2757.                                                         dd S3_r
  2758.                                                         dd S3_r
  2759.                                                         dd S3_C14
  2760.                                                 endif
  2761.                                         endif
  2762.                                 endif
  2763.                         endif
  2764.                 endif
  2765.  
  2766.         endif
  2767. endif
  2768. if VIBRATOVOLSLIDE_ON
  2769. S3_C6:
  2770.         ; cptr+2 : ESI
  2771.         call Vibrato
  2772. if VOLUMESLIDE_ON
  2773.         if PORTATOVOLSLIDE_ON
  2774.                 jmp S3_C10
  2775.         endif
  2776. else
  2777.         mov cl,[esi+FMUSIC_CHANNEL.volslide-2]
  2778.         mov eax,ecx
  2779.         and eax,0Fh
  2780.         shr ecx,4
  2781.         jz doeff_volslide_ok
  2782.         ; Slide up takes precedence over down
  2783.         xchg eax,ecx
  2784.         neg eax
  2785. doeff_volslide_ok:
  2786.         sub [esi+FMUSIC_CHANNEL.volume-2],eax
  2787.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  2788.         ret
  2789. endif
  2790. endif
  2791. if PORTATOVOLSLIDE_ON
  2792. S3_C5:
  2793.         ; cptr+2 : ESI
  2794.         call Portamento
  2795. if VOLUMESLIDE_ON
  2796.         xor ecx,ecx
  2797. else
  2798.         movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.volslide-2]
  2799.         mov eax,ecx
  2800.         and eax,0Fh
  2801.         shr ecx,4
  2802.         jz doeff_volslide_ok
  2803.         ; Slide up takes precedence over down
  2804.         xchg eax,ecx
  2805.         neg eax
  2806. doeff_volslide_ok:
  2807.         sub [esi+FMUSIC_CHANNEL.volume-2],eax
  2808.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  2809.         ret
  2810. endif
  2811. endif
  2812. if VOLUMESLIDE_ON
  2813. S3_C10:
  2814.         mov cl,[esi+FMUSIC_CHANNEL.volslide-2]
  2815.         mov eax,ecx
  2816.         and eax,0Fh
  2817.         shr ecx,4
  2818.         jz doeff_volslide_ok
  2819.         ; Slide up takes precedence over down
  2820.         xchg eax,ecx
  2821.         neg eax
  2822. doeff_volslide_ok:
  2823.         sub [esi+FMUSIC_CHANNEL.volume-2],eax
  2824.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  2825.         ret
  2826. endif
  2827. if PORTADOWN_ON
  2828. S3_C2:
  2829.         mov al,[esi+FMUSIC_CHANNEL.portaupdown-2]
  2830. DoFreqSlide:
  2831.         mov ecx,[esi+FMUSIC_CHANNEL.freq-2]
  2832.         lea ecx,[ecx+eax*4]
  2833.         cmp ecx,1
  2834.         jge DoFreqSlide_ok
  2835.         push 1
  2836.         pop ecx
  2837. DoFreqSlide_ok:
  2838.         mov [esi+FMUSIC_CHANNEL.freq-2],ecx
  2839.         and DWORD PTR [esi+FMUSIC_CHANNEL.freqdelta-2],0
  2840.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
  2841.         ret
  2842. endif
  2843. if PORTAUP_ON
  2844. S3_C1:
  2845.         mov al,[esi+FMUSIC_CHANNEL.portaupdown-2]
  2846. if PORTADOWN_ON
  2847.         neg eax
  2848.         jmp DoFreqSlide
  2849. else
  2850.         shl eax,2
  2851.         mov ecx,[esi+FMUSIC_CHANNEL.freq-2]
  2852.         sub ecx,eax
  2853.         cmp ecx,1
  2854.         jge DoFreqSlide_ok
  2855.         push 1
  2856.         pop ecx
  2857. DoFreqSlide_ok:
  2858.         mov [esi+FMUSIC_CHANNEL.freq-2],ecx
  2859.         and DWORD PTR [esi+FMUSIC_CHANNEL.freqdelta-2],0
  2860.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
  2861.         ret
  2862. endif
  2863. endif
  2864. if ARPEGGIO_ON
  2865. S3_C0:
  2866.         cmp BYTE PTR [edx+FMUSIC_NOTE.eparam],ch
  2867.         jbe doeff_arpeggio_ok
  2868.         mov eax,[ebp+var_mod]
  2869.         mov eax,[eax+FMUSIC_MODULE.tick-36]
  2870.         push 3
  2871.         cdq
  2872.         pop edi
  2873.         idiv edi
  2874.         dec edx
  2875.         jz doeff_arpeg_c1
  2876.         dec edx
  2877.         jne doeffs_enable_freq
  2878.         mov ecx,ebx
  2879. doeff_arpeg_c1:
  2880.         mov eax,[ebp+var_mod]
  2881.         test BYTE PTR [eax+FMUSIC_MODULE.flags-36],1
  2882.         je doeffs_flagsn1
  2883. doeffs_arpeggio_freqd:
  2884.         shl ecx,6
  2885.         mov [esi+FMUSIC_CHANNEL.freqdelta-2],ecx
  2886. if AMIGAPERIODS_ON
  2887.         jmp doeffs_enable_freq
  2888. endif
  2889. doeffs_flagsn1:
  2890. if AMIGAPERIODS_ON
  2891.         movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.realnote-2]
  2892.         mov edi,eax
  2893.         add eax,ecx     ; note   : EAX
  2894.         mov ecx,[esp+4] ; [sptr] : ECX
  2895.         ; ESI != 0
  2896.         call AmigaPeriod
  2897.         xchg eax,edi    ; note   : EAX
  2898.         mov ecx,[esp+4] ; [sptr] : ECX
  2899.         ; ESI != 0
  2900.         call AmigaPeriod
  2901.         sub edi,eax
  2902.         mov [esi+FMUSIC_CHANNEL.freqdelta-2],edi
  2903. endif
  2904. doeffs_enable_freq:
  2905.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
  2906. doeff_arpeggio_ok:
  2907.         ret
  2908. endif
  2909. if MULTIRETRIG_ON
  2910. S3_C27:
  2911.         mov cl,[esi+FMUSIC_CHANNEL.retrigy-2]
  2912.         test ecx,ecx
  2913.         jz doeff_multiretrig_ok
  2914.         mov eax,[ebp+var_mod]
  2915.         mov eax,[eax+FMUSIC_MODULE.tick-36]
  2916.         cdq
  2917.         idiv ecx
  2918.         test edx,edx
  2919.         jnz doeff_multiretrig_ok
  2920.         mov cl,[esi+FMUSIC_CHANNEL.retrigx-2]
  2921.         and ecx,0Fh
  2922.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_TRIGGER
  2923.         dec ecx
  2924.         mov eax,[esi+FMUSIC_CHANNEL.volume-2]
  2925.         js doeff_multiretrig_ok
  2926.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  2927.         call DWORD PTR [ecx*4+S4_TBL]
  2928.         mov [esi+FMUSIC_CHANNEL.volume-2],eax
  2929. S4_C2:
  2930.         dec eax
  2931. S4_C1:
  2932.         dec eax
  2933. doeff_multiretrig_ok:
  2934.         ret
  2935. S4_C5:
  2936.         sub eax,8
  2937. S4_C4:
  2938.         sub eax,4
  2939. S4_C3:
  2940.         sub eax,4
  2941.         ret
  2942. S4_C6:
  2943.         shl eax,1
  2944.         push 3
  2945.         cdq
  2946.         pop ecx
  2947.         idiv ecx
  2948.         ret
  2949. S4_C14:
  2950.         lea eax,[eax+eax*2]
  2951. S4_C7:
  2952.         sar eax,1
  2953.         ret
  2954. S4_C10:
  2955.         inc eax
  2956. S4_C9:
  2957.         inc eax
  2958.         ret
  2959. S4_C13:
  2960.         add eax,8
  2961. S4_C12:
  2962.         add eax,4
  2963. S4_C11:
  2964.         add eax,4
  2965.         ret
  2966. S4_C15:
  2967.         shl eax,1
  2968. S4_r:
  2969.         ret
  2970. S4_TBL:
  2971.         dd S4_C1
  2972.         dd S4_C2
  2973.         dd S4_C3
  2974.         dd S4_C4
  2975.         dd S4_C5
  2976.         dd S4_C6
  2977.         dd S4_C7
  2978.         dd S4_r
  2979.         dd S4_C9
  2980.         dd S4_C10
  2981.         dd S4_C11
  2982.         dd S4_C12
  2983.         dd S4_C13
  2984.         dd S4_C14
  2985.         dd S4_C15
  2986. endif
  2987. if PANSLIDE_ON
  2988. S3_C25:
  2989.         mov cl,[esi+FMUSIC_CHANNEL.panslide-2]
  2990.         mov eax,ecx
  2991.         and eax,0Fh
  2992.         mov edx,[esi+FMUSIC_CHANNEL.pan-2]
  2993.         shr ecx,4
  2994.         ; Slide right takes precedence over left
  2995.         jnz doeff_pan_slide_right
  2996.         sub edx,eax
  2997.         jns doeff_panslide_ok
  2998.         mov edx,ecx
  2999.         jmp doeff_panslide_ok
  3000. doeff_pan_slide_right:
  3001.         add ecx,edx
  3002.         cdq
  3003.         dec dl ; edx = 255
  3004.         cmp ecx,edx
  3005.         jg doeff_panslide_ok
  3006.         mov edx,ecx
  3007. doeff_panslide_ok:
  3008. if SETPANPOSITION_ON
  3009. S1_C8:
  3010. endif
  3011.         mov [esi+FMUSIC_CHANNEL.pan-2],edx
  3012.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
  3013.         ret
  3014. endif
  3015. if GLOBALVOLSLIDE_ON
  3016. S3_C17:
  3017.         mov ecx,[ebp+var_mod]
  3018.         mov edx,[ecx+FMUSIC_MODULE.globalvolume-36]
  3019.         mov al,[ecx+FMUSIC_MODULE.globalvsl-36]
  3020.         test al,0F0h
  3021.         ; Slide up takes precedence over down
  3022.         jnz doeff_gvsl_slide_up
  3023.         and eax,0Fh
  3024.         sub edx,eax
  3025.         jns set_global_vol
  3026.         cdq
  3027.         xor eax,eax
  3028. doeff_gvsl_slide_up:
  3029.         shr eax,4
  3030.         add edx,eax
  3031. set_global_vol:
  3032.         if SETGLOBALVOLUME_ON
  3033.         else
  3034.                 cmp edx,64
  3035.                 jle doeff_setglobalvol
  3036.                 push 64
  3037.                 pop edx
  3038. doeff_setglobalvol:
  3039.                 mov [ecx+FMUSIC_MODULE.globalvolume-36],edx
  3040.                 ret
  3041.         endif
  3042. endif
  3043. if SETGLOBALVOLUME_ON
  3044. S1_C16:
  3045.         cmp edx,64
  3046.         mov ecx,[ebp+var_mod]
  3047.         jle do_setglobalvol
  3048.         push 64
  3049.         pop edx
  3050. do_setglobalvol:
  3051.         mov [ecx+FMUSIC_MODULE.globalvolume-36],edx
  3052.         ret
  3053. endif
  3054. S3_C14:
  3055. if RETRIG_ON
  3056.         cmp cl,FMUSIC_XM_RETRIG
  3057.         je doeff_do_retrig
  3058. endif
  3059. if NOTECUT_ON
  3060.         sub cl,FMUSIC_XM_NOTECUT
  3061.         jz doeff_do_notecut
  3062. endif
  3063. if NOTEDELAY_ON
  3064.         if NOTECUT_ON
  3065.                 dec cl
  3066.         else
  3067.                 cmp cl,FMUSIC_XM_NOTEDELAY
  3068.         endif
  3069.         jne doeff_special_r
  3070.         mov ecx,[ebp+var_mod]
  3071.         xor eax,eax
  3072.         cmp [ecx+FMUSIC_MODULE.tick-36],ebx
  3073.         jne doeff_notectrl_z
  3074.         mov edx,[esp+4]
  3075.         mov DWORD PTR [esi+FMUSIC_CHANNEL.fadeoutvol-2],65536
  3076.         movzx edx,BYTE PTR [edx+FSOUND_SAMPLE.defvol]
  3077.         lea ecx,[eax+9]
  3078.         mov [esi+FMUSIC_CHANNEL.volume-2],edx
  3079.         mov edx,[esi+FMUSIC_CHANNEL.envvol-2]
  3080.         lea edi,[esi+FMUSIC_CHANNEL.envvoltick-2]
  3081.         cmp ecx,edx
  3082.         sbb edx,edx
  3083.         and edx,64
  3084.         mov [esi+FMUSIC_CHANNEL.envvol-2],edx
  3085.         ; memset(&cptr->envvoltick,0,36)
  3086.         rep stosd
  3087.         ; Retrigger tremolo and vibrato waveforms
  3088.         mov cl,[esi+FMUSIC_CHANNEL.wavecontrol-2]
  3089.         cmp cl,4Fh
  3090.         jge z2_tremolopos_ok
  3091.         mov BYTE PTR [esi+FMUSIC_CHANNEL.tremolopos-2],al ; = 0
  3092. z2_tremolopos_ok:
  3093.         test cl,0Ch
  3094.         jnz z2_vibpos_ok
  3095.         mov BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2],al ; = 0
  3096. z2_vibpos_ok:
  3097.         mov eax,[esi+FMUSIC_CHANNEL.period-2]
  3098.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOL_OR_FREQ_OR_TR
  3099.         mov [esi+FMUSIC_CHANNEL.freq-2],eax
  3100. if VOLUMEBYTE_ON
  3101.         mov eax,[ebp+doeff_current]
  3102.         movzx edx,BYTE PTR [eax+FMUSIC_NOTE.uvolume]
  3103.         ; volume : EDX
  3104.         ; cptr   : ESI
  3105.         jmp VolByte
  3106. else
  3107.         ret
  3108. endif
  3109. doeff_notectrl_z:
  3110.         mov BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],al
  3111. doeff_special_r:
  3112. endif
  3113.         ret
  3114. if NOTECUT_ON
  3115. doeff_do_notecut:
  3116.         mov ecx,[ebp+var_mod]
  3117.         cmp [ecx+FMUSIC_MODULE.tick-36],ebx
  3118.         jne doeff_notecut_ok
  3119.         and DWORD PTR [esi+FMUSIC_CHANNEL.volume-2],0
  3120.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  3121. doeff_notecut_ok:
  3122.         ret
  3123. endif
  3124. if RETRIG_ON
  3125. doeff_do_retrig:
  3126.         test ebx,ebx
  3127.         jz doeff_retrig_ok
  3128.         mov eax,[ebp+var_mod]
  3129.         mov eax,[eax+FMUSIC_MODULE.tick-36]
  3130.         cdq
  3131.         idiv ebx
  3132.         test edx,edx
  3133.         jne doeff_retrig_ok
  3134.         or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOL_OR_FREQ_OR_TR
  3135. doeff_retrig_ok:
  3136.         ret
  3137. endif
  3138.  
  3139. ; DESCRIPTION: Process sample flags
  3140. DoFlags:
  3141. ; cptr+2 - ESI
  3142. flags_iptr equ 16
  3143. flags_sptr equ 12
  3144.         mov ebx,esi
  3145.         push esi
  3146.         push edi
  3147. if INSTRUMENTVIBRATO_ON
  3148.         ; THIS GETS ADDED TO PREVIOUS FREQDELTAS
  3149.         mov esi,[esp+flags_iptr]
  3150.         xor eax,eax
  3151.         movzx edx,BYTE PTR [esi+FMUSIC_INSTRUMENT.VIBtype]
  3152.         lea edi,[ebx+FMUSIC_CHANNEL.ivibpos-2]
  3153.         dec edx ; switch(iptr->VIBtype)
  3154.         js ivib_case_0
  3155.         mov al,128
  3156.         jz ivib_case_1
  3157.         dec edx
  3158.         jz ivib_case_2
  3159.         ; case 3 / default
  3160.         mov dl,-128 ; -128 = 384 on a 1byte scope
  3161.         sub edx,[edi]
  3162. trim:
  3163.         movzx edx,dl
  3164.         sub eax,edx
  3165.         sar eax,1 ; delta = (128-((384-cptr->ivibpos)&0xFF))>>1 (case 3)
  3166.                   ; delta = (128-((cptr->ivibpos+128)&0xFF))>>1 (case 2)
  3167.         jmp ivib_end_switch
  3168. ivib_case_2:
  3169.         mov edx,[edi]
  3170.         sub edx,eax
  3171.         jmp trim
  3172. ivib_case_1:
  3173.         cmp [edi],eax
  3174.         sbb edx,edx
  3175.         and edx,eax
  3176.         lea eax,[edx-64] ; delta = +/- 64
  3177.         jmp ivib_end_switch
  3178. ivib_case_0:
  3179.         ; delta = 64 sin(2 Pi x/256)
  3180.         mov ecx,[edi]
  3181.         mov edx,ecx
  3182.         and ecx,7Fh
  3183.         cmp ecx,65
  3184.         adc eax,-1
  3185.         xor ecx,eax
  3186.         and eax,129
  3187.         add ecx,eax
  3188.         shr edx,8
  3189.         movzx eax,BYTE PTR [OFFSET sin64+ecx]
  3190.         sbb edx,edx
  3191.         xor eax,edx
  3192.         sub eax,edx
  3193. ivib_end_switch:
  3194.         movzx edx,BYTE PTR [esi+FMUSIC_INSTRUMENT.iVIBdepth]
  3195.         imul edx,eax ; delta *= iptr->iVIBdepth
  3196.         movzx eax,BYTE PTR [esi+FMUSIC_INSTRUMENT.VIBsweep]
  3197.         test eax,eax
  3198.         jz sweep_ok
  3199.         push edi
  3200.         xchg eax,edi
  3201.         mov eax,[ebx+FMUSIC_CHANNEL.ivibsweeppos-2]
  3202.         imul edx
  3203.         idiv edi
  3204.         xchg eax,edx ; delta *= cptr->ivibsweeppos/iptr->VIBsweep
  3205.         xchg eax,edi ; iptr->VIBsweep
  3206.         pop edi
  3207. sweep_ok:
  3208.         sar edx,6
  3209.         add [ebx+FMUSIC_CHANNEL.freqdelta-2],edx ; cptr->freqdelta += delta>>6
  3210.         mov edx,[ebx+FMUSIC_CHANNEL.ivibsweeppos-2]
  3211.         inc edx
  3212.         cmp edx,eax
  3213.         jle sweeppos_ok
  3214.         xchg eax,edx
  3215. sweeppos_ok:
  3216.         movzx eax,BYTE PTR [esi+FMUSIC_INSTRUMENT.VIBrate]
  3217.         add eax,[edi] ; cptr->ivibpos += iptr->VIBrate
  3218.         mov [ebx+FMUSIC_CHANNEL.ivibsweeppos-2],edx
  3219.         neg ah
  3220.         or BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
  3221.         neg ah
  3222.         sbb ah,0 ; ivibpos - 256
  3223.         mov [edi],eax
  3224. endif ; INSTRUMENTVIBRATO_ON
  3225.         mov esi,[ebx+FMUSIC_CHANNEL.cptr-2]
  3226.         test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_TRIGGER
  3227.         jz no_trig
  3228.         ; TRIGGER: allocate a channel
  3229.         cmp DWORD PTR [esi+FSOUND_CHANNEL.fsptr],0
  3230.         jz no_swap
  3231.         ; Swap between channels to avoid sounds cutting each other off and causing a click
  3232.         mov ecx,esi
  3233.         sub ecx,DWORD PTR [OFFSET _mod+FMUSIC_MODULE.Channels]
  3234.         shr ecx,7 ; /FSOUND_CHANNEL_size + 1
  3235.         sbb edi,edi
  3236.         and edi,-FSOUND_CHANNEL_size*2
  3237.         lea edi,[esi+edi+FSOUND_CHANNEL_size]
  3238.         push edi
  3239.         ; Copy the whole channel except it's trailing data
  3240.         push (FSOUND_CHANNEL_size-20)/4
  3241.         mov [ebx+FMUSIC_CHANNEL.cptr-2],edi
  3242.         pop ecx
  3243.         rep movsd
  3244.         ; This should cause the old channel to ramp out nicely
  3245.         mov [esi+FSOUND_CHANNEL.actualvolume-FSOUND_CHANNEL.fsptr],ecx
  3246.         mov [esi+FSOUND_CHANNEL.leftvolume-FSOUND_CHANNEL.fsptr],ecx
  3247.         mov [esi+FSOUND_CHANNEL.rightvolume-FSOUND_CHANNEL.fsptr],ecx
  3248.         pop esi
  3249. no_swap:
  3250.         lea edi,[esi+FSOUND_CHANNEL.fsptr]
  3251.         mov eax,[esp+flags_sptr]
  3252.         stosd ; fsptr
  3253.         ; START THE SOUND!
  3254.         xor eax,eax
  3255.         mov edx,[esi+FSOUND_CHANNEL.fsampleoffset]
  3256.         stosd ; mixposlo
  3257.         stosd ; ramp_leftvolume
  3258.         stosd ; ramp_rightvolume
  3259.         stosd ; ramp_count, speeddir
  3260.         mov [esi+FSOUND_CHANNEL.fsampleoffset],eax
  3261.         mov [esi+FSOUND_CHANNEL.mixpos],edx
  3262. no_trig:
  3263.         mov eax,[ebx+FMUSIC_CHANNEL.volume-2]
  3264.         xor ecx,ecx
  3265.         cdq
  3266.         not edx
  3267.         and eax,edx
  3268.         cmp eax,64
  3269.         jle volume_le64
  3270.         lea eax,[ecx+64]
  3271. volume_le64:
  3272.         dec cl ; ecx <- 255
  3273.         mov [ebx+FMUSIC_CHANNEL.volume-2],eax
  3274.         test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
  3275.         jz no_volume
  3276.         add eax,[ebx+FMUSIC_CHANNEL.voldelta-2]          ; 6 bit  (64)
  3277.         imul DWORD PTR [ebx+FMUSIC_CHANNEL.envvol-2]     ; 6 bit  (64)
  3278.         imul DWORD PTR [_mod+FMUSIC_MODULE.globalvolume] ; 6 bit  (64)
  3279.         imul ecx ; eax *= 255
  3280.         imul DWORD PTR [ebx+FMUSIC_CHANNEL.fadeoutvol-2] ; 16 bit (65536)
  3281.         ; eax:edx /= (2 * 64 * 64 * 64 * 65536)
  3282.         sar edx,3
  3283.         mov eax,[esi+FSOUND_CHANNEL.actualpan]
  3284.         mov [esi+FSOUND_CHANNEL.actualvolume],edx
  3285.         mov edi,edx
  3286.         imul edx
  3287.         idiv ecx
  3288.         mov [esi+FSOUND_CHANNEL.leftvolume],eax ; leftvolume <- volume*actualpan/255
  3289.         mov eax,ecx
  3290.         sub eax,[esi+FSOUND_CHANNEL.actualpan]
  3291.         imul edi
  3292.         idiv ecx
  3293.         mov [esi+FSOUND_CHANNEL.rightvolume],eax
  3294. no_volume:
  3295.         test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
  3296.         jz no_pan
  3297.         mov edi,128
  3298.         mov eax,[ebx+FMUSIC_CHANNEL.pan-2]
  3299.         sub eax,edi
  3300.         cdq
  3301.         xor eax,edx
  3302.         sub eax,edx
  3303.         sub edi,eax
  3304.         mov eax,[ebx+FMUSIC_CHANNEL.envpan-2]
  3305.         sar edi,5
  3306.         sub eax,32
  3307.         imul edi
  3308.         add eax,[ebx+FMUSIC_CHANNEL.pan-2]
  3309.         cdq
  3310.         not edx
  3311.         and eax,edx   ; if(pan < 0) pan = 0
  3312.         mov edi,[esi] ; actualvolume
  3313.         cmp eax,ecx
  3314.         mov edx,ecx
  3315.         xchg eax,edi
  3316.         jae pan_ae255
  3317.         imul edi
  3318.         idiv ecx
  3319.         mov edx,edi
  3320. pan_ae255:
  3321.         xchg eax,edx
  3322.         mov [esi+FSOUND_CHANNEL.actualpan],eax
  3323.         mov [esi+FSOUND_CHANNEL.leftvolume],edx
  3324.         not al ; 255 - pan
  3325.         imul DWORD PTR [esi] ; actualvolume
  3326.         idiv ecx
  3327.         mov [esi+FSOUND_CHANNEL.rightvolume],eax
  3328. no_pan:
  3329.         test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
  3330.         jz no_freq
  3331.         mov ecx,[ebx+FMUSIC_CHANNEL.freq-2]
  3332.         xor edx,edx
  3333.         add ecx,[ebx+FMUSIC_CHANNEL.freqdelta-2]
  3334.         lea eax,[edx+40] ; f = 40 Hz
  3335.         jle freq_bounds_ok
  3336.         test BYTE PTR [_mod+FMUSIC_MODULE.flags],1
  3337.         jnz modflags_n1
  3338.         mov eax,0DA7790h
  3339.         div ecx
  3340.         xor edx,edx
  3341.         jmp freq_bounds_ok
  3342. modflags_n1:
  3343.         mov eax,4608
  3344.         sub eax,[ebx+FMUSIC_CHANNEL.freq-2]
  3345.         add eax,[ebx+FMUSIC_CHANNEL.freqdelta-2]
  3346.         push eax
  3347.         fild DWORD PTR [esp]
  3348.         fmul DWORD PTR [f0_0013]
  3349.         fld st0
  3350.         frndint
  3351.         fsub st1,st0
  3352.         fxch st1
  3353.         f2xm1
  3354.         fld1
  3355.         faddp st1,st0
  3356.         fscale
  3357.         fstp st1
  3358.         fmul DWORD PTR [f8363_0]
  3359.         fistp DWORD PTR [esp]
  3360.         pop eax ; freq = 625.271028*exp2((4608-period)/64)
  3361. freq_bounds_ok:
  3362.         mov ebx,FSOUND_MixRate
  3363.         div ebx
  3364.         mov [esi+FSOUND_CHANNEL.speedhi],eax
  3365.         div ebx
  3366.         mov [esi+FSOUND_CHANNEL.speedlo],eax
  3367. no_freq:
  3368.         pop edi
  3369.         pop esi
  3370. if INSTRUMENTVIBRATO_ON
  3371.         ret 8
  3372. else
  3373.         ret 4
  3374. endif