Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1845 yogev_ezra 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