Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1845 | yogev_ezra | 1 | ; UFMOD.ASM |
2 | ; --------- |
||
3 | ; uFMOD public source code release. Provided as-is. |
||
4 | |||
5 | SOUND_VERSION equ 100h ; required Infinity sound driver version |
||
6 | FSOUND_Block equ 10 |
||
7 | FSOUND_BlockSize equ 1024 ; 1 << FSOUND_Block |
||
8 | |||
9 | if DEBUG |
||
10 | |||
11 | ; Debug messages: |
||
12 | sDBGMSG1 db "uFMOD: XM track loaded",13,10,0 |
||
13 | sDBGMSG2 db "uFMOD: Infinity driver loaded",13,10,0 |
||
14 | sDBGMSG3 db "uFMOD: Buffer created",13,10,0 |
||
15 | sDBGMSG4 db "uFMOD: Sound buffer destroyed",13,10,0 |
||
16 | sDBGMSG5 db "uFMOD: Infinity version: ",0 |
||
17 | |||
18 | ; DEBUG board: print a string. |
||
19 | DBG_print_s: |
||
20 | ; EDX = msg (trailing 0 is required!) |
||
21 | pushad |
||
22 | DBG_print_s_loop: |
||
23 | mov eax,63 |
||
24 | mov ebx,1 |
||
25 | mov cl,[edx] |
||
26 | test cl,cl |
||
27 | jz DBG_print_s_R |
||
28 | int 40h |
||
29 | inc edx |
||
30 | jmp DBG_print_s_loop |
||
31 | DBG_print_s_R: |
||
32 | popad |
||
33 | ret |
||
34 | |||
35 | ; DEBUG board: print the hex value in EAX. |
||
36 | DBG_print_x: |
||
37 | ; EAX = val |
||
38 | pushad |
||
39 | mov esi,eax |
||
40 | mov edx,OFFSET MixBuf |
||
41 | mov ecx,7 |
||
42 | mov DWORD PTR [edx+8],0A0Dh |
||
43 | print_eax_loop: |
||
44 | mov eax,esi |
||
45 | and al,0Fh |
||
46 | cmp al,10 |
||
47 | sbb al,69h |
||
48 | das |
||
49 | mov [edx+ecx],al |
||
50 | shr esi,4 |
||
51 | dec ecx |
||
52 | jns print_eax_loop |
||
53 | call DBG_print_s |
||
54 | popad |
||
55 | ret |
||
56 | endif ; DEBUG |
||
57 | |||
58 | if RAMP_STRONG |
||
59 | volumerampsteps equ 128 |
||
60 | volumeramps_pow equ 7 |
||
61 | endif |
||
62 | |||
63 | if RAMP_WEAK |
||
64 | volumerampsteps equ 16 |
||
65 | volumeramps_pow equ 4 |
||
66 | endif |
||
67 | |||
68 | if RAMP_NONE |
||
69 | volumerampsteps equ 64 |
||
70 | volumeramps_pow equ 6 |
||
71 | endif |
||
72 | |||
73 | XM_MEMORY equ 1 |
||
74 | XM_FILE equ 2 |
||
75 | XM_NOLOOP equ 8 |
||
76 | XM_SUSPENDED equ 16 |
||
77 | FMUSIC_ENVELOPE_SUSTAIN equ 2 |
||
78 | FMUSIC_ENVELOPE_LOOP equ 4 |
||
79 | FMUSIC_FREQ equ 1 |
||
80 | FMUSIC_VOLUME equ 2 |
||
81 | FMUSIC_PAN equ 4 |
||
82 | FMUSIC_TRIGGER equ 8 |
||
83 | FMUSIC_VOLUME_OR_FREQ equ 3 |
||
84 | FMUSIC_VOLUME_OR_PAN equ 6 |
||
85 | FMUSIC_VOL_OR_FREQ_OR_TR equ 11 |
||
86 | FMUSIC_FREQ_OR_TRIGGER equ 9 |
||
87 | NOT_FMUSIC_TRIGGER equ 0F7h |
||
88 | NOT_FMUSIC_TRIGGER_OR_FRQ equ 0F6h |
||
89 | |||
90 | ; FMUSIC_XMCOMMANDS enum: |
||
91 | FMUSIC_XM_PORTAUP equ 1 |
||
92 | FMUSIC_XM_PORTADOWN equ 2 |
||
93 | FMUSIC_XM_PORTATO equ 3 |
||
94 | FMUSIC_XM_VIBRATO equ 4 |
||
95 | FMUSIC_XM_PORTATOVOLSLIDE equ 5 |
||
96 | FMUSIC_XM_VIBRATOVOLSLIDE equ 6 |
||
97 | FMUSIC_XM_TREMOLO equ 7 |
||
98 | FMUSIC_XM_SETPANPOSITION equ 8 |
||
99 | FMUSIC_XM_SETSAMPLEOFFSET equ 9 |
||
100 | FMUSIC_XM_VOLUMESLIDE equ 10 |
||
101 | FMUSIC_XM_PATTERNJUMP equ 11 |
||
102 | FMUSIC_XM_SETVOLUME equ 12 |
||
103 | FMUSIC_XM_PATTERNBREAK equ 13 |
||
104 | FMUSIC_XM_SPECIAL equ 14 |
||
105 | FMUSIC_XM_SETSPEED equ 15 |
||
106 | FMUSIC_XM_SETGLOBALVOLUME equ 16 |
||
107 | FMUSIC_XM_GLOBALVOLSLIDE equ 17 |
||
108 | FMUSIC_XM_KEYOFF equ 20 |
||
109 | FMUSIC_XM_PANSLIDE equ 25 |
||
110 | FMUSIC_XM_MULTIRETRIG equ 27 |
||
111 | FMUSIC_XM_TREMOR equ 29 |
||
112 | FMUSIC_XM_EXTRAFINEPORTA equ 33 |
||
113 | |||
114 | ; FMUSIC_XMCOMMANDSSPECIAL enum: |
||
115 | FMUSIC_XM_FINEPORTAUP equ 1 |
||
116 | FMUSIC_XM_FINEPORTADOWN equ 2 |
||
117 | FMUSIC_XM_SETGLISSANDO equ 3 |
||
118 | FMUSIC_XM_SETVIBRATOWAVE equ 4 |
||
119 | FMUSIC_XM_SETFINETUNE equ 5 |
||
120 | FMUSIC_XM_PATTERNLOOP equ 6 |
||
121 | FMUSIC_XM_SETTREMOLOWAVE equ 7 |
||
122 | FMUSIC_XM_SETPANPOSITION16 equ 8 |
||
123 | FMUSIC_XM_RETRIG equ 9 |
||
124 | FMUSIC_XM_NOTECUT equ 12 |
||
125 | FMUSIC_XM_NOTEDELAY equ 13 |
||
126 | FMUSIC_XM_PATTERNDELAY equ 14 |
||
127 | |||
128 | if AC97SND_ON |
||
129 | |||
130 | file_read: |
||
131 | ; buf in EAX |
||
132 | ; size in EDX |
||
133 | push ebx |
||
134 | push esi |
||
135 | push edi |
||
136 | push ebp |
||
137 | xchg eax,edi |
||
138 | file_read_begin: |
||
139 | test edx,edx |
||
140 | jg file_read_chk_cache |
||
141 | file_read_done: |
||
142 | pop ebp |
||
143 | pop edi |
||
144 | pop esi |
||
145 | pop ebx |
||
146 | ret |
||
147 | ; *** CHECK IN THE CACHE |
||
148 | file_read_chk_cache: |
||
149 | mov ebp,OFFSET file_struct |
||
150 | mov esi,[ebp-24] |
||
151 | sub esi,[ebp+28] ; cache_offset |
||
152 | js file_read_cache_done |
||
153 | mov ecx,8192 |
||
154 | sub ecx,esi |
||
155 | jle file_read_cache_done |
||
156 | add esi,OFFSET MixBuf |
||
157 | sub edx,ecx |
||
158 | jns file_read_do_cache |
||
159 | add ecx,edx |
||
160 | file_read_do_cache: |
||
161 | add [ebp-24],ecx |
||
162 | rep movsb |
||
163 | test edx,edx |
||
164 | jle file_read_done ; data read from the cache (no need to access the FS) |
||
165 | file_read_cache_done: |
||
166 | ; *** FS BATCH READ OPERATION |
||
167 | mov eax,[ebp-24] |
||
168 | mov ecx,edx |
||
169 | add ecx,eax |
||
170 | and ecx,0FFFFE000h |
||
171 | sub ecx,eax |
||
172 | jle file_read_fs_done ; Too few data requested for a FS batch operation |
||
173 | sub edx,ecx |
||
174 | mov [ebp+4],eax ; file offset |
||
175 | mov [ebp+12],ecx ; NumberOfBytesToRead |
||
176 | mov [ebp+16],edi ; lpBuffer |
||
177 | mov ebx,ebp |
||
178 | add edi,ecx |
||
179 | push 70 |
||
180 | add [ebp-24],ecx |
||
181 | pop eax |
||
182 | int 40h |
||
183 | file_read_fs_done: |
||
184 | ; *** UPDATE THE CACHE |
||
185 | mov ecx,[ebp-24] |
||
186 | and ecx,0FFFFE000h |
||
187 | mov [ebp+4],ecx ; file offset |
||
188 | mov [ebp+28],ecx ; cache_offset |
||
189 | mov DWORD PTR [ebp+12],8192 ; NumberOfBytesToRead |
||
190 | mov DWORD PTR [ebp+16],OFFSET MixBuf ; lpBuffer |
||
191 | mov ebx,ebp |
||
192 | push 70 |
||
193 | pop eax |
||
194 | int 40h |
||
195 | jmp file_read_begin |
||
196 | |||
197 | if INFO_API_ON |
||
198 | PUBLIC _uFMOD_GetTitle |
||
199 | _uFMOD_GetTitle: |
||
200 | mov eax,OFFSET szTtl |
||
201 | ret |
||
202 | endif |
||
203 | |||
204 | else |
||
205 | uFMOD_mem dd mem_open, mem_read |
||
206 | if XM_FILE_ON |
||
207 | uFMOD_fs dd file_open, file_read |
||
208 | endif |
||
209 | |||
210 | szInfinity db "INFINITY",0 |
||
211 | |||
212 | if JUMP_TO_PAT_ON |
||
213 | |||
214 | ; Jump to the given pattern |
||
215 | PUBLIC _uFMOD_Jump2Pattern |
||
216 | _uFMOD_Jump2Pattern: |
||
217 | mov eax,[esp+4] |
||
218 | mov ecx,OFFSET _mod+36 |
||
219 | movzx eax,ax |
||
220 | and DWORD PTR [ecx+FMUSIC_MODULE.nextrow-36],0 |
||
221 | cmp ax,[ecx+FMUSIC_MODULE.numorders-36] |
||
222 | sbb edx,edx |
||
223 | and eax,edx |
||
224 | mov [ecx+FMUSIC_MODULE.nextorder-36],eax |
||
225 | ret |
||
226 | endif |
||
227 | |||
228 | if VOL_CONTROL_ON |
||
229 | |||
230 | ; Set global volume [0: silence, 25: max. volume] |
||
231 | vol_scale dw 1 ; -45 dB |
||
232 | dw 130 ; -24 |
||
233 | dw 164 ; -23 |
||
234 | dw 207 ; -22 |
||
235 | dw 260 ; -21 |
||
236 | dw 328 ; -20 |
||
237 | dw 413 ; -19 |
||
238 | dw 519 ; -18 |
||
239 | dw 654 ; -17 |
||
240 | dw 823 ; -16 |
||
241 | dw 1036 ; -15 |
||
242 | dw 1305 ; -14 |
||
243 | dw 1642 ; -13 |
||
244 | dw 2068 ; -12 |
||
245 | dw 2603 ; -11 |
||
246 | dw 3277 ; -10 |
||
247 | dw 4125 ; -9 |
||
248 | dw 5193 ; -8 |
||
249 | dw 6538 ; -7 |
||
250 | dw 8231 ; -6 |
||
251 | dw 10362 ; -5 |
||
252 | dw 13045 ; -4 |
||
253 | dw 16423 ; -3 |
||
254 | dw 20675 ; -2 |
||
255 | dw 26029 ; -1 |
||
256 | dw 32768 ; 0 dB |
||
257 | PUBLIC _uFMOD_SetVolume |
||
258 | _uFMOD_SetVolume: |
||
259 | mov eax,[esp+4] |
||
260 | cmp eax,25 |
||
261 | jna get_vol_scale |
||
262 | push 25 |
||
263 | pop eax |
||
264 | get_vol_scale: |
||
265 | mov ax,[vol_scale+eax*2] |
||
266 | mov [ufmod_vol],eax |
||
267 | ret |
||
268 | endif |
||
269 | |||
270 | if PAUSE_RESUME_ON |
||
271 | |||
272 | ; Pause the currently playing song. |
||
273 | PUBLIC _uFMOD_Pause |
||
274 | _uFMOD_Pause: |
||
275 | mov al,1 |
||
276 | jmp $+4 |
||
277 | |||
278 | ; Resume the currently paused song. |
||
279 | PUBLIC _uFMOD_Resume |
||
280 | _uFMOD_Resume: |
||
281 | xor eax,eax |
||
282 | mov BYTE PTR [ufmod_pause_],al |
||
283 | ret |
||
284 | endif |
||
285 | |||
286 | if INFO_API_ON |
||
287 | |||
288 | ; Return currently playing signal stats: |
||
289 | ; lo word : RMS volume in R channel |
||
290 | ; hi word : RMS volume in L channel |
||
291 | PUBLIC _uFMOD_GetStats |
||
292 | _uFMOD_GetStats: |
||
293 | push 4 |
||
294 | jmp _uFMOD_InfoApi |
||
295 | |||
296 | ; Return currently playing row and order: |
||
297 | ; lo word : row |
||
298 | ; hi word : order |
||
299 | PUBLIC _uFMOD_GetRowOrder |
||
300 | _uFMOD_GetRowOrder: |
||
301 | push 8 |
||
302 | jmp _uFMOD_InfoApi |
||
303 | |||
304 | ; Return the time in milliseconds since the song was started. |
||
305 | PUBLIC _uFMOD_GetTime |
||
306 | _uFMOD_GetTime: |
||
307 | push 0 |
||
308 | _uFMOD_InfoApi: |
||
309 | pop edx |
||
310 | mov eax,[time_ms+edx] |
||
311 | ret |
||
312 | endif |
||
313 | |||
314 | ; *********************** |
||
315 | ; * XM_MEMORY CALLBACKS * |
||
316 | ; *********************** |
||
317 | mem_read: |
||
318 | ; buf in EAX |
||
319 | ; size in EDX |
||
320 | push edi |
||
321 | push esi |
||
322 | xchg eax,edi ; buf |
||
323 | mov esi,OFFSET mmf |
||
324 | lodsd |
||
325 | mov ecx,edx |
||
326 | add edx,[esi] |
||
327 | cmp edx,eax |
||
328 | jl copy |
||
329 | sub eax,[esi] |
||
330 | xchg eax,ecx |
||
331 | copy: |
||
332 | test ecx,ecx |
||
333 | jle mem_read_R |
||
334 | lodsd |
||
335 | add eax,[esi] |
||
336 | mov [esi-4],edx |
||
337 | mem_do_copy: |
||
338 | mov dl,[eax] |
||
339 | mov [edi],dl |
||
340 | inc eax |
||
341 | inc edi |
||
342 | dec ecx |
||
343 | jnz mem_do_copy |
||
344 | mem_read_R: |
||
345 | pop esi |
||
346 | pop edi |
||
347 | if INFO_API_ON |
||
348 | PUBLIC _uFMOD_GetTitle |
||
349 | _uFMOD_GetTitle: |
||
350 | mov eax,OFFSET szTtl |
||
351 | endif |
||
352 | mem_open: |
||
353 | ret |
||
354 | |||
355 | ; ********************* |
||
356 | ; * XM_FILE CALLBACKS * |
||
357 | ; ********************* |
||
358 | if XM_FILE_ON |
||
359 | file_open: |
||
360 | ; pszName in ESI |
||
361 | ; Prepare the FILE struct for subsecuent I/O: |
||
362 | lea eax,[ebp+8] ; file_struct |
||
363 | xor edx,edx |
||
364 | mov [eax],edx ; +0 subfunction: 0 = read |
||
365 | mov [eax+8],edx ; +8 Reserved |
||
366 | ; +12 NumberOfBytesToRead |
||
367 | ; +16 lpBuffer |
||
368 | push -1 |
||
369 | push 1 |
||
370 | mov [eax+20],dl ; +20 db 0 |
||
371 | mov [eax+21],esi ; +21 lpFileName |
||
372 | pop DWORD PTR [eax+28] ; cache_offset |
||
373 | pop DWORD PTR [eax-28] ; [mmf] = maximum size |
||
374 | ret |
||
375 | |||
376 | file_read: |
||
377 | ; buf in EAX |
||
378 | ; size in EDX |
||
379 | push ebx |
||
380 | push esi |
||
381 | push edi |
||
382 | push ebp |
||
383 | xchg eax,edi |
||
384 | file_read_begin: |
||
385 | test edx,edx |
||
386 | jg file_read_chk_cache |
||
387 | file_read_done: |
||
388 | pop ebp |
||
389 | pop edi |
||
390 | pop esi |
||
391 | pop ebx |
||
392 | ret |
||
393 | ; *** CHECK IN THE CACHE |
||
394 | file_read_chk_cache: |
||
395 | mov ebp,OFFSET file_struct |
||
396 | mov esi,[ebp-24] |
||
397 | sub esi,[ebp+28] ; cache_offset |
||
398 | js file_read_cache_done |
||
399 | mov ecx,8192 |
||
400 | sub ecx,esi |
||
401 | jle file_read_cache_done |
||
402 | add esi,OFFSET MixBuf |
||
403 | sub edx,ecx |
||
404 | jns file_read_do_cache |
||
405 | add ecx,edx |
||
406 | file_read_do_cache: |
||
407 | add [ebp-24],ecx |
||
408 | rep movsb |
||
409 | test edx,edx |
||
410 | jle file_read_done ; data read from the cache (no need to access the FS) |
||
411 | file_read_cache_done: |
||
412 | ; *** FS BATCH READ OPERATION |
||
413 | mov eax,[ebp-24] |
||
414 | mov ecx,edx |
||
415 | add ecx,eax |
||
416 | and ecx,0FFFFE000h |
||
417 | sub ecx,eax |
||
418 | jle file_read_fs_done ; Too few data requested for a FS batch operation |
||
419 | sub edx,ecx |
||
420 | mov [ebp+4],eax ; file offset |
||
421 | mov [ebp+12],ecx ; NumberOfBytesToRead |
||
422 | mov [ebp+16],edi ; lpBuffer |
||
423 | mov ebx,ebp |
||
424 | add edi,ecx |
||
425 | push 70 |
||
426 | add [ebp-24],ecx |
||
427 | pop eax |
||
428 | int 40h |
||
429 | file_read_fs_done: |
||
430 | ; *** UPDATE THE CACHE |
||
431 | mov ecx,[ebp-24] |
||
432 | and ecx,0FFFFE000h |
||
433 | mov [ebp+4],ecx ; file offset |
||
434 | mov [ebp+28],ecx ; cache_offset |
||
435 | mov DWORD PTR [ebp+12],8192 ; NumberOfBytesToRead |
||
436 | mov DWORD PTR [ebp+16],OFFSET MixBuf ; lpBuffer |
||
437 | mov ebx,ebp |
||
438 | push 70 |
||
439 | pop eax |
||
440 | int 40h |
||
441 | jmp file_read_begin |
||
442 | endif |
||
443 | |||
444 | endif ; AC97SND_ON = 0 |
||
445 | |||
446 | uFMOD_lseek: |
||
447 | ; pos in EAX |
||
448 | ; org in ECX |
||
449 | ; !org in Z |
||
450 | mov edx,OFFSET mmf+4 |
||
451 | jz mem_ok |
||
452 | add eax,[edx] |
||
453 | mem_ok: |
||
454 | test eax,eax |
||
455 | js mem_seek_R |
||
456 | cmp eax,[edx-4] |
||
457 | ja mem_seek_R |
||
458 | mov [edx],eax |
||
459 | mem_seek_R: |
||
460 | ret |
||
461 | |||
462 | ; Dynamic memory allocation |
||
463 | alloc: |
||
464 | ; EAX: how many bytes to allocate |
||
465 | add eax,3 |
||
466 | and eax,-4 |
||
467 | jle alloc_error2 |
||
468 | mov ecx,OFFSET ufmod_heap |
||
469 | alloc_lookup: |
||
470 | cmp DWORD PTR [ecx],0 |
||
471 | je do_alloc |
||
472 | mov ecx,[ecx] |
||
473 | cmp [ecx+4],eax |
||
474 | jl alloc_lookup |
||
475 | sub [ecx+4],eax |
||
476 | mov eax,[ecx+4] |
||
477 | lea eax,[eax+ecx+8] |
||
478 | ret |
||
479 | do_alloc: |
||
480 | add eax,8 |
||
481 | push ebx |
||
482 | push edi |
||
483 | mov ebx,eax |
||
484 | add ebx,8191 |
||
485 | neg eax |
||
486 | and ebx,-8192 |
||
487 | push ecx |
||
488 | add eax,ebx |
||
489 | xchg eax,edi |
||
490 | push 12 |
||
491 | push 68 |
||
492 | mov ecx,ebx |
||
493 | pop eax |
||
494 | pop ebx |
||
495 | int 40h |
||
496 | ; Test for error condition |
||
497 | test eax,eax |
||
498 | pop ebx |
||
499 | mov edx,edi ; free space |
||
500 | jz alloc_error1 |
||
501 | mov [ebx],eax |
||
502 | mov edi,eax |
||
503 | lea eax,[eax+edx+8] |
||
504 | mov [edi+4],edx |
||
505 | pop edi |
||
506 | pop ebx |
||
507 | ret |
||
508 | alloc_error1: |
||
509 | pop edi |
||
510 | pop ebx |
||
511 | alloc_error2: |
||
512 | xor eax,eax |
||
513 | pop edx ; EIP |
||
514 | pop ebx |
||
515 | leave |
||
516 | _alloc_R: |
||
517 | ret |
||
518 | |||
519 | ; Starts playing a song. |
||
520 | PUBLIC _uFMOD_LoadSong |
||
521 | _uFMOD_LoadSong: |
||
522 | |||
523 | ; *** FREE PREVIOUS TRACK, IF ANY |
||
524 | call _uFMOD_StopSong |
||
525 | |||
526 | if AC97SND_ON |
||
527 | mov ecx,[esp+4] |
||
528 | push ebx |
||
529 | push esi |
||
530 | push edi |
||
531 | push ebp |
||
532 | mov ebp,OFFSET uFMOD_fopen |
||
533 | ; Prepare the FILE struct for subsecuent I/O: |
||
534 | lea eax,[ebp+8] ; file_struct |
||
535 | xor edx,edx |
||
536 | mov [eax],edx ; +0 subfunction: 0 = read |
||
537 | mov [eax+8],edx ; +8 Reserved |
||
538 | ; +12 NumberOfBytesToRead |
||
539 | ; +16 lpBuffer |
||
540 | mov [eax+20],dl ; +20 db 0 |
||
541 | mov [eax+21],ecx ; +21 lpFileName |
||
542 | push -1 |
||
543 | push 1 |
||
544 | mov DWORD PTR [ebp+4],OFFSET file_read ; uFMOD_fread |
||
545 | pop DWORD PTR [eax+28] ; cache_offset |
||
546 | mov [eax-24],edx |
||
547 | pop DWORD PTR [eax-28] ; [mmf] = maximum size |
||
548 | else |
||
549 | mov eax,[esp+8] ; param |
||
550 | mov ecx,[esp+12] ; fdwSong |
||
551 | mov edx,[esp+4] ; lpXM |
||
552 | test edx,edx |
||
553 | jz _alloc_R |
||
554 | ; *** SET I/O CALLBACKS |
||
555 | push ebx |
||
556 | push esi |
||
557 | push edi |
||
558 | push ebp |
||
559 | mov ebp,OFFSET uFMOD_fopen |
||
560 | mov [ebp-20],eax ; mmf |
||
561 | xor eax,eax |
||
562 | mov [ebp-16],eax ; mmf+4 |
||
563 | test cl,XM_MEMORY |
||
564 | mov esi,OFFSET uFMOD_mem |
||
565 | if XM_FILE_ON |
||
566 | jnz set_callbacks |
||
567 | test cl,XM_FILE |
||
568 | lea esi,[esi+(uFMOD_fs-uFMOD_mem)] |
||
569 | endif |
||
570 | jz goto_StopSong |
||
571 | set_callbacks: |
||
572 | if NOLOOP_ON |
||
573 | test cl,XM_NOLOOP |
||
574 | setnz [ebp-24] ; ufmod_noloop |
||
575 | endif |
||
576 | if PAUSE_RESUME_ON |
||
577 | and cl,XM_SUSPENDED |
||
578 | mov [ebp-23],cl ; ufmod_pause_ |
||
579 | endif |
||
580 | mov edi,ebp ; uFMOD_fopen |
||
581 | movsd |
||
582 | movsd |
||
583 | mov esi,edx ; uFMOD_fopen:lpXM <= ESI |
||
584 | if VOL_CONTROL_ON |
||
585 | cmp [ebp-4],eax ; ufmod_vol |
||
586 | jne play_vol_ok |
||
587 | mov WORD PTR [ebp-4],32768 |
||
588 | play_vol_ok: |
||
589 | endif |
||
590 | xor edi,edi |
||
591 | ; *** INIT THE INFINITY DRIVER |
||
592 | lea eax,[edi+68] |
||
593 | lea ebx,[edi+16] |
||
594 | mov ecx,OFFSET szInfinity |
||
595 | int 40h |
||
596 | test eax,eax |
||
597 | mov [hSound],eax |
||
598 | jz goto_StopSong |
||
599 | if DEBUG |
||
600 | mov edx,OFFSET sDBGMSG2 |
||
601 | call DBG_print_s |
||
602 | endif |
||
603 | ; *** CHECK THE DRIVER VERSION |
||
604 | push edi ; ver = 0 |
||
605 | push esp ; &ver |
||
606 | mov edx,esp |
||
607 | push 4 ; .out_size |
||
608 | push edx ; .output = &&ver |
||
609 | push edi ; .inp_size |
||
610 | push edi ; .input |
||
611 | push edi ; .code = SRV_GETVERSION |
||
612 | push eax ; .handle = [hSound] |
||
613 | lea ebx,[edi+17] |
||
614 | lea eax,[edi+68] |
||
615 | mov ecx,esp |
||
616 | int 40h |
||
617 | add esp,28 |
||
618 | pop eax ; ver |
||
619 | if DEBUG |
||
620 | mov edx,OFFSET sDBGMSG5 |
||
621 | call DBG_print_s |
||
622 | call DBG_print_x |
||
623 | endif |
||
624 | shr eax,16 |
||
625 | cmp eax,SOUND_VERSION |
||
626 | ja _uFMOD_StopSong+4 ; obsolete program version (Hint: try adjusting SOUND_VERSION!) |
||
627 | ; *** ALLOCATE A HEAP OBJECT |
||
628 | lea eax,[edi+68] |
||
629 | lea ebx,[edi+11] |
||
630 | int 40h |
||
631 | test eax,eax |
||
632 | jz goto_StopSong |
||
633 | ; *** LOAD THE TRACK |
||
634 | mov [ebp-12],esi ; mmf+8 <= pMem |
||
635 | if XM_FILE_ON |
||
636 | call DWORD PTR [ebp] ; uFMOD_fopen |
||
637 | endif |
||
638 | |||
639 | endif ; AC97SND_ON = 0 |
||
640 | |||
641 | call LoadXM |
||
642 | test eax,eax |
||
643 | goto_StopSong: |
||
644 | jz _uFMOD_StopSong+4 |
||
645 | if DEBUG |
||
646 | mov edx,OFFSET sDBGMSG1 |
||
647 | call DBG_print_s |
||
648 | endif |
||
649 | |||
650 | if AC97SND_ON |
||
651 | else |
||
652 | xor edi,edi |
||
653 | ; *** CREATE THE PCM BUFFER |
||
654 | push edi ; size (default is 64Kb) |
||
655 | push PCM_format ; format: 16-bit / stereo / sampling rate |
||
656 | mov edx,esp |
||
657 | push OFFSET hBuff |
||
658 | mov eax,esp |
||
659 | push 4 ; .out_size |
||
660 | push eax ; .output = &&hBuff |
||
661 | push 8 ; .inp_size |
||
662 | push edx ; .input |
||
663 | push 1 ; .code = SND_CREATE_BUFF |
||
664 | push DWORD PTR [hSound] ; .handle |
||
665 | lea eax,[edi+68] |
||
666 | lea ebx,[edi+17] |
||
667 | mov ecx,esp |
||
668 | int 40h |
||
669 | pop esi ; <- hSound |
||
670 | add esp,32 |
||
671 | test eax,eax |
||
672 | jnz _uFMOD_StopSong+4 ; buffer not created |
||
673 | if DEBUG |
||
674 | mov edx,OFFSET sDBGMSG3 |
||
675 | call DBG_print_s |
||
676 | endif |
||
677 | xchg eax,esi ; return the driver handle |
||
678 | endif ; AC97SND_ON = 0 |
||
679 | |||
680 | ; *** ENABLE PCM OUTPUT |
||
681 | mov [SW_Exit],eax |
||
682 | pop ebp |
||
683 | pop edi |
||
684 | pop esi |
||
685 | pop ebx |
||
686 | ret |
||
687 | |||
688 | ; Stop the currently playing song, if any, and free all resources allocated for that song. |
||
689 | PUBLIC _uFMOD_StopSong |
||
690 | _uFMOD_StopSong: |
||
691 | push ebx |
||
692 | push esi |
||
693 | push edi |
||
694 | push ebp |
||
695 | ; _uFMOD_StopSong+4 |
||
696 | xor edi,edi |
||
697 | mov ebp,OFFSET ufmod_heap |
||
698 | ; *** DISABLE PCM OUTPUT |
||
699 | mov [ebp+16],edi ; SW_Exit |
||
700 | |||
701 | if AC97SND_ON |
||
702 | else |
||
703 | ; *** STOP AND DESTROY THE PCM BUFFER |
||
704 | mov eax,[ebp+12] ; hBuff |
||
705 | test eax,eax |
||
706 | jz SND_buffer_free |
||
707 | push eax ; buffer |
||
708 | mov edx,esp |
||
709 | push edi ; .out_size |
||
710 | push edi ; .output |
||
711 | push 4 ; .inp_size |
||
712 | push edx ; .input |
||
713 | push 11 ; .code = SND_STOP |
||
714 | push DWORD PTR [ebp+8] ; .handle = [hSound] |
||
715 | lea eax,[edi+68] |
||
716 | lea ebx,[edi+17] |
||
717 | mov ecx,esp |
||
718 | int 40h |
||
719 | mov DWORD PTR [esp+4],2 ; .code = SND_DESTROY_BUFF |
||
720 | lea eax,[edi+68] |
||
721 | int 40h |
||
722 | add esp,28 |
||
723 | if DEBUG |
||
724 | mov edx,OFFSET sDBGMSG4 |
||
725 | call DBG_print_s |
||
726 | endif |
||
727 | SND_buffer_free: |
||
728 | mov [ebp+12],edi ; hBuff |
||
729 | endif ; AC97SND_ON = 0 |
||
730 | |||
731 | ; *** FREE THE HEAP |
||
732 | mov esi,[ebp] ; ufmod_heap |
||
733 | heapfree: |
||
734 | test esi,esi |
||
735 | jz free_R |
||
736 | mov ecx,esi |
||
737 | mov esi,[esi] |
||
738 | lea eax,[edi+68] |
||
739 | lea ebx,[edi+13] |
||
740 | int 40h |
||
741 | jmp heapfree |
||
742 | free_R: |
||
743 | xor eax,eax |
||
744 | |||
745 | if AC97SND_ON |
||
746 | else |
||
747 | if INFO_API_ON |
||
748 | ; *** CLEAR THE INFO API DATA |
||
749 | lea ecx,[eax+4] |
||
750 | mov edi,OFFSET time_ms |
||
751 | rep stosd |
||
752 | endif |
||
753 | endif ; AC97SND_ON = 0 |
||
754 | |||
755 | mov DWORD PTR [ebp],eax ; ufmod_heap |
||
756 | pop ebp |
||
757 | pop edi |
||
758 | pop esi |
||
759 | pop ebx |
||
760 | ret |
||
761 | |||
762 | PUBLIC _uFMOD_WaveOut |
||
763 | _uFMOD_WaveOut: |
||
764 | push edi |
||
765 | push ebp |
||
766 | xor edi,edi |
||
767 | |||
768 | if AC97SND_ON |
||
769 | ; *** PCM OUTPUT ENABLED? |
||
770 | cmp DWORD PTR [SW_Exit],edi |
||
771 | lea eax,[edi+1] ; return error if output not enabled |
||
772 | je _uFMOD_WaveOut_R |
||
773 | ; *** COMPUTE THE NUMBER OF FREE BLOCKS AVAILABLE |
||
774 | lea ecx,[esp+12] ; &hBuff |
||
775 | push edi ; space = 0 |
||
776 | mov edx,esp |
||
777 | push 4 ; .out_size |
||
778 | push edx ; .output = &space |
||
779 | push 4 ; .inp_size |
||
780 | push ecx ; .input |
||
781 | push 17 ; .code = SND_GETFREESPACE |
||
782 | mov ecx,[ecx] |
||
783 | push DWORD PTR [hSound] ; .handle |
||
784 | mov [hBuff],ecx |
||
785 | else |
||
786 | mov ebp,OFFSET hSound |
||
787 | ; *** PCM OUTPUT ENABLED? |
||
788 | cmp [ebp+8],edi ; SW_Exit |
||
789 | lea eax,[edi+1] ; return error if output not enabled |
||
790 | je _uFMOD_WaveOut_R |
||
791 | ; *** COMPUTE THE NUMBER OF FREE BLOCKS AVAILABLE |
||
792 | push edi ; space = 0 |
||
793 | mov edx,esp |
||
794 | push 4 ; .out_size |
||
795 | lea ecx,[ebp+4] ; &hBuff |
||
796 | push edx ; .output = &space |
||
797 | push 4 ; .inp_size |
||
798 | push ecx ; .input |
||
799 | push 17 ; .code = SND_GETFREESPACE |
||
800 | push DWORD PTR [ebp] ; .handle = [hSound] |
||
801 | endif ; AC97SND_ON = 0 |
||
802 | |||
803 | lea ebx,[edi+17] |
||
804 | lea eax,[edi+68] |
||
805 | mov ecx,esp |
||
806 | int 40h |
||
807 | add esp,24 |
||
808 | pop edi ; <- space |
||
809 | shr edi,FSOUND_Block+2 ; / (FSOUND_BlockSize * 4) |
||
810 | jz _uFMOD_WaveOut_R ; no free blocks available |
||
811 | _uFMOD_WaveOut_loop: |
||
812 | call uFMOD_do_WaveOut |
||
813 | neg eax |
||
814 | dec edi |
||
815 | ja _uFMOD_WaveOut_loop |
||
816 | _uFMOD_WaveOut_R: |
||
817 | pop ebp |
||
818 | pop edi |
||
819 | ret |
||
820 | |||
821 | uFMOD_do_WaveOut: |
||
822 | mov ecx,FSOUND_BlockSize*2 |
||
823 | push ebx |
||
824 | push esi |
||
825 | push edi |
||
826 | mov edi,OFFSET MixBuf |
||
827 | xor eax,eax |
||
828 | push edi ; mixbuffer <= MixBuf |
||
829 | push edi ; <- MixPtr |
||
830 | ; MIXBUFFER CLEAR |
||
831 | mov esi,OFFSET _mod+36 |
||
832 | rep stosd |
||
833 | |||
834 | if AC97SND_ON |
||
835 | else |
||
836 | if PAUSE_RESUME_ON |
||
837 | cmp [ufmod_pause_],al |
||
838 | xchg eax,ebp |
||
839 | jne do_swfill |
||
840 | endif |
||
841 | endif ; AC97SND_ON = 0 |
||
842 | |||
843 | mov ebp,FSOUND_BlockSize |
||
844 | ; UPDATE MUSIC |
||
845 | mov ebx,[esi+FMUSIC_MODULE.mixer_samplesleft-36] |
||
846 | fill_loop_1: |
||
847 | test ebx,ebx |
||
848 | jnz mixedleft_nz |
||
849 | ; UPDATE XM EFFECTS |
||
850 | cmp [esi+FMUSIC_MODULE.tick-36],ebx ; new note |
||
851 | mov ecx,[esi+FMUSIC_MODULE.pattern-36] |
||
852 | jne update_effects |
||
853 | dec ebx |
||
854 | ; process any rows commands to set the next order/row |
||
855 | mov edx,[esi+FMUSIC_MODULE.nextorder-36] |
||
856 | mov eax,[esi+FMUSIC_MODULE.nextrow-36] |
||
857 | mov [esi+FMUSIC_MODULE.nextorder-36],ebx |
||
858 | test edx,edx |
||
859 | mov [esi+FMUSIC_MODULE.nextrow-36],ebx |
||
860 | jl fill_nextrow |
||
861 | mov [esi+FMUSIC_MODULE.order-36],edx |
||
862 | fill_nextrow: |
||
863 | test eax,eax |
||
864 | jl update_note |
||
865 | mov [esi+FMUSIC_MODULE.row-36],eax |
||
866 | update_note: |
||
867 | ; mod+36 : ESI |
||
868 | call DoNote |
||
869 | if ROWCOMMANDS_ON |
||
870 | cmp DWORD PTR [esi+FMUSIC_MODULE.nextrow-36],-1 |
||
871 | jne inc_tick |
||
872 | endif |
||
873 | mov eax,[esi+FMUSIC_MODULE.row-36] |
||
874 | inc eax |
||
875 | ; if end of pattern |
||
876 | ; "if(mod->nextrow >= mod->pattern[mod->orderlist[mod->order]].rows)" |
||
877 | cmp ax,[ebx] |
||
878 | jl set_nextrow |
||
879 | mov edx,[esi+FMUSIC_MODULE.order-36] |
||
880 | movzx ecx,WORD PTR [esi+FMUSIC_MODULE.numorders-36] |
||
881 | inc edx |
||
882 | xor eax,eax |
||
883 | cmp edx,ecx |
||
884 | jl set_nextorder |
||
885 | |||
886 | if AC97SND_ON |
||
887 | else |
||
888 | ; We've reached the end of the order list. So, stop playing, unless looping is enabled. |
||
889 | if NOLOOP_ON |
||
890 | cmp [ufmod_noloop],al |
||
891 | je set_restart |
||
892 | pop eax ; skip MixPtr |
||
893 | pop edx ; skip mixbuffer |
||
894 | pop edi |
||
895 | inc eax ; end of loop reached while XM_NOLOOP flag is enabled |
||
896 | pop esi |
||
897 | pop ebx |
||
898 | ret |
||
899 | set_restart: |
||
900 | endif |
||
901 | endif ; AC97SND_ON = 0 |
||
902 | |||
903 | movzx edx,WORD PTR [esi+FMUSIC_MODULE.restart-36] |
||
904 | cmp edx,ecx |
||
905 | sbb ecx,ecx |
||
906 | and edx,ecx |
||
907 | set_nextorder: |
||
908 | mov [esi+FMUSIC_MODULE.nextorder-36],edx |
||
909 | set_nextrow: |
||
910 | mov [esi+FMUSIC_MODULE.nextrow-36],eax |
||
911 | jmp inc_tick |
||
912 | update_effects: |
||
913 | ; mod+36 : ESI |
||
914 | call DoEffs |
||
915 | inc_tick: |
||
916 | mov eax,[esi+FMUSIC_MODULE.speed-36] |
||
917 | mov ebx,[esi+FMUSIC_MODULE.mixer_samplespertick-36] |
||
918 | inc DWORD PTR [esi+FMUSIC_MODULE.tick-36] |
||
919 | if PATTERNDELAY_ON |
||
920 | add eax,[esi+FMUSIC_MODULE.patterndelay-36] |
||
921 | endif |
||
922 | cmp [esi+FMUSIC_MODULE.tick-36],eax |
||
923 | jl mixedleft_nz |
||
924 | if PATTERNDELAY_ON |
||
925 | and DWORD PTR [esi+FMUSIC_MODULE.patterndelay-36],0 |
||
926 | endif |
||
927 | and DWORD PTR [esi+FMUSIC_MODULE.tick-36],0 |
||
928 | mixedleft_nz: |
||
929 | mov edi,ebp |
||
930 | cmp ebx,edi |
||
931 | jae fill_ramp |
||
932 | mov edi,ebx |
||
933 | fill_ramp: |
||
934 | pop edx ; <- MixPtr |
||
935 | sub ebp,edi |
||
936 | lea eax,[edx+edi*8] |
||
937 | push eax ; MixPtr += (SamplesToMix<<3) |
||
938 | ; tail : [arg0] |
||
939 | ; len : EDI |
||
940 | ; mixptr : EDX |
||
941 | ; _mod+36 : ESI |
||
942 | call Ramp |
||
943 | |||
944 | if AC97SND_ON |
||
945 | else |
||
946 | if INFO_API_ON |
||
947 | lea eax,[edi+edi*4] |
||
948 | cdq |
||
949 | shl eax,2 |
||
950 | mov ecx,FSOUND_MixRate/50 |
||
951 | div ecx |
||
952 | ; time_ms += SamplesToMix*FSOUND_OOMixRate*1000 |
||
953 | add [time_ms],eax |
||
954 | endif |
||
955 | endif ; AC97SND_ON = 0 |
||
956 | |||
957 | sub ebx,edi ; MixedLeft -= SamplesToMix |
||
958 | test ebp,ebp |
||
959 | jnz fill_loop_1 |
||
960 | mov [esi+FMUSIC_MODULE.mixer_samplesleft-36],ebx ; <= MixedLeft |
||
961 | |||
962 | if AC97SND_ON |
||
963 | else |
||
964 | if INFO_API_ON |
||
965 | mov ecx,[esi + FMUSIC_MODULE.row-36] |
||
966 | or ecx,[esi + FMUSIC_MODULE.order-2-36] |
||
967 | mov DWORD PTR [s_row],ecx |
||
968 | endif |
||
969 | endif ; AC97SND_ON = 0 |
||
970 | |||
971 | do_swfill: |
||
972 | ; *** CLIP AND COPY BLOCK TO OUTPUT BUFFER |
||
973 | pop eax ; skip MixPtr |
||
974 | pop esi ; <- mixbuffer |
||
975 | |||
976 | if AC97SND_ON |
||
977 | else |
||
978 | if INFO_API_ON |
||
979 | ; ebx : L channel RMS volume |
||
980 | ; ebp : R channel RMS volume |
||
981 | xor ebx,ebx |
||
982 | endif |
||
983 | endif ; AC97SND_ON = 0 |
||
984 | |||
985 | mov edi,esi |
||
986 | mov ecx,FSOUND_BlockSize*2 |
||
987 | align 4 |
||
988 | fill_loop_2: |
||
989 | lodsd |
||
990 | |||
991 | if AC97SND_ON |
||
992 | mov ebx,eax |
||
993 | cdq |
||
994 | xor eax,edx |
||
995 | sub eax,edx |
||
996 | mov ebp,255*volumerampsteps/2 |
||
997 | xor edx,edx |
||
998 | div ebp |
||
999 | cmp edx,255*volumerampsteps/4 |
||
1000 | sbb eax,-1 |
||
1001 | cmp eax,8000h |
||
1002 | sbb edx,edx |
||
1003 | not edx |
||
1004 | or eax,edx |
||
1005 | sar ebx,31 |
||
1006 | and eax,7FFFh |
||
1007 | xor eax,ebx |
||
1008 | sub eax,ebx |
||
1009 | else |
||
1010 | if INFO_API_ON |
||
1011 | push edi |
||
1012 | cdq |
||
1013 | mov edi,eax |
||
1014 | push esi |
||
1015 | xor eax,edx |
||
1016 | mov esi,255*volumerampsteps/2 |
||
1017 | sub eax,edx |
||
1018 | xor edx,edx |
||
1019 | div esi |
||
1020 | cmp edx,255*volumerampsteps/4 |
||
1021 | pop esi |
||
1022 | sbb eax,-1 |
||
1023 | cmp eax,8000h |
||
1024 | sbb edx,edx |
||
1025 | not edx |
||
1026 | or eax,edx |
||
1027 | sar edi,31 |
||
1028 | and eax,7FFFh |
||
1029 | if VOL_CONTROL_ON |
||
1030 | mul DWORD PTR [ufmod_vol] |
||
1031 | shr eax,15 |
||
1032 | endif |
||
1033 | ; sum. the L and R channel RMS volume |
||
1034 | ror ecx,1 |
||
1035 | sbb edx,edx |
||
1036 | and edx,eax |
||
1037 | add ebp,edx ; += |vol| |
||
1038 | rol ecx,1 |
||
1039 | sbb edx,edx |
||
1040 | not edx |
||
1041 | and edx,eax |
||
1042 | add ebx,edx ; += |vol| |
||
1043 | xor eax,edi |
||
1044 | sub eax,edi |
||
1045 | pop edi |
||
1046 | else |
||
1047 | mov ebx,eax |
||
1048 | cdq |
||
1049 | xor eax,edx |
||
1050 | sub eax,edx |
||
1051 | mov ebp,255*volumerampsteps/2 |
||
1052 | xor edx,edx |
||
1053 | div ebp |
||
1054 | cmp edx,255*volumerampsteps/4 |
||
1055 | sbb eax,-1 |
||
1056 | cmp eax,8000h |
||
1057 | sbb edx,edx |
||
1058 | not edx |
||
1059 | or eax,edx |
||
1060 | sar ebx,31 |
||
1061 | and eax,7FFFh |
||
1062 | if VOL_CONTROL_ON |
||
1063 | mul DWORD PTR [ufmod_vol] |
||
1064 | shr eax,15 |
||
1065 | endif |
||
1066 | xor eax,ebx |
||
1067 | sub eax,ebx |
||
1068 | endif |
||
1069 | endif ; AC97SND_ON = 0 |
||
1070 | |||
1071 | dec ecx |
||
1072 | stosw |
||
1073 | jnz fill_loop_2 |
||
1074 | |||
1075 | if AC97SND_ON |
||
1076 | else |
||
1077 | if INFO_API_ON |
||
1078 | shr ebp,FSOUND_Block ; R_vol / FSOUND_BlockSize |
||
1079 | shl ebx,16-FSOUND_Block ; (L_vol / FSOUND_BlockSize) << 16 |
||
1080 | mov bx,bp |
||
1081 | mov DWORD PTR [L_vol],ebx |
||
1082 | endif |
||
1083 | endif ; AC97SND_ON = 0 |
||
1084 | |||
1085 | ; *** DISPATCH DATA TO THE AC97 DRIVER |
||
1086 | push FSOUND_BlockSize*4 ; size |
||
1087 | push OFFSET MixBuf ; &src |
||
1088 | push DWORD PTR [hBuff] ; buffer |
||
1089 | mov edx,esp |
||
1090 | push ecx ; .out_size |
||
1091 | push ecx ; .output |
||
1092 | push 12 ; .inp_size |
||
1093 | push edx ; .input |
||
1094 | push 9 ; .code = SND_OUT |
||
1095 | push DWORD PTR [hSound] ; .handle |
||
1096 | lea eax,[ecx+68] |
||
1097 | lea ebx,[ecx+17] |
||
1098 | mov ecx,esp |
||
1099 | int 40h |
||
1100 | add esp,36 |
||
1101 | pop edi |
||
1102 | pop esi |
||
1103 | pop ebx |
||
1104 | ret><>->=>3) |