Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 1844 → Rev 1845

/programs/develop/libraries/ufmod/Fasm/frmwrk.asm
0,0 → 1,142
; FRMWRK.ASM
; ----------
; A set of common GUI code used in uFMOD examples for KolibriOS.
; Feel free to reuse it in your own projects if you like it ;)
 
; ---------------------------------------------------------------
; void _cdecl _MessageBox (szCap, lpString, cbString);
; void _cdecl _MessageBoxCB(szCap, lpString, cbString, cbProc);
; ---------------------------------------------------------------
 
; This is similar to a Win32 MessageBox. The box is centered
; on screen. It contains a single-line text message and an
; "OK" button. This function returns when user closes the
; box (via the X button or via the OK button). An optional
; callback subroutine may be specified to be called when no
; events are pending in the event queue.
 
; NOTE: Doesn't work if you already have defined a window
; in the current process! Doesn't modify the event mask. So,
; make sure keyboard events are enabled before calling this
; function. This function doesn't check the validity of the
; supplied parameters!
 
; Parameters:
; szCap - A pointer to the ASCIIz string containing the
; caption. A trailing zero char IS required.
; lpString - A pointer to an ASCII string containing a single
; line message to pop up in the box. No trailing
; zero char is required.
; cbString - number of characters in string.
; cbProc - Address of the callback subroutine. Can be NULL.
 
sOK db "OK"
if FRMWRK_CALLBACK_ON
_MessageBoxCB:
else
_MessageBox:
end if
push ebp
push esi
push edi
push ebx
xor ebp,ebp ; global 0
mov esi,[esp+28] ; cbString
mov edi,[esp+20] ; szCap
 
; Get screen metrics.
lea eax,[ebp+14]
int 40h
mov ecx,eax
movzx eax,ax
shr ecx,16 ; screen w
xchg eax,edx ; screen h
lea ebx,[esi*2+esi]
lea ebx,[ebx*2+28] ; w = string len * 6 + 28
sub ecx,ebx
shr ecx,1
shl ecx,16
or ebx,ecx
lea ecx,[ebp+52h] ; h = 52h
sub edx,ecx
shr edx,1
shl edx,16
or ecx,edx ; y = (screen h - window h) / 2
mov edx,ebx ; x = (screen w - window w) / 2
 
_MessageBoxCB_redraw:
; Start redraw.
push edx
lea eax,[ebp+12]
lea ebx,[ebp+1]
int 40h
 
; Define and draw window.
xor eax,eax
mov ebx,edx ; x, w (ECX: y, h)
mov edx,34C0C0C0h ; style and BG color
int 40h
 
; Define the OK button.
push esi
lea eax,[ebp+8]
sub ebx,28+0Ah
shr bx,1
shl ebx,16 ; x = (window w - button w) / 2
mov bx,18+0Ah ; w = 18 + 0Ah
mov ecx,001C0012h ; y = 1Ch, h = 12h
lea edx,[ebp+1] ; ID = close
mov esi,0C0C0C0h ; color
int 40h
 
; Draw the OK label.
lea eax,[ebp+4]
add ebx,90000h ; x = button x + 9
mov bx,22h ; y = 22h
xor ecx,ecx ; style, font and color
mov edx,sOK ; string
lea esi,[ebp+2] ; length
int 40h
pop esi
 
; Draw text string.
lea eax,[ebp+4]
mov ebx,000A000Ah ; x = 0Ah, y = 0Ah
xor ecx,ecx ; style, font and color
mov edx,[esp+28] ; lpString
int 40h
 
; End redraw.
lea eax,[ebp+12]
lea ebx,[ebp+2]
int 40h
 
if FRMWRK_CALLBACK_ON
_MessageBoxCB_eventloop:
mov edx,[esp+36] ; cbProc
test edx,edx
lea eax,[ebp+10]
jz _MessageBoxCB_peekevent
 
; Invoke the callback.
call edx
 
lea eax,[ebp+23]
lea ebx,[ebp+10] ; wait for at most 0.1 sec
_MessageBoxCB_peekevent:
int 40h
dec eax
js _MessageBoxCB_eventloop
else
lea eax,[ebp+10]
int 40h
dec eax
end if
pop edx
jz _MessageBoxCB_redraw
 
pop ebx
pop edi
pop esi
pop ebp
ret
/programs/develop/libraries/ufmod/Fasm/jmp2pat.asm
0,0 → 1,239
; JMP2PAT.ASM
; -----------
; Sometimes it makes sense merging various XM tracks
; sharing the same instruments in a single XM file.
; This example program uses such an XM file actually
; containing 3 tracks and the _uFMOD_Jump2Pattern
; function to play all 3 tracks in the same file.
 
; A precompiled version (not packed or whatever) is
; available in bin\
 
use32
org 0
db 'MENUET01'
dd 1
dd START ; Entry point
dd uFMOD_IMG_END ; End of code and initialized data
dd MEMORY_END ; End of uninitialized (BSS) data
dd STACK_B ; Bottom of the stack
dd 0 ; Args
dd 0 ; Reserved
 
; uFMOD setup:
UF_FREQ equ 48000 ; Set sampling rate to 48KHz (22050, 44100, 48000)
UF_RAMP equ STRONG ; Select STRONG interpolation (NONE, WEAK, STRONG)
UD_MODE equ UNSAFE ; Select UNSAFE mode (NORMAL, UNSAFE)
DEBUG equ 0 ; Skip debug-board messages
NOLINKER equ 1 ; Select "no linker" mode
 
; uFMOD constants:
XM_MEMORY = 1
XM_FILE = 2
XM_NOLOOP = 8
XM_SUSPENDED = 16
uFMOD_MIN_VOL = 0
uFMOD_MAX_VOL = 25
uFMOD_DEFAULT_VOL = 25
 
; BLITZXMK.XM tracked by Kim (aka norki):
; [00:07] - track #1
; [08:10] - track #2
; [11:13] - track #3
xm file '..\ufmodlib\media\BLITZXMK.XM'
xm_length = $ - xm
 
; Optimization:
; This header file is suitable for blitzxmk.xm track only!
; If you change the track, update the optimization header.
; (Use the standart eff.inc file for a general purpose player app.)
include '..\ufmodlib\media\blitz.eff.inc'
 
; Include the GUI framework.
FRMWRK_CALLBACK_ON equ 0 ; Disable callback
include 'frmwrk.asm'
 
; UI text messages.
vals dd 0,8,11 ; Preset pattern indexes
wnd_btns1 db "1 2 3 Pause "
wnd_btns2 db "1 2 3 Resume"
wnd_btns_l = $ - wnd_btns2
wnd_cap db "Jump2Pattern",0
err_txt db "Error"
err_txt_l = $ - err_txt
err_cap db ":-(",0
 
START:
; Start playback.
push XM_MEMORY
push xm_length
push xm
call _uFMOD_LoadSong
 
; Stack fixing is required here, but in this simple
; example leaving ESP as it is won't harm. In a real
; application you should uncomment the following line:
; add esp,12
 
test eax,eax
jz error
xor ebp,ebp ; global 0
mov [wnd_btns],wnd_btns1
 
; Switch keyboard mode to SCANCODE.
lea ebx,[ebp+1]
lea eax,[ebp+66]
mov ecx,ebx
int 40h
 
; Get screen metrics.
lea eax,[ebp+14]
int 40h
mov ecx,eax
movzx eax,ax
shr ecx,16 ; screen w
xchg eax,edx ; screen h
mov ebx,wnd_btns_l*6+42
sub ecx,ebx
shr ecx,1
shl ecx,16
or ebx,ecx
lea ecx,[ebp+40h] ; h = 40h
sub edx,ecx
shr edx,1
shl edx,16
or ecx,edx ; y = (screen h - window h) / 2
mov edx,ebx ; x = (screen w - window w) / 2
 
redraw:
; Start redraw.
push edx
lea eax,[ebp+12]
lea ebx,[ebp+1]
int 40h
 
; Define and draw window.
xor eax,eax
mov ebx,edx ; x, w (ECX: y, h)
mov edx,34C0C0C0h ; style and BG color
mov edi,wnd_cap
int 40h
 
; Define the 1 2 3 Pause/Resume buttons.
lea eax,[ebp+8]
mov ebx,0A0012h ; x = 0Ah, w = 12h
mov ecx,0A0012h ; y = 0Ah, h = 10h
lea edx,[ebp+10] ; ID = #10
mov esi,0C0C0C0h ; color
int 40h
mov ebx,280012h ; x = 28h, w = 12h
inc edx ; ID = #11
int 40h
mov ebx,460012h ; x = 46h, w = 12h
inc edx ; ID = #12
int 40h
mov ebx,640030h ; x = 64h, w = 30h
inc edx ; ID = #13
int 40h
 
; Draw the labels.
lea eax,[ebp+4]
mov ebx,120011h ; x = 12h, y = 11h
xor ecx,ecx ; style, font and color
mov edx,[wnd_btns] ; string
lea esi,[ebp+wnd_btns_l] ; length
int 40h
 
; End redraw.
lea eax,[ebp+12]
lea ebx,[ebp+2]
int 40h
 
eventloop:
; Update the PCM buffer.
call _uFMOD_WaveOut
 
lea eax,[ebp+23]
lea ebx,[ebp+10] ; wait for at most 0.1 sec
int 40h
dec eax
js eventloop ; 0 = idle
jz redraw ; 1 = redraw
 
dec eax ; 2 = keyboard event
jnz chk_eventbutton
 
; Get key scancode.
lea eax,[ebp+2]
int 40h
cmp ah,19h ; P
je do_PauseResume
cmp ah,13h ; R
je do_PauseResume
chk_kb123:
movzx eax,ah
sub eax,2
jmp do_Jump2Pat123
 
chk_eventbutton: ; 3 = button event
lea eax,[ebp+17]
int 40h
cmp ah,1 ; Close
je break_loop
cmp ah,13 ; Pause/Resume
jne chk_btn123
 
do_PauseResume:
cmp BYTE [paused],1
mov edx,_uFMOD_Resume
mov ebx,wnd_btns1
je do_Resume
mov edx,_uFMOD_Pause
mov ebx,wnd_btns2
do_Resume:
call edx
xor BYTE [paused],1
mov [wnd_btns],ebx
jmp redraw
 
chk_btn123: ; 1 2 3
movzx eax,ah
sub eax,10
 
do_Jump2Pat123:
cmp eax,3
jae eventloop
push DWORD [vals+eax*4]
call _uFMOD_Jump2Pattern
pop eax ; fix stack
jmp eventloop
break_loop:
 
; Stop playback.
call _uFMOD_StopSong
 
r: ; Exit.
xor eax,eax
dec eax
int 40h
 
error:
push err_txt_l ; cbString
push err_txt ; lpString
push err_cap ; szCap
call _MessageBox
; add esp,16
jmp r
 
; Include the whole uFMOD sources here. (Right after
; your main code to avoid naming conflicts, but still
; inside your code section.)
macro PUBLIC symbol {} ; hide all publics
include '..\ufmodlib\src\fasm.asm'
 
wnd_btns dd ?
paused db ?
align 4
rb 1020
STACK_B dd ? ; Stack bottom
MEMORY_END: ; End of uninitialized (BSS) data
/programs/develop/libraries/ufmod/Fasm/make.bat
0,0 → 1,20
@echo off
rem Make the uFMOD examples.
rem Compiler: FASM
rem Target OS: KolibriOS
 
rem FASM Path:
SET UF_FASM=\fasm
 
if not exist "%UF_FASM%\fasm.exe" goto Err1
"%UF_FASM%\fasm" mini.asm mini
"%UF_FASM%\fasm" jmp2pat.asm jmp2pat
goto TheEnd
 
:Err1
echo Couldn't find fasm.exe in %UF_FASM%\
 
:TheEnd
pause
@echo on
cls
/programs/develop/libraries/ufmod/Fasm/mini.asm
0,0 → 1,109
; MINI.ASM
; --------
; Minimalistic uFMOD usage example.
 
; Shows how to play an XM track in memory,
; including proper error handling.
 
; A precompiled version (not packed or whatever) is
; available in bin\
 
use32
org 0
db 'MENUET01'
dd 1
dd START ; Entry point
dd uFMOD_IMG_END ; End of code and initialized data
dd MEMORY_END ; End of uninitialized (BSS) data
dd STACK_B ; Bottom of the stack
dd 0 ; Args
dd 0 ; Reserved
 
; uFMOD setup:
UF_FREQ equ 48000 ; Set sampling rate to 48KHz (22050, 44100, 48000)
UF_RAMP equ STRONG ; Select STRONG interpolation (NONE, WEAK, STRONG)
UD_MODE equ UNSAFE ; Select UNSAFE mode (NORMAL, UNSAFE)
DEBUG equ 0 ; Skip debug-board messages
NOLINKER equ 1 ; Select "no linker" mode
 
; uFMOD constants:
XM_MEMORY = 1
XM_FILE = 2
XM_NOLOOP = 8
XM_SUSPENDED = 16
uFMOD_MIN_VOL = 0
uFMOD_MAX_VOL = 25
uFMOD_DEFAULT_VOL = 25
 
; The XM track.
xm file '..\ufmodlib\media\mini.xm'
xm_length = $ - xm
 
; Optimization:
; This header file is suitable for mini.xm track only!
; If you change the track, update the optimization header.
; (Use the standart eff.inc file for a general purpose player app.)
include '..\ufmodlib\media\mini.eff.inc'
 
; Include the GUI framework.
FRMWRK_CALLBACK_ON equ 1 ; Enable callback
include 'frmwrk.asm'
 
; UI text messages.
msg_txt db "uFMOD ruleZ!"
msg_txt_l = $ - msg_txt
msg_cap db "FASM",0
err_txt db "Error"
err_txt_l = $ - err_txt
err_cap db ":-(",0
 
START:
; Start playback.
push XM_MEMORY
push xm_length
push xm
call _uFMOD_LoadSong
 
; Stack fixing is required here, but in this simple
; example leaving ESP as it is won't harm. In a real
; application you should uncomment the following line:
; add esp,12
 
test eax,eax
jz error
 
; Wait for user input.
push _uFMOD_WaveOut ; cbProc <- continue fetching data!
push msg_txt_l ; cbString
push msg_txt ; lpString
push msg_cap ; szCap
call _MessageBoxCB
; add esp,16
 
; Stop playback.
call _uFMOD_StopSong
 
r: ; Exit.
xor eax,eax
dec eax
int 40h
 
error:
push 0 ; cbProc <- no callback
push err_txt_l ; cbString
push err_txt ; lpString
push err_cap ; szCap
call _MessageBoxCB
; add esp,16
jmp r
 
; Include the whole uFMOD sources here. (Right after
; your main code to avoid naming conflicts, but still
; inside your code section.)
macro PUBLIC symbol {} ; hide all publics
include '..\ufmodlib\src\fasm.asm'
 
align 4
rb 1020
STACK_B dd ? ; Stack bottom
MEMORY_END: ; End of uninitialized (BSS) data
/programs/develop/libraries/ufmod/Fasm
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/develop/libraries/ufmod/Masm32/make.bat
0,0 → 1,35
@echo off
rem Set compiler location:
SET MASM32=\masm32
SET UF_FASM=\fasm
 
if not exist "%MASM32%\bin\ml.exe" goto Err1
if not exist "%UF_FASM%\fasm.exe" goto Err2
"%MASM32%\bin\ml" /c /coff mini.asm
"%MASM32%\bin\link" /DRIVER /SUBSYSTEM:NATIVE /BASE:-0x10000 /ALIGN:0x10000 /MERGE:.data=.text -ignore:4078 mini.obj ufmod.obj
del mini.obj
echo virtual at 0 >tmp.asm
echo file 'mini.exe':3Ch,4 >>tmp.asm
echo load pehea dword from 0 >>tmp.asm
echo file 'mini.exe':pehea+0F8h,28h >>tmp.asm
echo load physofs dword from 4+14h >>tmp.asm
echo load mem dword from 4+8 >>tmp.asm
echo file 'mini.exe':physofs+16,4 >>tmp.asm
echo load sz dword from $-4 >>tmp.asm
echo end virtual >>tmp.asm
echo file 'mini.exe':physofs,sz >>tmp.asm
echo store dword mem at 14h >>tmp.asm
"%UF_FASM%\fasm" tmp.asm mini
del mini.exe
del tmp.asm
 
goto TheEnd
:Err1
echo Couldn't find ml.exe in %MASM32%\bin
goto TheEnd
:Err2
echo Couldn't find fasm.exe in %UF_FASM%\
 
:TheEnd
pause
cls
/programs/develop/libraries/ufmod/Masm32/mini.asm
0,0 → 1,266
; MINI.ASM
; --------
; Shows how to place data and code inside (!!!) the XM track.
 
.386
.model flat
 
include ufmod.inc ; uFMOD API
 
.CODE
 
PE_BASE db "MENUET01"
dd 1
dd OFFSET _START ; Entry point
dd OFFSET BSS_START ; End of code and initialized data
dd OFFSET BSS_END ; End of uninitialized (BSS) data
dd OFFSET STACK_B ; Bottom of the stack
dd 0 ; Args
dd 0 ; Reserved
 
err_txt db "Error"
err_txt_l EQU $ - err_txt
 
_START:
; Start playback.
push XM_MEMORY
push xm_length
push BYTE PTR xm
 
; Let's place the stream right inside the code section.
xm_length EQU 905
xm EQU $ - PE_BASE
xm_unused_000 LABEL BYTE
 
; *** The following 60 bytes are not used. So, we'll place
; *** some code here.
; (the actual size and location of such gaps may be
; found out using the Eff utility)
 
call uFMOD_LoadSong
xor ebp,ebp ; global 0
 
; Stack fixing is required here, but in this simple
; example leaving ESP as it is won't harm. In a real
; application you should uncomment the following line:
; add esp,12
 
test eax,eax
jz error
 
; Wait for user input.
push uFMOD_WaveOut ; cbProc <- continue fetching data!
push BYTE PTR msg_txt_l ; cbString
push OFFSET msg_txt ; lpString
push OFFSET msg_cap ; szCap
call MessageBoxCB
; add esp,16
 
; Stop playback.
call uFMOD_StopSong
 
r: ; Exit.
lea eax,[ebp-1]
int 40h
 
error:
push ebp ; cbProc <- no callback
push BYTE PTR err_txt_l ; cbString
push BYTE PTR (err_txt - PE_BASE) ; lpString
push OFFSET err_cap ; szCap
call MessageBoxCB
; add esp,16
jmp r
 
org xm_unused_000 + 60
db 034h,000h,000h,000h,020h,000h,000h,000h,002h,000h,00Dh,000h,001h,000h,001h,000h
db 00Ah,000h,091h,000h,000h,001h,002h,003h,004h,005h,006h,007h,000h,001h,002h,003h
db 004h,005h,006h,007h,008h,009h,00Ah,00Bh,008h,009h,00Ch,00Bh,008h,009h,00Ah,00Bh
db 008h,009h,00Ch,00Bh,009h,000h,000h,000h,000h,004h,000h,001h,000h,083h,016h,001h
db 080h,080h,02Eh,001h,000h,00Eh,060h,080h,03Ah,001h,000h,00Eh,062h,081h,061h,083h
db 035h,001h,009h,000h,000h,000h,000h,004h,000h,001h,000h,083h,016h,001h,080h,080h
db 02Eh,001h,000h,00Eh,060h,080h,035h,001h,000h,00Eh,062h,081h,061h,083h,038h,001h
db 009h,000h,000h,000h,000h,004h,000h,001h,000h,083h,016h,001h,080h,080h,02Eh,001h
db 000h,00Eh,060h,080h,038h,001h,000h,00Eh,062h,080h,083h,033h,001h,009h,000h,000h
db 000h,000h,006h,000h,001h,000h,083h,016h,001h,080h,080h,02Eh,001h,000h,00Eh,060h
db 080h,033h,001h,000h,00Eh,061h,081h,061h,083h,035h,001h,083h,00Dh,001h,083h,036h
db 001h,080h,083h,036h,001h,009h,000h,000h,000h,000h,004h,000h,001h,000h,083h,00Fh
db 001h,080h,080h,02Eh,001h,000h,00Eh,060h,080h,036h,001h,000h,00Eh,062h,081h,061h
db 083h,033h,001h,009h,000h,000h,000h,000h,006h,000h,001h,000h,083h,00Fh,001h,080h
db 080h,02Eh,001h,000h,00Eh,060h,080h,033h,001h,000h,00Eh,061h,081h,061h,083h,02Eh
db 001h,083h,012h,001h,083h,033h,001h,080h,083h,035h,001h,009h,000h,000h,000h,000h
db 006h,000h,001h,000h,083h,016h,001h,080h,080h,02Eh,001h,000h,00Eh,060h,080h,035h
db 001h,000h,00Eh,061h,081h,061h,083h,02Eh,001h,083h,00Dh,001h,083h,031h,001h,080h
db 083h,02Eh,001h,009h,000h,000h,000h,000h,008h,000h,001h,000h,083h,012h,001h,098h
db 00Ah,001h,083h,019h,001h,088h,00Ah,083h,01Eh,001h,081h,061h,083h,012h,001h,080h
db 083h,014h,001h,080h,083h,01Bh,001h,080h,083h,020h,001h,080h,083h,014h,001h,080h
db 009h,000h,000h,000h,000h,008h,000h,001h,000h,083h,012h,001h,081h,061h,083h,019h
db 001h,080h,083h,01Eh,001h,080h,083h,012h,001h,080h,083h,019h,001h,083h,031h,001h
db 083h,01Eh,001h,080h,083h,012h,001h,083h,031h,001h,083h,019h,001h,080h,009h,000h
db 000h,000h,000h,008h,000h,001h,000h,083h,014h,001h,083h,033h,001h,083h,01Bh,001h
db 080h,083h,020h,001h,083h,031h,001h,083h,014h,001h,080h,083h,01Bh,001h,083h,030h
db 001h,083h,020h,001h,080h,083h,014h,001h,083h,031h,001h,083h,01Bh,001h,080h,009h
db 000h,000h,000h,000h,008h,000h,001h,000h,083h,016h,001h,083h,030h,001h,083h,01Dh
db 001h,083h,031h,001h,083h,022h,001h,083h,035h,001h,083h,016h,001h,098h,00Ah,001h
db 083h,01Dh,001h,088h,00Ah,083h,022h,001h,081h,061h,083h,016h,001h,080h,083h,01Dh
db 001h,080h,009h,000h,000h,000h,000h,008h,000h,001h,000h,083h,016h,001h,080h,083h
db 01Dh,001h,080h,083h,022h,001h,080h,083h,016h,001h,080h,083h,018h,001h,080h,083h
db 01Dh,001h,080h,083h,011h,001h,080h,083h,018h,001h,080h,009h,000h,000h,000h,000h
db 008h,000h,001h,000h,083h,016h,001h,083h,030h,001h,083h,01Dh,001h,083h,031h,001h
db 083h,019h,001h,083h,02Eh,001h,083h,016h,001h,098h,00Ah,001h,083h,01Dh,001h,088h
db 00Ah,083h,019h,001h,081h,061h,083h,016h,001h,080h,083h,01Dh,001h,080h,0F1h,000h
db 000h,000h
xm_unused_001 LABEL BYTE
 
; The following 23 bytes are not used.
; So, let's place the MessageBox text and caption instead.
; UI text messages.
msg_txt db "uFMOD ruleZ!"
msg_txt_l equ $ - msg_txt
msg_cap db "MASM32",0
err_cap db ":-(",0
 
org xm_unused_001 + 23
db 001h,000h,012h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
db 000h,000h,000h,000h,000h,000h,000h,000h,040h,000h,008h,000h,02Ch,000h,00Eh,000h
db 008h,000h,018h,000h,016h,000h,020h,000h,008h,000h,02Dh,000h,00Dh,000h,032h,000h
db 004h,000h,03Ch,000h,007h,000h,044h,000h,004h,000h,05Ah,000h,000h,000h,064h,000h
db 000h,000h,06Eh,000h,000h,000h,000h,000h,020h,000h,00Ah,000h,028h,000h,01Eh,000h
db 018h,000h,032h,000h,020h,000h,03Ch,000h,020h,000h,046h,000h,020h,000h,050h,000h
db 020h,000h,05Ah,000h,020h,000h,064h,000h,020h,000h,06Eh,000h,020h,000h,078h,000h
db 020h,000h,082h,000h,020h,000h,009h,006h,001h,002h,004h,002h,003h,005h,001h,000h
db 000h,000h,000h,000h,080h,000h,00Ch,000h,000h,000h,000h,000h,000h,000h,00Ch,000h
db 000h,000h,040h,000h,001h,080h,0F9h,000h,0BFh,000h,0C3h,000h,00Ah,000h,057h,000h
db 06Eh,000h,023h,000h
 
; ----------------------------------------------------------
; void MessageBoxCB(szCap, lpString, cbString, cbProc);
; ----------------------------------------------------------
 
; This is similar to a Win32 MessageBox. The box is centered
; on screen. It contains a single-line text message and an
; "OK" button. This function returns when user closes the
; box (via the X button or via the OK button). An optional
; callback subroutine may be specified to be called when no
; events are pending in the event queue.
 
; NOTE: Doesn't work if you already have defined a window
; in the current process! Doesn't modify the event mask. So,
; make sure keyboard events are enabled before calling this
; function. This function doesn't check the validity of the
; supplied parameters!
 
; Parameters:
; szCap - A pointer to the ASCIIz string containing the
; caption. A trailing zero char IS required.
; lpString - A pointer to an ASCII string containing a single
; line message to pop up in the box. No trailing
; zero char is required.
; cbString - number of characters in string.
; cbProc - Address of the callback subroutine. Can be NULL.
 
sOK db "OK"
MessageBoxCB:
; EBP = 0
mov esi,[esp+12] ; cbString
mov edi,[esp+4] ; szCap
 
; Get screen metrics.
lea eax,[ebp+14]
int 40h
mov ecx,eax
movzx eax,ax
shr ecx,16 ; screen w
xchg eax,edx ; screen h
lea ebx,[esi*2+esi]
lea ebx,[ebx*2+28] ; w = string len * 6 + 28
sub ecx,ebx
shr ecx,1
shl ecx,16
or ebx,ecx
lea ecx,[ebp+52h] ; h = 52h
sub edx,ecx
shr edx,1
shl edx,16
or ecx,edx ; y = (screen h - window h) / 2
mov edx,ebx ; x = (screen w - window w) / 2
 
_MessageBoxCB_redraw:
; Start redraw.
push edx
lea eax,[ebp+12]
lea ebx,[ebp+1]
int 40h
 
; Define and draw window.
xor eax,eax
mov ebx,edx ; x, w (ECX: y, h)
mov edx,34C0C0C0h ; style and BG color
int 40h
 
; Define the OK button.
push esi
lea eax,[ebp+8]
sub ebx,28+0Ah
shr bx,1
shl ebx,16 ; x = (window w - button w) / 2
mov bx,18+0Ah ; w = 18 + 0Ah
mov ecx,001C0012h ; y = 1Ch, h = 12h
lea edx,[ebp+1] ; ID = close
mov esi,0C0C0C0h ; color
int 40h
 
; Draw the OK label.
lea eax,[ebp+4]
add ebx,90000h ; x = button x + 9
mov bx,22h ; y = 22h
xor ecx,ecx ; style, font and color
mov edx,OFFSET sOK ; string
lea esi,[ebp+2] ; length
int 40h
pop esi
 
; Draw text string.
lea eax,[ebp+4]
mov ebx,000A000Ah ; x = 0Ah, y = 0Ah
xor ecx,ecx ; style, font and color
mov edx,[esp+12] ; lpString
int 40h
 
; End redraw.
lea eax,[ebp+12]
lea ebx,[ebp+2]
int 40h
 
_MessageBoxCB_eventloop:
mov edx,[esp+20] ; cbProc
test edx,edx
lea eax,[ebp+10]
jz _MessageBoxCB_peekevent
 
; Invoke the callback.
call edx
 
lea eax,[ebp+23]
lea ebx,[ebp+10] ; wait for at most 0.1 sec
_MessageBoxCB_peekevent:
int 40h
dec eax
js _MessageBoxCB_eventloop
 
pop edx
jz _MessageBoxCB_redraw
ret
 
.DATA?
BSS_START LABEL BYTE
db 1020 dup (?)
STACK_B dd ? ; Stack bottom
BSS_END LABEL BYTE
 
END _START
/programs/develop/libraries/ufmod/Masm32/ufmod.inc
0,0 → 1,241
; uFMOD header file
; Target OS: KolibriOS
; Compiler: MASM32
 
; HANDLE uFMOD_LoadSong(
; void *lpXM,
; void *param,
; int fdwSong
; )
; ---
; Description:
; ---
; Loads the given XM song and starts playing it as soon as you
; call uFMOD_WaveOut for the first time. Playback won't begin
; if XM_SUSPENDED flag is specified. It will stop any currently
; playing song before loading the new one.
; ---
; Parameters:
; ---
; lpXM
; Specifies the song to load. If this parameter is 0, any
; currently playing song is stopped. In such a case, function
; does not return a meaningful value. fdwSong parameter
; determines whether this value is interpreted as a filename
; or as a pointer to an image of the song in memory.
; param
; If XM_MEMORY is specified, this parameter should be the size
; of the image of the song in memory.
; If XM_FILE is specified, this parameter is ignored.
; fdwSong
; Flags for playing the song. The following values are defined:
; XM_FILE lpXM points to filename. param is ignored.
; XM_MEMORY lpXM points to an image of a song in memory.
; param is the image size. Once, uFMOD_LoadSong
; returns, it's safe to free/discard the memory
; buffer.
; XM_NOLOOP An XM track plays repeatedly by default. Specify
; this flag to play it only once.
; XM_SUSPENDED The XM track is loaded in a suspended state,
; and will not play until the uFMOD_Resume function
; is called. This is useful for preloading a song
; or testing an XM track for validity.
; ---
; Return Values:
; ---
; On success, returns the handle of the Infinity Sound driver.
; Returns 0 on failure.
uFMOD_LoadSong PROTO C :DWORD,:DWORD,:DWORD
 
; int uFMOD_WaveOut(void)
; ---
; Description:
; ---
; Updates the internal playback buffer.
; ---
; Remarks:
; ---
; This function should be called from the same thread
; uFMOD_LoadSong was previously called. Playback doesn't actually
; begin when calling uFMOD_LoadSong, but when calling uFMOD_WaveOut
; after a successful uFMOD_LoadSong call. Afterwards, you should
; call uFMOD_WaveOut repeatedly at least once every 250 ms to
; prevent "buffer underruns".
; uFMOD_WaveOut is a non-blocking function. The accuracy of the
; InfoAPI functions (uFMOD_GetStats, uFMOD_GetRowOrder and
; uFMOD_GetTime) depends on the periodicity of this function being
; invoked.
; ---
; Return Values:
; ---
; Returns non zero on error.
uFMOD_WaveOut PROTO C
 
; void uFMOD_StopSong(void)
; ---
; Description:
; ---
; Stops the currently playing song, freeing the associated
; resources.
; ---
; Remarks:
; ---
; Does nothing if no song is playing at the time the call is made.
uFMOD_StopSong PROTO C
 
; void uFMOD_Jump2Pattern(
; unsigned int pat
; )
; ---
; Description:
; ---
; Jumps to the specified pattern index.
; ---
; Parameters:
; ---
; pat
; Next zero based pattern index.
; ---
; Remarks:
; ---
; uFMOD doesn't automatically perform Note Off effects before jumping
; to the target pattern. In other words, the original pattern will
; remain in the mixer until it fades out. You can use this feature to
; your advantage. If you don't like it, just insert leading Note Off
; commands in all patterns intended to be used as uFMOD_Jump2Pattern
; targets.
; if the pattern index lays outside of the bounds of the pattern order
; table, calling this function jumps to pattern 0, effectively
; rewinding playback.
uFMOD_Jump2Pattern PROTO C :DWORD
 
; void uFMOD_Pause(void)
; ---
; Description:
; ---
; Pauses the currently playing song, if any.
; ---
; Remarks:
; ---
; While paused you can still control the volume (uFMOD_SetVolume) and
; the pattern order (uFMOD_Jump2Pattern). The RMS volume coefficients
; (uFMOD_GetStats) will go down to 0 and the progress tracker
; (uFMOD_GetTime) will "freeze" while the song is paused.
; uFMOD_Pause doesn't perform the request immediately. Instead, it
; signals to pause when playback reaches next chunk of data.
; This way, uFMOD_Pause performs asynchronously and returns very fast.
; It is not cumulative. So, calling uFMOD_Pause many times in a row
; has the same effect as calling it once.
; You shouldn't stop calling uFMOD_WaveOut while the song is paused!
uFMOD_Pause PROTO C
 
; void uFMOD_Resume(void)
; ---
; Description:
; ---
; Resumes the currently paused song, if any.
; ---
; Remarks:
; ---
; uFMOD_Resume doesn't perform the request immediately. Instead, it
; signals to resume when uFMOD_WaveOut is called again. uFMOD_Resume
; is not cumulative. So, calling it many times in a row has the same
; effect as calling it once.
uFMOD_Resume PROTO C
 
; unsigned int uFMOD_GetStats(void)
; ---
; Description:
; ---
; Returns the current RMS volume coefficients in (L)eft and (R)ight
; channels.
; low-order word: RMS volume in R channel
; hi-order word: RMS volume in L channel
; Range from 0 (silence) to $7FFF (maximum) on each channel.
; ---
; Remarks:
; ---
; This function is useful for updating a VU meter. It's recommended
; to rescale the output to log10 (decibels or dB for short), because
; human ears track volume changes in a dB scale. You may call
; uFMOD_GetStats() as often as you like, but take in mind that uFMOD
; updates both channel RMS volumes at the same rate uFMOD_WaveOut
; function is called. In other words, you should call uFMOD_WaveOut
; more often to increase the accuracy of uFMOD_GetStats.
uFMOD_GetStats PROTO C
 
; unsigned int uFMOD_GetRowOrder(void)
; ---
; Description:
; ---
; Returns the currently playing row and order.
; low-order word: row
; hi-order word: order
; ---
; Remarks:
; ---
; This function is useful for synchronization. uFMOD updates both
; row and order values at the same rate uFMOD_WaveOut function is
; called. In other words, you should call uFMOD_WaveOut more often
; to increase the accuracy of uFMOD_GetRowOrder.
uFMOD_GetRowOrder PROTO C
 
; unsigned int uFMOD_GetTime(void)
; ---
; Description:
; ---
; Returns the time in milliseconds since the song was started.
; ---
; Remarks:
; ---
; This function is useful for synchronizing purposes. Multimedia
; applications can use uFMOD_GetTime to synchronize GFX to sound,
; for example. An XM player can use this function to update a progress
; meter.
uFMOD_GetTime PROTO C
 
; unsigned char* uFMOD_GetTitle(void)
; ---
; Description:
; ---
; Returns the current song's title.
; ---
; Remarks:
; ---
; Not every song has a title, so be prepared to get an empty string.
uFMOD_GetTitle PROTO C
 
; void uFMOD_SetVolume(
; unsigned int vol
; )
; ---
; Description:
; ---
; Sets the global volume. The volume scale is linear.
; ---
; Parameters:
; ---
; vol
; New volume. Range: from uFMOD_MIN_VOL (muting) to uFMOD_MAX_VOL
; (maximum volume). Any value above uFMOD_MAX_VOL maps to maximum
; volume.
; ---
; Remarks:
; ---
; uFMOD internally converts the given values to a logarithmic scale (dB).
; Maximum volume is set by default. The volume value is preserved across
; uFMOD_LoadSong calls. You can set the desired volume level before
; actually starting to play a song.
; You can use Infinity Sound API to control the L and R channels volumes
; separately. It also has a wider range than uFMOD_SetVolume, sometimes
; allowing to amplify the sound volume as well, as opposed to
; uFMOD_SetVolume only being able to attenuate it.
uFMOD_SetVolume PROTO C :DWORD
 
XM_MEMORY EQU 1
XM_FILE EQU 2
XM_NOLOOP EQU 8
XM_SUSPENDED EQU 16
uFMOD_MIN_VOL EQU 0
uFMOD_MAX_VOL EQU 25
uFMOD_DEFAULT_VOL EQU 25
/programs/develop/libraries/ufmod/Masm32/ufmod.obj
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/develop/libraries/ufmod/Masm32
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/develop/libraries/ufmod/Nasm/make.bat
0,0 → 1,18
@echo off
rem Compiler: NASM
rem Target OS: KolibriOS
 
rem NASM Path:
SET UF_NASM=\nasm
 
if not exist "%UF_NASM%\nasmw.exe" goto Err1
"%UF_NASM%\nasmw" -fbin -t -O5 -i..\ufmodlib\src\ mini.asm
goto TheEnd
 
:Err1
echo Couldn't find nasmw.exe in %UF_NASM%\
 
:TheEnd
pause
@echo on
cls
/programs/develop/libraries/ufmod/Nasm/mini.asm
0,0 → 1,225
; MINI.ASM
; --------
; Minimalistic uFMOD usage example.
 
; Shows how to play an XM track in memory,
; including proper error handling.
 
BITS 32
org 0
db "MENUET01"
dd 1
dd START ; Entry point
dd uFMOD_IMG_END ; End of code and initialized data
dd MEMORY_END ; End of uninitialized (BSS) data
dd STACK_B ; Bottom of the stack
dd 0 ; Args
dd 0 ; Reserved
 
; uFMOD setup:
%define f48000 ; Set sampling rate to 48KHz (22050, 44100, 48000)
%define STRONG ; Select STRONG interpolation (NONE, WEAK, STRONG)
%define UNSAFE ; Select UNSAFE mode (NORMAL, UNSAFE)
%define NODEBUG ; Skip debug-board messages
%define NOLINKER ; Select "no linker" mode
 
; uFMOD constants:
%define uFMOD_MIN_VOL 0
%define uFMOD_MAX_VOL 25
%define uFMOD_DEFAULT_VOL 25
 
; The XM track.
xm incbin "..\ufmodlib\media\mini.xm"
xm_length equ $ - xm
 
; Optimization:
; This header file is suitable for mini.xm track only!
; If you change the track, update the optimization header.
; (Use the standart eff.inc file for a general purpose player app.)
%include "..\ufmodlib\media\mini.eff.inc"
 
; UI text messages.
msg_txt db "uFMOD ruleZ!"
msg_txt_l equ $ - msg_txt
msg_cap db "NASM",0
err_txt db "Error"
err_txt_l equ $ - err_txt
err_cap db ":-(",0
 
START:
; Start playback.
push XM_MEMORY
push xm_length
push xm
call _uFMOD_LoadSong
 
; Stack fixing is required here, but in this simple
; example leaving ESP as it is won't harm. In a real
; application you should uncomment the following line:
; add esp,12
 
test eax,eax
jz error
 
; Wait for user input.
push _uFMOD_WaveOut ; cbProc <- continue fetching data!
push msg_txt_l ; cbString
push msg_txt ; lpString
push msg_cap ; szCap
call _MessageBoxCB
; add esp,16
 
; Stop playback.
call _uFMOD_StopSong
 
r: ; Exit.
xor eax,eax
dec eax
int 40h
 
error:
push 0 ; cbProc <- no callback
push err_txt_l ; cbString
push err_txt ; lpString
push err_cap ; szCap
call _MessageBoxCB
; add esp,16
jmp r
 
; ---------------------------------------------------------------
; void _cdecl _MessageBoxCB(szCap, lpString, cbString, cbProc);
; ---------------------------------------------------------------
 
; This is similar to a Win32 MessageBox. The box is centered
; on screen. It contains a single-line text message and an
; "OK" button. This function returns when user closes the
; box (via the X button or via the OK button). An optional
; callback subroutine may be specified to be called when no
; events are pending in the event queue.
 
; NOTE: Doesn't work if you already have defined a window
; in the current process! Doesn't modify the event mask. So,
; make sure keyboard events are enabled before calling this
; function. This function doesn't check the validity of the
; supplied parameters!
 
; Parameters:
; szCap - A pointer to the ASCIIz string containing the
; caption. A trailing zero char IS required.
; lpString - A pointer to an ASCII string containing a single
; line message to pop up in the box. No trailing
; zero char is required.
; cbString - number of characters in string.
; cbProc - Address of the callback subroutine. Can be NULL.
 
sOK db "OK"
_MessageBoxCB:
push ebp
push esi
push edi
push ebx
xor ebp,ebp ; global 0
mov esi,[esp+28] ; cbString
mov edi,[esp+20] ; szCap
 
; Get screen metrics.
lea eax,[ebp+14]
int 40h
mov ecx,eax
movzx eax,ax
shr ecx,16 ; screen w
xchg eax,edx ; screen h
lea ebx,[esi*2+esi]
lea ebx,[ebx*2+28] ; w = string len * 6 + 28
sub ecx,ebx
shr ecx,1
shl ecx,16
or ebx,ecx
lea ecx,[ebp+52h] ; h = 52h
sub edx,ecx
shr edx,1
shl edx,16
or ecx,edx ; y = (screen h - window h) / 2
mov edx,ebx ; x = (screen w - window w) / 2
 
_MessageBoxCB_redraw:
; Start redraw.
push edx
lea eax,[ebp+12]
lea ebx,[ebp+1]
int 40h
 
; Define and draw window.
xor eax,eax
mov ebx,edx ; x, w (ECX: y, h)
mov edx,34C0C0C0h ; style and BG color
int 40h
 
; Define the OK button.
push esi
lea eax,[ebp+8]
sub ebx,28+0Ah
shr bx,1
shl ebx,16 ; x = (window w - button w) / 2
mov bx,18+0Ah ; w = 18 + 0Ah
mov ecx,001C0012h ; y = 1Ch, h = 12h
lea edx,[ebp+1] ; ID = close
mov esi,0C0C0C0h ; color
int 40h
 
; Draw the OK label.
lea eax,[ebp+4]
add ebx,90000h ; x = button x + 9
mov bx,22h ; y = 22h
xor ecx,ecx ; style, font and color
mov edx,sOK ; string
lea esi,[ebp+2] ; length
int 40h
pop esi
 
; Draw text string.
lea eax,[ebp+4]
mov ebx,000A000Ah ; x = 0Ah, y = 0Ah
xor ecx,ecx ; style, font and color
mov edx,[esp+28] ; lpString
int 40h
 
; End redraw.
lea eax,[ebp+12]
lea ebx,[ebp+2]
int 40h
 
_MessageBoxCB_eventloop:
mov edx,[esp+36] ; cbProc
test edx,edx
lea eax,[ebp+10]
jz _MessageBoxCB_peekevent
 
; Invoke the callback.
call edx
 
lea eax,[ebp+23]
lea ebx,[ebp+10] ; wait for at most 0.1 sec
_MessageBoxCB_peekevent:
int 40h
dec eax
js _MessageBoxCB_eventloop
 
pop edx
jz _MessageBoxCB_redraw
 
pop ebx
pop edi
pop esi
pop ebp
ret
 
; Include the whole uFMOD sources here. (Right after
; your main code to avoid naming conflicts, but still
; inside your code section.)
%include "nasm.asm"
 
alignb 4
resb 1020
STACK_B resd 1 ; Stack bottom
MEMORY_END: ; End of uninitialized (BSS) data
/programs/develop/libraries/ufmod/Nasm
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/develop/libraries/ufmod/core.asm
0,0 → 1,3374
; CORE.ASM
; --------
; uFMOD public source code release. Provided as-is.
 
if VIBRATO_OR_TREMOLO
sin127 db 00h,0Ch,19h,25h,31h,3Ch,47h,51h,5Ah,62h,6Ah,70h,75h,7Ah,7Dh,7Eh
db 7Fh,7Eh,7Dh,7Ah,75h,70h,6Ah,62h,5Ah,51h,47h,3Ch,31h,25h,19h,0Ch
endif
if INSTRUMENTVIBRATO_ON
sin64 db 00h,02h,03h,05h,06h,08h,09h,0Bh,0Ch,0Eh,10h,11h,13h,14h,16h,17h
db 18h,1Ah,1Bh,1Dh,1Eh,20h,21h,22h,24h,25h,26h,27h,29h,2Ah,2Bh,2Ch
db 2Dh,2Eh,2Fh,30h,31h,32h,33h,34h,35h,36h,37h,38h,38h,39h,3Ah,3Bh
db 3Bh,3Ch,3Ch,3Dh,3Dh,3Eh,3Eh,3Eh,3Fh,3Fh,3Fh,40h,40h,40h,40h,40h
endif
if AMIGAPERIODS_ON
f0_0833 dd 8.3333336e-2
f13_375 dd 1.3375e1
endif
f0_0013 dd 1.302083375e-3
f8363_0 dd 8.3630004275e3
 
; Mixer ramping
Ramp:
; [arg0] - ptr. to end of buffer
; ESI - _mod+36
; EDI - length
; EDX - buffer
; LOOP THROUGH CHANNELS
mov ecx,[esi+FMUSIC_MODULE.Channels-36]
push ebx
push ebp
loop_ch:
push esi
mov esi,[ecx+FSOUND_CHANNEL.fsptr] ; load the correct SAMPLE pointer for this channel
test esi,esi ; if(!fsptr) skip this channel!
jz MixExit_1
push edx ; mix buffer
push edx ; cur. mix buffer pointer
mov ebx,[ecx+FSOUND_CHANNEL.mixpos]
; Set up a mix counter. See what will happen first, will the output buffer
; end be reached first? or will the end of the sample be reached first? whatever
; is smallest will be the mixcount.
push edi
CalculateLoopCount:
cmp BYTE PTR [ecx+FSOUND_CHANNEL.speeddir],0
mov edx,[esi+FSOUND_SAMPLE.loopstart]
mov eax,[ecx+FSOUND_CHANNEL.mixposlo]
jne samplesleftbackwards
; work out how many samples left from mixpos to loop end
add edx,[esi+FSOUND_SAMPLE.looplen]
sub edx,ebx
ja submixpos
mov edx,[esi+FSOUND_SAMPLE._length]
sub edx,ebx
submixpos:
; edx : samples left (loopstart+looplen-mixpos)
neg edx
neg eax
adc edx,ebx
samplesleftbackwards:
; work out how many samples left from mixpos to loop start
neg edx
add edx,ebx
js MixExit
; edx:eax now contains number of samples left to mix
mov ebp,[ecx+FSOUND_CHANNEL.speedlo]
shrd eax,edx,5
mov ebx,[ecx+FSOUND_CHANNEL.speedhi]
shr edx,5
shrd ebp,ebx,5
jnz speedok ; divide by 0 check
mov ebp,FREQ_40HZ_p
mov DWORD PTR [ecx+FSOUND_CHANNEL.speedlo],FREQ_40HZ_f
speedok:
div ebp
xor ebp,ebp
neg edx
adc eax,ebp
jz DoOutputbuffEnd
mov ebx,OFFSET uFMOD_fopen
cmp eax,edi
; set a flag to say mix will end when end of output buffer is reached
seta [ebx-22] ; mix_endflag
jae staywithoutputbuffend
xchg eax,edi
staywithoutputbuffend:
if RAMP_NONE
else
movzx eax,WORD PTR [ecx+FSOUND_CHANNEL.ramp_count]
; VOLUME RAMP SETUP
; Reasons to ramp
; 1 volume change
; 2 sample starts (just treat as volume change - 0 to volume)
; 3 sample ends (ramp last n number of samples from volume to 0)
; now if the volume has changed, make end condition equal a volume ramp
test eax,eax
endif
mov edx,[ecx+FSOUND_CHANNEL.leftvolume]
mov ebp,[ecx+FSOUND_CHANNEL.rightvolume]
if RAMP_NONE
mov [ecx+FSOUND_CHANNEL.ramp_leftvolume],ebp
mov [ecx+FSOUND_CHANNEL.ramp_rightvolume],edx
else
mov [ebx-16],edi ; mmf+4 <- remember mix count before modifying it
jz volumerampstart
; if it tries to continue an old ramp, but the target has changed,
; set up a new ramp
cmp dx,[ecx+FSOUND_CHANNEL.ramp_lefttarget]
jne volumerampstart
cmp bp,[ecx+FSOUND_CHANNEL.ramp_righttarget]
je volumerampclamp ; restore old ramp
volumerampstart:
; SETUP NEW RAMP
mov [ecx+FSOUND_CHANNEL.ramp_lefttarget],dx
shl edx,volumeramps_pow
sub edx,[ecx+FSOUND_CHANNEL.ramp_leftvolume]
xor eax,eax
sar edx,volumeramps_pow
mov DWORD PTR [ecx+FSOUND_CHANNEL.ramp_leftspeed],edx
jz novolumerampL
mov al,volumerampsteps
novolumerampL:
mov [ecx+FSOUND_CHANNEL.ramp_righttarget],bp
shl ebp,volumeramps_pow
sub ebp,[ecx+FSOUND_CHANNEL.ramp_rightvolume]
sar ebp,volumeramps_pow
mov DWORD PTR [ecx+FSOUND_CHANNEL.ramp_rightspeed],ebp
jz novolumerampR
mov al,volumerampsteps
novolumerampR:
test eax,eax
mov [ecx+FSOUND_CHANNEL.ramp_count],ax
jz volumerampend
volumerampclamp:
cmp edi,eax
jbe volumerampend ; dont clamp mixcount
mov edi,eax
volumerampend:
mov eax,[ecx+FSOUND_CHANNEL.ramp_leftspeed]
mov [ebx],eax ; ramp_leftspeed
mov eax,[ecx+FSOUND_CHANNEL.ramp_rightspeed]
mov [ebx+4],eax ; ramp_rightspeed
endif
mov [ebx-20],edi ; mmf
; SET UP ALL OF THE REGISTERS HERE FOR THE INNER LOOP
; edx : speed
; ebx : mixpos
; ebp : speed low
; esi : destination pointer
; edi : counter
mov ebx,[ecx+FSOUND_CHANNEL.mixpos]
lea ebx,[ebx*2+esi+FSOUND_SAMPLE.buff]
push esi
cmp BYTE PTR [ecx+FSOUND_CHANNEL.speeddir],0
mov esi,[esp+8] ; <- cur. mix buffer
mov edx,[ecx+FSOUND_CHANNEL.speedhi]
mov ebp,[ecx+FSOUND_CHANNEL.speedlo]
je MixLoop16
; neg edx:ebp
neg ebp
not edx
sbb edx,-1
align 4
MixLoop16:
push edi
push edx
movsx edi,WORD PTR [ebx]
movsx eax,WORD PTR [ebx+2]
mov edx,[ecx+FSOUND_CHANNEL.mixposlo]
sub eax,edi
shr edx,1 ; force unsigned
imul edx
shl edi,volumeramps_pow-1
shld edx,eax,volumeramps_pow
add edx,edi
if RAMP_NONE
mov eax,edx
imul edx,[ecx+FSOUND_CHANNEL.ramp_rightvolume]
add [esi],edx
imul DWORD PTR [ecx+FSOUND_CHANNEL.ramp_leftvolume]
add [esi+4],eax
else
xchg eax,edx
mov edi,eax
imul DWORD PTR [ecx+FSOUND_CHANNEL.ramp_rightvolume]
shrd eax,edx,volumeramps_pow-1
rol edx,1
and edx,1
add eax,edx
sar eax,1
add [esi],eax
xchg eax,edi
imul DWORD PTR [ecx+FSOUND_CHANNEL.ramp_leftvolume]
shrd eax,edx,volumeramps_pow-1
rol edx,1
and edx,1
add eax,edx
mov edi,[uFMOD_fread]
sar eax,1
add [esi+4],eax
mov edx,[uFMOD_fopen]
add [ecx+FSOUND_CHANNEL.ramp_rightvolume],edi ; + cur_ramp_rightspeed
add [ecx+FSOUND_CHANNEL.ramp_leftvolume],edx ; + cur_ramp_leftspeed
endif
pop edx
xor eax,eax
add [ecx+FSOUND_CHANNEL.mixposlo],ebp
pop edi
adc eax,edx
add esi,8
dec edi
lea ebx,[ebx+eax*2]
jnz MixLoop16
mov edi,[esp+20h] ; find out how many OUTPUT samples left to mix
mov [esp+8],esi ; update cur. mix buffer
sub edi,esi
shr edi,3 ; edi <- # of samples left
pop esi ; esi <- sample pointer
lea eax,[esi+FSOUND_SAMPLE.buff]
sub ebx,eax
shr ebx,1
mov [ecx+FSOUND_CHANNEL.mixpos],ebx
if RAMP_NONE
xor edx,edx
else
; DID A VOLUME RAMP JUST HAPPEN?
movzx edx,WORD PTR [ecx+FSOUND_CHANNEL.ramp_count]
test edx,edx
jz DoOutputbuffEnd
mov eax,[mmf]
cdq
sub [ecx+FSOUND_CHANNEL.ramp_count],ax
; if(!rampcount) a ramp has FINISHED, so finish the rest of the mix
jnz DoOutputbuffEnd
sub eax,[mmf+4]
; clear out the ramp speeds
mov [ecx+FSOUND_CHANNEL.ramp_leftspeed],edx
neg eax
mov [ecx+FSOUND_CHANNEL.ramp_rightspeed],edx
; is it 0 because ramp ended only? or both ended together?
; if sample ended together with ramp... problems... loop isn't handled
sbb edx,edx
; start again and continue rest of mix
test edi,edx
jnz CalculateLoopCount ; dont start again if nothing left
xor edx,edx
endif
DoOutputbuffEnd:
cmp [mix_endflag],dl
jne MixExit
movzx eax,BYTE PTR [esi+FSOUND_SAMPLE.loopmode]
; SWITCH ON LOOP MODE TYPE
dec eax ; check for normal loop (FSOUND_LOOP_NORMAL = 1)
jnz CheckBidiLoop
mov eax,[esi+FSOUND_SAMPLE.loopstart]
mov ebp,[esi+FSOUND_SAMPLE.looplen]
add eax,ebp
cmp ebx,eax
jbe rewind_ok
sub ebx,eax
xchg eax,ebx
div ebp
rewind_ok:
sub ebp,edx
sub ebx,ebp
jmp ChkLoop_OK
CheckBidiLoop:
dec eax ; FSOUND_LOOP_BIDI = 2
neg eax
adc edx,-1
and [ecx+FSOUND_CHANNEL.mixposlo],edx
and [ecx+FSOUND_CHANNEL.mixpos],edx
and [ecx+FSOUND_CHANNEL.fsptr],edx
jz MixExit
cmp [ecx+FSOUND_CHANNEL.speeddir],al ; FSOUND_MIXDIR_FORWARDS
je BidiForward
BidiBackwards:
mov eax,[esi+FSOUND_SAMPLE.loopstart]
neg ebp
dec eax
sub ebp,1
dec BYTE PTR [ecx+FSOUND_CHANNEL.speeddir] ; set FSOUND_MIXDIR_FORWARDS
sbb eax,ebx
mov ebx,[esi+FSOUND_SAMPLE.loopstart]
add ebx,eax
cmp eax,[esi+FSOUND_SAMPLE.looplen]
jl BidiFinish
BidiForward:
mov eax,[esi+FSOUND_SAMPLE.loopstart]
add eax,[esi+FSOUND_SAMPLE.looplen]
lea edx,[eax-1]
sbb eax,ebx
neg ebp
xchg eax,ebx
sub ebp,1
adc ebx,edx
inc BYTE PTR [ecx+FSOUND_CHANNEL.speeddir] ; go backwards
cmp ebx,[esi+FSOUND_SAMPLE.loopstart]
jl BidiBackwards
BidiFinish:
mov [ecx+FSOUND_CHANNEL.mixposlo],ebp
ChkLoop_OK:
test edi,edi
mov [ecx+FSOUND_CHANNEL.mixpos],ebx
jnz CalculateLoopCount
MixExit:
pop edi
pop eax ; discard cur. mix buffer pointer
pop edx
MixExit_1:
add ecx,FSOUND_CHANNEL_size
pop esi
cmp ecx,[esi+FMUSIC_MODULE.uFMOD_Ch-36]
jl loop_ch
pop ebp
pop ebx
ret
 
if AMIGAPERIODS_ON
AmigaPeriod:
; [sptr] in ECX
; note in EAX
; ESI != 0
mov edx,132
push edi
sub edx,eax
push esi
test eax,eax
push edx
movsx eax,BYTE PTR [ecx+FSOUND_SAMPLE.finetune]
mov edi,edx
jz _do_inc
cdq
shl edx,1
_do_inc:
inc edx
exp2:
fild DWORD PTR [esp]
fmul DWORD PTR [f0_0833] ; /12.0f
fld st0
frndint
fsub st1,st0
fxch st1
f2xm1
fld1
faddp st1,st0
fscale
fstp st1
fmul DWORD PTR [f13_375] ; *13.375f
fistp DWORD PTR [esp]
test esi,esi
pop ecx
jz exp2_end
sub edi,edx
push edi
xor esi,esi
mov edi,ecx
jmp exp2
exp2_end:
sub ecx,edi
test edx,edx
jns _do_imul
neg ecx
_do_imul:
imul ecx
and edx,127 ; +2^7-1
add eax,edx
sar eax,7
pop esi
add eax,edi
pop edi
ret
endif ; AMIGAPERIODS_ON
 
; DESCRIPTION: To carry out a vibrato at a certain depth and speed
if VIBRATO_OR_VOLSLIDE
if TREMOLO_ON
VibratoOrTremolo:
; cptr+2 = ESI
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2]
mov al,[esi+FMUSIC_CHANNEL.wavecontrol-2]
mov edx,ecx
add dl,[esi+FMUSIC_CHANNEL.vibspeed-2]
and edx,3Fh
and eax,3 ; switch(cptr->wavecontrol&3)
mov [esi+FMUSIC_CHANNEL.vibpos-2],dl
jz vibrato_c0
; C2 : Sqare wave
rol ecx,27
sbb edx,edx
xor edx,7Fh
or edx,1
dec eax
jnz vibrato_default
; C1 : Triangle wave (ramp down)
shr edx,24
ror ecx,23
add edx,ecx
neg edx
jmp vibrato_default
vibrato_c0:
; C0 : Sine wave
; delta = 127 sin(2 Pi x/64)
mov eax,ecx
and ecx,1Fh
shr eax,6
movzx edx,BYTE PTR [OFFSET sin127+ecx]
sbb eax,eax
xor edx,eax
sub edx,eax
vibrato_default:
movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.vibdepth-2]
imul edx ; delta *= cptr->vibdepth
sar eax,5
ret
endif
 
Vibrato:
; cptr+2 = ESI
if TREMOLO_ON
call VibratoOrTremolo
sar eax,1
else
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2]
mov al,[esi+FMUSIC_CHANNEL.wavecontrol-2]
mov edx,ecx
add dl,[esi+FMUSIC_CHANNEL.vibspeed-2]
and edx,3Fh
and eax,3 ; switch(cptr->wavecontrol&3)
mov [esi+FMUSIC_CHANNEL.vibpos-2],dl
jz vibrato_c0
; C2 : Sqare wave
rol ecx,27
sbb edx,edx
xor edx,7Fh
or edx,1
dec eax
jnz vibrato_default
; C1 : Triangle wave (ramp down)
shr edx,24
ror ecx,23
add edx,ecx
neg edx
jmp vibrato_default
vibrato_c0:
; C0 : Sine wave
; delta = 127 sin(2 Pi x/64)
mov eax,ecx
and ecx,1Fh
shr eax,6
movzx edx,BYTE PTR [OFFSET sin127+ecx]
sbb eax,eax
xor edx,eax
sub edx,eax
vibrato_default:
movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.vibdepth-2]
imul edx ; delta *= cptr->vibdepth
sar eax,6
endif
mov [esi+FMUSIC_CHANNEL.freqdelta-2],eax
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
ret
endif ; VIBRATO_OR_VOLSLIDE
 
if TREMOLO_ON
Tremolo:
; cptr+2 = ESI
if VIBRATO_OR_VOLSLIDE
push esi
add esi,FMUSIC_CHANNEL.tremolopos-FMUSIC_CHANNEL.vibpos
call VibratoOrTremolo
pop esi
else
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.tremolopos-2]
mov al,[esi+FMUSIC_CHANNEL.wavecontrol-2]
mov edx,ecx
add dl,[esi+FMUSIC_CHANNEL.tremolospeed-2]
and edx,3Fh
and eax,3 ; switch(cptr->wavecontrol&3)
mov [esi+FMUSIC_CHANNEL.tremolopos-2],dl
jz tremolo_c0
; C2 : Sqare wave
rol ecx,27
sbb edx,edx
xor edx,7Fh
or edx,1
dec eax
jnz tremolo_default
; C1 : Triangle wave (ramp down)
shr edx,24
ror ecx,23
add edx,ecx
neg edx
jmp tremolo_default
tremolo_c0:
; C0 : Sine wave
; delta = 127 sin(2 Pi x/64)
mov eax,ecx
and ecx,1Fh
shr eax,6
movzx edx,BYTE PTR [OFFSET sin127+ecx]
sbb eax,eax
xor edx,eax
sub edx,eax
tremolo_default:
movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.tremolodepth-2]
imul edx
sar eax,5
endif
mov [esi+FMUSIC_CHANNEL.voldelta-2],eax
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
ret
endif ; TREMOLO_ON
 
if PORTATO_OR_VOLSLIDE
Portamento:
; cptr+2 = ESI
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
mov eax,[esi+FMUSIC_CHANNEL.freq-2]
mov ecx,[esi+FMUSIC_CHANNEL.portatarget-2]
movzx edx,BYTE PTR [esi+FMUSIC_CHANNEL.portaspeed-2]
shl edx,2
sub eax,ecx
jg porta_do_sub
add eax,edx
jg _do_trim
jmp _no_trim
porta_do_sub:
sub eax,edx
jl _do_trim
_no_trim:
add ecx,eax
_do_trim:
mov [esi+FMUSIC_CHANNEL.freq-2],ecx
ret
endif ; PORTATO_OR_VOLSLIDE
 
if VOLUME_OR_PANENVELOPE
Envelope:
; cptr+2 = ESI
; env_iptr = ECX
; control = AL
env_type equ -4
envstopped equ -8
envdelta equ -12
env_value equ -16
valfrac equ -20
; env_tick = -24
sustain_l2 equ -26
sustain_l1 equ -27
sustain_loop equ -28
env_next equ -32
env_pos equ -36
push edi
push ebx
push ebp
mov ebp,esp
; Initialize local vars with PAN/VOL data
lea edi,[ecx+FMUSIC_INSTRUMENT.PANPoints]
xor ebx,ebx
if PANENVELOPE_ON
mov edx,DWORD PTR [edi+FMUSIC_INSTRUMENT.PANsustain-FMUSIC_INSTRUMENT.PANPoints]
mov [ebp+sustain_loop],edx ; load PANsustain, PANLoopStart and PANLoopEnd
mov cl,BYTE PTR [edi+FMUSIC_INSTRUMENT.PANtype-FMUSIC_INSTRUMENT.PANPoints]
movzx edx,BYTE PTR [edi+FMUSIC_INSTRUMENT.PANnumpoints-FMUSIC_INSTRUMENT.PANPoints]
endif
or [esi+FMUSIC_CHANNEL.notectrl-2],al ; cptr->notectrl |= control
if PANENVELOPE_ON
if VOLUMEENVELOPE_ON
cmp al,FMUSIC_VOLUME ; is it FMUSIC_VOLUME or FMUSIC_PAN?
endif
lea eax,[esi+FMUSIC_CHANNEL.envpanstopped-2]
endif
if VOLUMEENVELOPE_ON
if PANENVELOPE_ON
jnz pan_or_vol_ok
endif
; control = FMUSIC_VOLUME
add ebx,FMUSIC_CHANNEL.envvol-FMUSIC_CHANNEL.envpan
mov eax,DWORD PTR [edi+FMUSIC_INSTRUMENT.VOLsustain-FMUSIC_INSTRUMENT.PANPoints]
mov [ebp+sustain_loop],eax ; load VOLsustain, VOLLoopStart and VOLLoopEnd
mov cl,BYTE PTR [edi+FMUSIC_INSTRUMENT.VOLtype-FMUSIC_INSTRUMENT.PANPoints]
movzx edx,BYTE PTR [edi+FMUSIC_INSTRUMENT.VOLnumpoints-FMUSIC_INSTRUMENT.PANPoints]
lea eax,[esi+FMUSIC_CHANNEL.envvolstopped-2]
add edi,FMUSIC_INSTRUMENT.VOLPoints-FMUSIC_INSTRUMENT.PANPoints
pan_or_vol_ok:
endif
cmp BYTE PTR [eax],dh
jne goto_envelope_ret
push ecx ; -> env_type
push eax ; -> envstopped
lea ecx,[esi+ebx+FMUSIC_CHANNEL.envpanpos-2]
lea eax,[esi+ebx+FMUSIC_CHANNEL.envpandelta-2]
push eax ; -> envdelta
lea eax,[esi+ebx+FMUSIC_CHANNEL.envpan-2]
push eax ; -> env_value
lea eax,[esi+ebx+FMUSIC_CHANNEL.envpanfrac-2]
lea ebx,[esi+ebx+FMUSIC_CHANNEL.envpantick-2]
push eax ; -> valfrac
mov eax,[ecx]
cmp eax,edx ; if(*pos>=numpoints) envelop out of bound
push ebx ; -> env_tick
jge envelope_done
movzx eax,WORD PTR [edi+eax*4]
cmp [ebx],eax ; if(*tick == points[(*pos)<<1]) we are at the correct tick for the position
jnz add_envdelta
test BYTE PTR [ebp+env_type],FMUSIC_ENVELOPE_LOOP
jz loop_ok
movzx eax,BYTE PTR [ebp+sustain_l2]
cmp [ecx],eax
jnz loop_ok ; if((type&FMUSIC_ENVELOPE_LOOP) && *pos == loopend) handle loop
movzx eax,BYTE PTR [ebp+sustain_l1]
mov [ecx],eax ; *pos = loopstart
movzx eax,WORD PTR [edi+eax*4]
mov [ebx],eax ; *tick = points[(*pos)<<1]
loop_ok:
mov eax,[ecx]
mov [ebp+env_pos],eax
lea eax,[edi+eax*4]
dec edx
movzx ebx,WORD PTR [eax] ; get tick at this point
cmp [ecx],edx
mov edx,[eax+4]
mov edi,edx
movzx eax,WORD PTR [eax+2]
mov [ebp+env_next],edx ; get tick at next point
mov edx,[ebp+env_value]
mov [edx],eax ; *value = points[(currpos<<1)+1]
jne env_continue
; if it is at the last position, abort the envelope and continue last value
mov eax,[ebp+envstopped]
inc BYTE PTR [eax] ; *envstopped = TRUE
goto_envelope_ret:
jmp Envelope_Ret
env_continue:
shl eax,16
sub edi,eax
xchg eax,edi
xor ax,ax
; sustain
test BYTE PTR [ebp+env_type],FMUSIC_ENVELOPE_SUSTAIN
jz not_sustain
movzx edx,BYTE PTR [ebp+sustain_loop]
cmp [ebp+env_pos],edx
jne not_sustain
cmp BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2],al
je Envelope_Ret
not_sustain:
; interpolate 2 points to find delta step
inc DWORD PTR [ecx] ; (*pos)++
mov ecx,[ebp+valfrac]
mov [ecx],edi ; *valfrac = curr
mov edi,[ebp+envdelta]
movzx ecx,WORD PTR [ebp+env_next]
and DWORD PTR [edi],0 ; *envdelta = 0
sub ecx,ebx
jz envelope_done
cdq
idiv ecx
mov [edi],eax ; *envdelta = (next-curr)/(nexttick-currtick)
jmp envelope_done
add_envdelta:
; interpolate
mov eax,[ebp+envdelta]
mov ecx,[eax]
mov eax,[ebp+valfrac]
add [eax],ecx ; *valfrac += *envdelta
envelope_done:
pop edx ; <- env_tick
pop eax ; <- valfrac
pop ecx ; <- env_value
mov eax,[eax]
inc DWORD PTR [edx] ; (*tick)++
sar eax,16
mov [ecx],eax ; *value = *valfrac >> 16
Envelope_Ret:
leave
pop ebx
pop edi
ret
endif ; VOLUME_OR_PANENVELOPE
 
if VOLUMEBYTE_ON
VolByte:
; volume = EDX
; cptr+2 = ESI
sub edx,16
jb switch_volume
cmp edx,40h
ja switch_volume
; if(volume >= 0x10 && volume <= 0x50)
mov [esi+FMUSIC_CHANNEL.volume-2],edx
switch_volume:
mov eax,edx
and edx,0Fh
shr eax,4 ; switch(volume>>4)
sub eax,5
jz case_6
dec eax
jz case_7
dec eax
jz case_6
dec eax
jz case_7
sub eax,2
jbe case_AB
dec eax
jz case_C
dec eax
jz case_D
dec eax
jz case_E
dec eax
jnz vol_default
; case 0xF
test edx,edx
jz vol_z
shl dl,4
mov [esi+FMUSIC_CHANNEL.portaspeed-2],dl
vol_z:
and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER
if PORTATO_OR_VOLSLIDE
mov eax,[esi+FMUSIC_CHANNEL.period-2]
mov [esi+FMUSIC_CHANNEL.portatarget-2],eax ; cptr->portatarget = cptr->period
endif
vol_default:
ret
case_6: ; / case 8
neg edx
case_7: ; / case 9
add [esi+FMUSIC_CHANNEL.volume-2],edx
ret
case_AB:
mov [esi+eax+FMUSIC_CHANNEL.vibspeed-1],dl
ret
case_C:
shl edx,4
mov [esi+FMUSIC_CHANNEL.pan-2],edx
xchg eax,edx
case_D:
neg edx
case_E:
add [esi+FMUSIC_CHANNEL.pan-2],edx
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
ret
endif ; VOLUMEBYTE_ON
 
if TREMOR_ON
Tremor:
; cptr+2 = ESI
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
mov dx,WORD PTR [esi+FMUSIC_CHANNEL.tremorpos-2]
cmp dl,dh
jbe inc_pos
mov ecx,[esi+FMUSIC_CHANNEL.volume-2]
neg ecx
mov [esi+FMUSIC_CHANNEL.voldelta-2],ecx
inc_pos:
add dh,[esi+FMUSIC_CHANNEL.tremoroff-2]
cmp dl,dh
jbe Tremor_Ret
mov dl,-1
Tremor_Ret:
inc dl
mov [esi+FMUSIC_CHANNEL.tremorpos-2],dl
ret
endif ; TREMOR_ON
 
SetBPM:
; bpm = ECX
test ecx,ecx
mov eax,FSOUND_MixRate*5/2
jz SetBPM_Ret
cdq
div ecx
SetBPM_Ret:
mov DWORD PTR [_mod+FMUSIC_MODULE.mixer_samplespertick],eax
ret
 
; Loads an XM stream into memory. Returns non-zero on success.
LoadXM:
loadxm_count1 equ -4
loadxm_numpat equ -8
loadxm_fnumpat equ -12
loadxm_count2 equ -16
loadxm_skip equ -20
loadxm_s0loopmode equ -38
loadxm_s0bytes equ -42
loadxm_s0looplen equ -48
loadxm_s0loopstart equ -52
loadxm_sample_2 equ -56
loadxm_pat_size equ -63
loadxm_pat equ -68
loadxm_tmp29 equ -91
loadxm_tmp27 equ -93
loadxm_tmp equ -120
mov eax,OFFSET _mod
push ebp
mov esi,eax
mov ebp,esp
mov edx,FMUSIC_MODULE_size
; buf : EAX
; size : EDX
call [uFMOD_fread]
xor ecx,ecx
mov eax,[esi+FMUSIC_MODULE.mixer_samplespertick]
push ecx ; -> loadxm_count1
; GOTO PATTERN DATA
lea eax,[eax+60]
; pos : EAX
; org : ECX
; !org : Z
call uFMOD_lseek
add esp,-116
push ebx
; SAVE TRACK TITLE
if INFO_API_ON
push 20 ; a title has max. 20 chars
lea edx,[esi+17]
mov edi,OFFSET szTtl
if UCODE
xor eax,eax
endif
pop ecx
loadxm_ttl:
mov al,[edx]
inc edx
cmp al,20h ; copy only printable chars
jl loadxm_ttl_ok
if UCODE
stosw
else
stosb
endif
loadxm_ttl_ok:
dec ecx
jnz loadxm_ttl
xchg eax,ecx
stosd
else
xor eax,eax
endif
; COUNT NUM. OF PATTERNS
movzx ecx,WORD PTR [esi+FMUSIC_MODULE.numorders]
movzx ebx,WORD PTR [esi+FMUSIC_MODULE.numpatternsmem]
neg ebx
mov edi,esi
sbb edx,edx
and ecx,edx
neg ebx
dec ecx
movzx edx,dl
mov [ebp+loadxm_fnumpat],ebx
if CHK4VALIDITY
cmp ecx,edx
ja loadxm_R
endif
loadxm_for_pats:
mov dl,[esi+FMUSIC_MODULE.orderlist]
cmp edx,eax
jbe loadxm_for_continue
xchg eax,edx
loadxm_for_continue:
inc esi
dec ecx
jns loadxm_for_pats
mov [ebp+loadxm_numpat],eax
inc eax
mov esi,edi
; ALLOCATE THE PATTERN ARRAY (whatever is bigger: fnumpat or numpat) & CHANNEL POOL
cmp eax,ebx
jae loadxm_pats_ok2
xchg eax,ebx
loadxm_pats_ok2:
movzx ecx,BYTE PTR [esi+FMUSIC_MODULE.numinsts]
imul ecx,FMUSIC_INSTRUMENT_size
mov [esi+FMUSIC_MODULE.numpatternsmem],ax
lea edi,[ecx+eax*FMUSIC_PATTERN_size]
mov eax,edi
sub edi,ecx
movzx ecx,BYTE PTR [esi+FMUSIC_MODULE.numchannels_xm]
if CHK4VALIDITY
cmp ecx,64
jle loadxm_numchan_ok
xor ecx,ecx
loadxm_numchan_ok:
endif
mov [esi+FMUSIC_MODULE.numchannels],ecx
mov ebx,ecx
shl ebx,7 ; *FSOUND_CHANNEL_size*2 == *FMUSIC_CHANNEL_size
if CHK4VALIDITY
jz loadxm_R
endif
mov [ebp+loadxm_count2],ecx
lea eax,[eax+ebx*2]
; numbytes : EAX
call alloc
lea edx,[eax+ebx]
mov [esi+FMUSIC_MODULE.Channels],eax
mov [esi+FMUSIC_MODULE.uFMOD_Ch],edx
mov ebx,FMUSIC_CHANNEL_size ; = FSOUND_CHANNEL_size*2
loop_2:
mov BYTE PTR [eax+FSOUND_CHANNEL.speedhi],1
mov [edx+FMUSIC_CHANNEL.cptr],eax
add eax,ebx
add edx,ebx
dec DWORD PTR [ebp+loadxm_count2]
jnz loop_2
mov [esi],edx ; FMUSIC_MODULE.pattern
add edi,edx
movzx ecx,WORD PTR [esi+FMUSIC_MODULE.defaultbpm]
mov [esi+FMUSIC_MODULE.instrument],edi
mov edi,edx
; bpm : ECX
call SetBPM
push 64
movzx ecx,WORD PTR [esi+FMUSIC_MODULE.defaultspeed]
pop DWORD PTR [esi+FMUSIC_MODULE.globalvolume]
mov [esi+FMUSIC_MODULE.speed],ecx
; ALLOCATE INSTRUMENT ARRAY
mov eax,[ebp+loadxm_fnumpat]
; READ & UNPACK PATTERNS
loadxm_load_pats:
push 9
lea eax,[ebp+loadxm_pat]
pop edx
; buf : EAX
; size : EDX
call [uFMOD_fread]
; ALLOCATE PATTERN BUFFER
mov eax,[ebp+loadxm_pat_size] ; length of pattern & packed pattern size
mov ecx,[esi+FMUSIC_MODULE.numchannels]
cmp eax,10000h
mov [edi],eax
movzx eax,ax
jb loadxm_ldpats_continue ; skip an empty pattern
if CHK4VALIDITY
cmp eax,257
sbb edx,edx
and eax,edx
jz loadxm_R
endif
mul ecx
mov [ebp+loadxm_count2],eax
lea eax,[eax+eax*4] ; x SIZE FMUSIC_NOTE
; numbytes : EAX
call alloc
mov [edi+FMUSIC_PATTERN.data],eax
xchg eax,ebx
loadxm_for_rowsxchan:
push esi
mov esi,[uFMOD_fread]
xor edx,edx
lea eax,[ebp+loadxm_skip]
inc edx
; buf : EAX
; size : EDX
call esi ; uFMOD_fread
movzx edx,BYTE PTR [ebp+loadxm_skip]
test dl,80h
jz loadxm_noskip
and edx,1
jz loadxm_nonote
mov eax,ebx ; &nptr->note
; buf : EAX
; size : EDX
call esi ; uFMOD_fread
loadxm_nonote:
test BYTE PTR [ebp+loadxm_skip],2
jz loadxm_nonumber
xor edx,edx
lea eax,[ebx+1] ; &nptr->number
inc edx
; buf : EAX
; size : EDX
call esi ; uFMOD_fread
loadxm_nonumber:
test BYTE PTR [ebp+loadxm_skip],4
jz loadxm_novolume
xor edx,edx
lea eax,[ebx+2] ; &nptr->volume
inc edx
; buf : EAX
; size : EDX
call esi ; uFMOD_fread
loadxm_novolume:
test BYTE PTR [ebp+loadxm_skip],8
jz loadxm_noeffect
xor edx,edx
lea eax,[ebx+3] ; &nptr->effect
inc edx
; buf : EAX
; size : EDX
call esi ; uFMOD_fread
loadxm_noeffect:
test BYTE PTR [ebp+loadxm_skip],16
jz loadxm_isnote97
xor edx,edx
lea eax,[ebx+4] ; &nptr->eparam
inc edx
jmp loadxm_skip_read
loadxm_noskip:
test edx,edx
jz loadxm_skip_z
mov [ebx],dl
loadxm_skip_z:
lea eax,[ebx+1]
mov dl,4
loadxm_skip_read:
; buf : EAX
; size : EDX
call esi ; uFMOD_fread
loadxm_isnote97:
pop esi
inc ebx
mov dl,BYTE PTR [esi+FMUSIC_MODULE.numinsts]
cmp [ebx],dl
jbe loadxm_number_ok
mov BYTE PTR [ebx],0
loadxm_number_ok:
add ebx,4
dec DWORD PTR [ebp+loadxm_count2]
jnz loadxm_for_rowsxchan
loadxm_ldpats_continue:
inc DWORD PTR [ebp+loadxm_count1]
mov eax,[ebp+loadxm_fnumpat]
add edi,8
cmp eax,[ebp+loadxm_count1]
ja loadxm_load_pats
; allocate and clean out any extra patterns
mov ecx,[ebp+loadxm_numpat]
cmp ecx,eax
jb loadxm_extrapats_ok
mov ebx,[esi] ; FMUSIC_MODULE.pattern
mov eax,[esi+FMUSIC_MODULE.numchannels]
push esi
lea esi,[ebx+ecx*FMUSIC_PATTERN_size]
lea edi,[eax+eax*4]
shl edi,6 ; numchannels*64*SIZE FMUSIC_NOTE
loadxm_for_extrapats:
dec DWORD PTR [ebp+loadxm_numpat]
mov eax,edi
mov BYTE PTR [esi],64 ; pptr->rows = 64
; Allocate memory for pattern buffer
; numbytes : EAX
call alloc
mov [esi+FMUSIC_PATTERN.data],eax
sub esi,FMUSIC_PATTERN_size
mov eax,[ebp+loadxm_fnumpat]
cmp [ebp+loadxm_numpat],eax
jae loadxm_for_extrapats
pop esi
loadxm_extrapats_ok:
xor eax,eax
mov [esi+FMUSIC_MODULE.mixer_samplesleft],eax
mov [esi+FMUSIC_MODULE.tick],eax
if PATTERNDELAY_ON
lea edi,[esi+FMUSIC_MODULE.patterndelay]
stosd
else
lea edi,[esi+FMUSIC_MODULE.nextorder]
endif
stosd
stosd
; Load instrument information
mov al,BYTE PTR [esi+FMUSIC_MODULE.numinsts]
test al,al
jz loadxm_ret1
mov [ebp+loadxm_count1],al
mov ebx,[esi+FMUSIC_MODULE.instrument]
loadxm_for_instrs:
push 33
lea eax,[ebp+loadxm_tmp]
pop edx
; buf : EAX
; size : EDX
call [uFMOD_fread] ; instrument size & name
mov esi,[ebp+loadxm_tmp] ; firstsampleoffset = tmp[0]
mov dl,[ebp+loadxm_tmp27]
sub esi,33
test dl,dl
jz loadxm_inst_ok
if CHK4VALIDITY
xor eax,eax
cmp DWORD PTR [ebp+loadxm_tmp29],41
sbb ecx,ecx
not ecx
or edx,ecx
cmp dl,16
ja loadxm_R ; if(numsamples > 16) goto error
endif
mov edx,208
lea eax,[ebx+FMUSIC_INSTRUMENT.keymap]
sub esi,edx
; buf : EAX
; size : EDX
call [uFMOD_fread]
loadxm_inst_ok:
xor ecx,ecx
xchg eax,esi
inc ecx ; SEEK_CUR
; pos : EAX
; org : ECX
; !org : Z
call uFMOD_lseek
lea edx,[ebx+FMUSIC_INSTRUMENT.VOLfade]
xor eax,eax
mov cx,[edx]
shl ecx,1
cmp BYTE PTR [edx+FMUSIC_INSTRUMENT.VOLnumpoints-FMUSIC_INSTRUMENT.VOLfade],2
mov [edx],cx ; iptr->VOLfade *= 2
jnb ladxm_voltype_ok
mov BYTE PTR [edx+FMUSIC_INSTRUMENT.VOLtype-FMUSIC_INSTRUMENT.VOLfade],al
ladxm_voltype_ok:
cmp BYTE PTR [edx+FMUSIC_INSTRUMENT.PANnumpoints-FMUSIC_INSTRUMENT.VOLfade],2
jnb loadxm_PANtype_ok
mov BYTE PTR [edx+FMUSIC_INSTRUMENT.PANtype-FMUSIC_INSTRUMENT.VOLfade],al
loadxm_PANtype_ok:
cmp [ebp+loadxm_tmp27],al
je loadx_for_loadsamp_end
mov [ebp+loadxm_numpat],eax
mov [ebp+loadxm_fnumpat],ebx ; FMUSIC_INSTRUMENT.sample
loadxm_for_samp:
lea eax,[ebp+loadxm_sample_2]
mov edx,[ebp+loadxm_tmp29]
; buf : EAX
; size : EDX
call [uFMOD_fread]
mov esi,[ebp+loadxm_s0loopstart]
mov edi,[ebp+loadxm_s0looplen]
mov al,[ebp+loadxm_s0bytes]
mov ecx,eax
shr eax,4 ; sample[0].bytes >>= 4
and al,1 ; [b 4] : 8/16 bit sample data
mov [ebp+loadxm_s0bytes],al
jz loadxm_s0bytes_ok
shr DWORD PTR [ebp+loadxm_sample_2],1
shr esi,1
shr edi,1
loadxm_s0bytes_ok:
mov eax,[ebp+loadxm_sample_2]
cmp eax,esi
jg loadxm_loopstart_ok
mov esi,eax
loadxm_loopstart_ok:
lea edx,[esi+edi]
sub edx,eax
js loadxm_looplen_ok
sub edi,edx
loadxm_looplen_ok:
and ecx,3 ; [b 0-1] : loop type
jz loadxm_reset_sample
test edi,edi
jnz loadxm_s0loop_ok
loadxm_reset_sample:
xor esi,esi
xor ecx,ecx
mov edi,eax
loadxm_s0loop_ok:
mov [ebp+loadxm_s0loopstart],esi
mov [ebp+loadxm_s0looplen],edi
mov [ebp+loadxm_s0loopmode],cl
lea eax,[eax+eax+26] ; sample[0].length*2+SIZE FSOUND_SAMPLE+4
; numbytes : EAX
call alloc
mov ecx,[ebp+loadxm_fnumpat]
mov [ecx],eax
; memcpy(iptr->sample[count2],sample,sizeof(FSOUND_SAMPLE))
inc DWORD PTR [ebp+loadxm_numpat]
add DWORD PTR [ebp+loadxm_fnumpat],4
push 5
xchg eax,edi
mov eax,[ebp+loadxm_numpat]
pop ecx
cmp al,[ebp+loadxm_tmp27]
lea esi,[ebp+loadxm_sample_2]
rep movsd
jb loadxm_for_samp
; Load sample data
mov [ebp+loadxm_numpat],ecx
; ebx <- FMUSIC_INSTRUMENT.sample
loadx_for_loadsamp:
mov esi,[ebx+ecx*4]
xor eax,eax
mov edx,[esi]
mov ch,[esi+FSOUND_SAMPLE.Resved]
mov cl,[esi+FSOUND_SAMPLE.bytes]
if CHK4VALIDITY
test edx,0FFC00000h
jnz loadxm_R
endif
add esi,FSOUND_SAMPLE.buff
if ADPCM_ON
cmp ch,0ADh ; ModPlug 4-bit ADPCM
jne loadxm_regular_samp
inc edx
mov edi,esi
sar edx,1
push ebx
push edx
lea edx,[edx+edx*2]
add edi,edx ; ptr = buff+compressed_length*3
; Read in the compression table
lea edx,[eax+16] ; edx = 16
lea eax,[ebp+loadxm_sample_2]
mov ebx,eax
; buf : EAX
; size : EDX
call [uFMOD_fread]
; Read in the sample data
pop edx
mov eax,edi
; buf : EAX
; size : EDX
call [uFMOD_fread]
; Decompress sample data
mov edx,esi
xor ecx,ecx ; delta
loadxm_unpack_loop:
cmp edx,edi
jge loadxm_unpack_ok
mov al,[edi]
mov ah,al
and al,0Fh
xlatb
shr ah,4
inc edi
add ch,al
mov al,ah
xlatb
add al,ch
shl eax,24
or ecx,eax
mov [edx],ecx
shr ecx,16 ; ch <- delta
add edx,4
jmp loadxm_unpack_loop
loadxm_unpack_ok:
pop ebx
jmp loadxm_chk_loop_bidi
loadxm_regular_samp:
endif
shl edx,cl ; sptr->length << sptr->bytes
mov eax,esi
; buf : EAX
; size : EDX
call [uFMOD_fread]
mov ecx,DWORD PTR [esi+FSOUND_SAMPLE._length-FSOUND_SAMPLE.buff]
lea edi,[ecx+esi] ; buff = sptr->buff+sptr->length
lea eax,[edi+ecx] ; ptr = buff+sptr->length
xor edx,edx
cmp BYTE PTR [esi+FSOUND_SAMPLE.bytes-FSOUND_SAMPLE.buff],dl
jne loadxm_16bit_ok
; Promote to 16 bits
loadxm_to16bits:
dec eax
dec edi
dec eax
mov dh,[edi]
cmp eax,edi
mov [eax],dx
ja loadxm_to16bits
xor edx,edx
loadxm_16bit_ok:
mov eax,esi
; Do delta conversion
loadxm_do_delta_conv:
add dx,[eax]
mov [eax],dx
dec ecx
lea eax,[eax+2]
jg loadxm_do_delta_conv
js loadxm_loops_ok
loadxm_chk_loop_bidi:
mov eax,DWORD PTR [esi+FSOUND_SAMPLE.looplen-FSOUND_SAMPLE.buff]
mov ecx,DWORD PTR [esi+FSOUND_SAMPLE.loopstart-FSOUND_SAMPLE.buff]
add eax,ecx
cmp BYTE PTR [esi+FSOUND_SAMPLE.loopmode-FSOUND_SAMPLE.buff],2 ; LOOP_BIDI
lea eax,[esi+eax*2]
jnz loadxm_chk_loop_normal
mov cx,[eax-2]
jmp loadxm_fix_loop
loadxm_chk_loop_normal:
cmp BYTE PTR [esi+FSOUND_SAMPLE.loopmode-FSOUND_SAMPLE.buff],1 ; LOOP_NORMAL
jnz loadxm_loops_ok
mov cx,WORD PTR [esi+ecx*2]
loadxm_fix_loop:
mov [eax],cx
loadxm_loops_ok:
inc DWORD PTR [ebp+loadxm_numpat]
mov ecx,[ebp+loadxm_numpat]
cmp cl,[ebp+loadxm_tmp27]
jb loadx_for_loadsamp
loadx_for_loadsamp_end:
add ebx,FMUSIC_INSTRUMENT_size
dec BYTE PTR [ebp+loadxm_count1]
jnz loadxm_for_instrs
loadxm_ret1:
inc eax
loadxm_R:
pop ebx
donote_R:
leave
ret
 
DoNote:
; mod+36 = ESI
var_mod equ -4
donote_sptr equ -8
donote_jumpflag equ -10
donote_porta equ -12
donote_oldpan equ -16
donote_currtick equ -20
donote_oldfreq equ -24
donote_iptr equ -28
; Point our note pointer to the correct pattern buffer, and to the
; correct offset in this buffer indicated by row and number of channels
mov eax,[esi+FMUSIC_MODULE.order-36]
push ebp
movzx ebx,BYTE PTR [eax+esi+FMUSIC_MODULE.orderlist-36]
mov ebp,esp
mov eax,[esi+FMUSIC_MODULE.row-36]
lea ebx,[ecx+ebx*FMUSIC_PATTERN_size]
mov ecx,[esi+FMUSIC_MODULE.numchannels-36]
if PATTERNBREAK_ON
if PATTERNJUMP_ON
mov BYTE PTR [ebp+donote_jumpflag],ch
endif
endif
mul ecx
lea edi,[eax+eax*4] ; x SIZE FMUSIC_NOTE
push esi
add edi,[ebx+FMUSIC_PATTERN.data] ; mod->pattern[mod->orderlist[mod->order]].data+(mod->row*mod->numchannels)
sub esp,24
; Loop through each channel in the row
shl ecx,7 ; x FMUSIC_CHANNEL_size
jz donote_R
push esi
mov esi,[esi+FMUSIC_MODULE.uFMOD_Ch-36]
push ebx
inc esi
inc esi
add ecx,esi
donote_for_channels:
push ecx
mov bl,[edi+FMUSIC_NOTE.eparam]
mov al,[edi+FMUSIC_NOTE.effect]
and ebx,0Fh
cmp al,FMUSIC_XM_PORTATO
je donote_doporta
cmp al,FMUSIC_XM_PORTATOVOLSLIDE
donote_doporta:
setz [ebp+donote_porta]
; First store note and instrument number if there was one
mov cl,[edi+FMUSIC_NOTE.number]
jz donote_rem_note
dec cl
js donote_rem_inst
mov [esi+FMUSIC_CHANNEL.inst-2],cl ; remember the instrument #
donote_rem_inst:
mov cl,[edi] ; get current note
dec ecx
cmp cl,96
jae donote_rem_note
mov [esi+FMUSIC_CHANNEL.note-2],cl ; remember the note
donote_rem_note:
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.inst-2]
mov eax,[ebp+var_mod]
imul ecx,FMUSIC_INSTRUMENT_size
add ecx,[eax+FMUSIC_MODULE.instrument-36]
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.note-2]
cdq
mov al,[eax+ecx+FMUSIC_INSTRUMENT.keymap]
cmp al,16
mov [ebp+donote_iptr],ecx
jae donote_set_sptr
mov edx,[ecx+eax*4+FMUSIC_INSTRUMENT.sample]
donote_set_sptr:
test edx,edx
jnz donote_valid_sptr
mov edx,OFFSET DummySamp
donote_valid_sptr:
mov [ebp+donote_sptr],edx
if NOTEDELAY_ON
mov ecx,[esi+FMUSIC_CHANNEL.freq-2]
mov eax,[esi+FMUSIC_CHANNEL.volume-2]
mov [ebp+donote_oldfreq],ecx
mov ecx,[esi+FMUSIC_CHANNEL.pan-2]
mov [ebp+donote_currtick],eax
mov [ebp+donote_oldpan],ecx
endif
if TREMOLO_ON
; if there is no more tremolo, set volume to volume + last tremolo delta
mov al,[edi+FMUSIC_NOTE.effect]
cmp al,FMUSIC_XM_TREMOLO
je donote_tremolo_vol
cmp BYTE PTR [esi+FMUSIC_CHANNEL.recenteffect-2],FMUSIC_XM_TREMOLO
jne donote_tremolo_vol
mov ecx,[esi+FMUSIC_CHANNEL.voldelta-2]
add [esi+FMUSIC_CHANNEL.volume-2],ecx
donote_tremolo_vol:
mov [esi+FMUSIC_CHANNEL.recenteffect-2],al
endif
xor ecx,ecx
mov [esi+FMUSIC_CHANNEL.voldelta-2],ecx
mov [esi+FMUSIC_CHANNEL.freqdelta-2],ecx
mov BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME_OR_FREQ
; PROCESS NOTE
mov cl,[edi] ; note
dec ecx
cmp cl,96
jae donote_note_ok
; get note according to relative note
movsx eax,BYTE PTR [edx+FSOUND_SAMPLE.relative]
add ecx,eax
mov eax,[ebp+var_mod]
mov [esi+FMUSIC_CHANNEL.realnote-2],cl
; Get period according to realnote and finetune
test BYTE PTR [eax+FMUSIC_MODULE.flags-36],1
je donote_flagsn1
mov eax,[ebp+donote_sptr]
movsx eax,BYTE PTR [eax+FSOUND_SAMPLE.finetune]
cdq
shl ecx,6
sub eax,edx
sar eax,1
lea eax,[ecx+eax-7680]
neg eax
if AMIGAPERIODS_ON
jmp donote_chk_porta
donote_flagsn1:
xchg eax,ecx ; note : EAX
mov ecx,[ebp+donote_sptr] ; [sptr] : ECX
; ESI != 0
call AmigaPeriod
donote_chk_porta:
mov [esi+FMUSIC_CHANNEL.period-2],eax
else
mov [esi+FMUSIC_CHANNEL.period-2],eax
donote_flagsn1:
mov eax,[esi+FMUSIC_CHANNEL.period-2]
endif
; Frequency only changes if there are no portamento effects
cmp BYTE PTR [ebp+donote_porta],0
jne donote_freq_ok
mov [esi+FMUSIC_CHANNEL.freq-2],eax
donote_freq_ok:
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_TRIGGER
donote_note_ok:
; PROCESS INSTRUMENT NUMBER
cmp BYTE PTR [edi+FMUSIC_NOTE.number],0
je donote_zcptr_ok
mov eax,[ebp+donote_sptr]
; DESCRIPTION: Reset current channel
push edi
push 9
movzx ecx,BYTE PTR [eax+FSOUND_SAMPLE.defvol]
mov [esi+FMUSIC_CHANNEL.volume-2],ecx
pop ecx
movzx eax,BYTE PTR [eax+FSOUND_SAMPLE.defpan]
mov [esi+FMUSIC_CHANNEL.pan-2],eax
push 64
xor eax,eax
pop DWORD PTR [esi+FMUSIC_CHANNEL.envvol-2]
push 32
lea edi,[esi+FMUSIC_CHANNEL.envvoltick-2]
pop DWORD PTR [esi+FMUSIC_CHANNEL.envpan-2]
mov DWORD PTR [esi+FMUSIC_CHANNEL.fadeoutvol-2],65536
; memset(&cptr->envvoltick,0,36)
rep stosd
; Retrigger tremolo and vibrato waveforms
mov cl,[esi+FMUSIC_CHANNEL.wavecontrol-2]
pop edi
cmp cl,4Fh
jge z_tremolopos_ok
mov BYTE PTR [esi+FMUSIC_CHANNEL.tremolopos-2],al ; = 0
z_tremolopos_ok:
test cl,0Ch
jnz z_vibpos_ok
mov BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2],al ; = 0
z_vibpos_ok:
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME_OR_PAN
donote_zcptr_ok:
if VOLUMEBYTE_ON
; PROCESS VOLUME BYTE
movzx edx,BYTE PTR [edi+FMUSIC_NOTE.uvolume]
; volume : EDX
; cptr+2 : ESI
call VolByte
endif
; PROCESS KEY OFF
cmp BYTE PTR [edi],97 ; note
jae donote_set_keyoff
cmp BYTE PTR [edi+FMUSIC_NOTE.effect],FMUSIC_XM_KEYOFF
jne donote_keyoff_ok
donote_set_keyoff:
inc BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2]
donote_keyoff_ok:
; PROCESS ENVELOPES
if VOLUMEENVELOPE_ON
mov ecx,[ebp+donote_iptr]
test BYTE PTR [ecx+FMUSIC_INSTRUMENT.VOLtype],1
jz donote_no_voltype
mov al,FMUSIC_VOLUME
; cptr+2 : ESI
; env_iptr : ECX
; control : AL
call Envelope
jmp donote_volenv_ok
donote_no_voltype:
endif
cmp BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2],0
je donote_volenv_ok
and DWORD PTR [esi+FMUSIC_CHANNEL.envvol-2],0
donote_volenv_ok:
if PANENVELOPE_ON
mov ecx,[ebp+donote_iptr]
test BYTE PTR [ecx+FMUSIC_INSTRUMENT.PANtype],1
je donote_no_pantype
mov al,FMUSIC_PAN
; cptr+2 : ESI
; env_iptr : ECX
; control : AL
call Envelope
donote_no_pantype:
endif
; PROCESS VOLUME FADEOUT
cmp BYTE PTR [esi+FMUSIC_CHANNEL.keyoff-2],0
mov ecx,[ebp+donote_iptr]
je donote_fadevol_ok
movzx eax,WORD PTR [ecx+FMUSIC_INSTRUMENT.VOLfade]
sub [esi+FMUSIC_CHANNEL.fadeoutvol-2],eax
jns donote_fadevol_ok
and DWORD PTR [esi+FMUSIC_CHANNEL.fadeoutvol-2],0
donote_fadevol_ok:
; PROCESS TICK 0 EFFECTS
movzx eax,BYTE PTR [edi+FMUSIC_NOTE.effect]
dec eax ; skip FMUSIC_XM_ARPEGGIO
movzx edx,BYTE PTR [edi+FMUSIC_NOTE.eparam]
if EXTRAFINEPORTA_ON
cmp al,32
else
if TREMOR_ON
cmp al,28
else
if MULTIRETRIG_ON
cmp al,26
else
if PANSLIDE_ON
cmp al,24
else
if SETENVELOPEPOS_ON
cmp al,20
else
if GLOBALVOLSLIDE_ON
cmp al,16
else
if SETGLOBALVOLUME_ON
cmp al,15
else
if SETSPEED_ON
cmp al,14
else
cmp al,13
endif
endif
endif
endif
endif
endif
endif
endif
ja donote_s1_brk
test edx,edx
call DWORD PTR [eax*4+S1_TBL]
donote_s1_brk:
if INSTRUMENTVIBRATO_ON
push DWORD PTR [ebp+donote_iptr]
endif
push DWORD PTR [ebp+donote_sptr]
; cptr+2 : ESI
call DoFlags
sub esi,-(FMUSIC_CHANNEL_size)
pop ecx
add edi,FMUSIC_NOTE_size
cmp esi,ecx
jl donote_for_channels
pop ebx
pop esi
leave
S1_r:
ret
S1_TBL:
if PORTAUP_OR_DOWN_ON
dd S1_C1
dd S1_C1
else
dd S1_r
dd S1_r
endif
if PORTATO_ON
dd S1_C3
else
dd S1_r
endif
if VIBRATO_ON
dd S1_C4
else
dd S1_r
endif
if PORTATOVOLSLIDE_ON
dd S1_C5
else
dd S1_r
endif
if VIBRATOVOLSLIDE_ON
dd S1_C6
else
dd S1_r
endif
if TREMOLO_ON
dd S1_C7
else
dd S1_r
endif
if SETPANPOSITION_ON
dd S1_C8
else
dd S1_r
endif
if SETSAMPLEOFFSET_ON
dd S1_C9
else
dd S1_r
endif
if VOLUMESLIDE_ON
dd S1_C10
else
dd S1_r
endif
if PATTERNJUMP_ON
dd S1_C11
else
dd S1_r
endif
if SETVOLUME_ON
dd S1_C12
else
dd S1_r
endif
if PATTERNBREAK_ON
dd S1_C13
else
dd S1_r
endif
dd S1_C14
if EXTRAFINEPORTA_ON
if SETSPEED_ON
dd S1_C15
else
dd S1_r
endif
if SETGLOBALVOLUME_ON
dd S1_C16
else
dd S1_r
endif
if GLOBALVOLSLIDE_ON
dd S1_C17
else
dd S1_r
endif
dd S1_r ; unassigned effect ordinal [18]
dd S1_r ; unassigned effect ordinal [19]
dd S1_r ; skip FMUSIC_XM_KEYOFF
if SETENVELOPEPOS_ON
dd S1_C21
else
dd S1_r
endif
dd S1_r ; unassigned effect ordinal [22]
dd S1_r ; unassigned effect ordinal [23]
dd S1_r ; unassigned effect ordinal [24]
if PANSLIDE_ON
dd S1_C25
else
dd S1_r
endif
dd S1_r ; unassigned effect ordinal [26]
if MULTIRETRIG_ON
dd S1_C27
else
dd S1_r
endif
dd S1_r ; unassigned effect ordinal [28]
if TREMOR_ON
dd S1_C29
else
dd S1_r
endif
dd S1_r ; unassigned effect ordinal [30]
dd S1_r ; unassigned effect ordinal [31]
dd S1_r ; unassigned effect ordinal [32]
dd S1_C33
else
if TREMOR_ON
if SETSPEED_ON
dd S1_C15
else
dd S1_r
endif
if SETGLOBALVOLUME_ON
dd S1_C16
else
dd S1_r
endif
if GLOBALVOLSLIDE_ON
dd S1_C17
else
dd S1_r
endif
dd S1_r
dd S1_r
dd S1_r
if SETENVELOPEPOS_ON
dd S1_C21
else
dd S1_r
endif
dd S1_r
dd S1_r
dd S1_r
if PANSLIDE_ON
dd S1_C25
else
dd S1_r
endif
dd S1_r
if MULTIRETRIG_ON
dd S1_C27
else
dd S1_r
endif
dd S1_r
dd S1_C29
else
if MULTIRETRIG_ON
if SETSPEED_ON
dd S1_C15
else
dd S1_r
endif
if SETGLOBALVOLUME_ON
dd S1_C16
else
dd S1_r
endif
if GLOBALVOLSLIDE_ON
dd S1_C17
else
dd S1_r
endif
dd S1_r
dd S1_r
dd S1_r
if SETENVELOPEPOS_ON
dd S1_C21
else
dd S1_r
endif
dd S1_r
dd S1_r
dd S1_r
if PANSLIDE_ON
dd S1_C25
else
dd S1_r
endif
dd S1_r
dd S1_C27
else
if PANSLIDE_ON
if SETSPEED_ON
dd S1_C15
else
dd S1_r
endif
if SETGLOBALVOLUME_ON
dd S1_C16
else
dd S1_r
endif
if GLOBALVOLSLIDE_ON
dd S1_C17
else
dd S1_r
endif
dd S1_r
dd S1_r
dd S1_r
if SETENVELOPEPOS_ON
dd S1_C21
else
dd S1_r
endif
dd S1_r
dd S1_r
dd S1_r
dd S1_C25
else
if SETENVELOPEPOS_ON
if SETSPEED_ON
dd S1_C15
else
dd S1_r
endif
if SETGLOBALVOLUME_ON
dd S1_C16
else
dd S1_r
endif
if GLOBALVOLSLIDE_ON
dd S1_C17
else
dd S1_r
endif
dd S1_r
dd S1_r
dd S1_r
dd S1_C21
else
if GLOBALVOLSLIDE_ON
if SETSPEED_ON
dd S1_C15
else
dd S1_r
endif
if SETGLOBALVOLUME_ON
dd S1_C16
else
dd S1_r
endif
dd S1_C17
else
if SETGLOBALVOLUME_ON
if SETSPEED_ON
dd S1_C15
else
dd S1_r
endif
dd S1_C16
else
if SETSPEED_ON
dd S1_C15
endif
endif
endif
endif
endif
endif
endif
endif
if PORTAUP_OR_DOWN_ON
S1_C1:
jz donote_xm_porta_end
mov [esi+FMUSIC_CHANNEL.portaupdown-2],dl
donote_xm_porta_end:
ret
endif
if PORTATO_ON
S1_C3:
jz donote_xm_portato_end
mov [esi+FMUSIC_CHANNEL.portaspeed-2],dl
donote_xm_portato_end:
if PORTATOVOLSLIDE_ON
jmp donote_xm_portavolsl_end
else
mov eax,[esi+FMUSIC_CHANNEL.period-2]
and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER_OR_FRQ
mov [esi+FMUSIC_CHANNEL.portatarget-2],eax
ret
endif
endif
if PORTATOVOLSLIDE_ON
S1_C5:
jz donote_xm_portavolsl_end
mov [esi+FMUSIC_CHANNEL.volslide-2],dl
donote_xm_portavolsl_end:
mov eax,[esi+FMUSIC_CHANNEL.period-2]
and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER_OR_FRQ
mov [esi+FMUSIC_CHANNEL.portatarget-2],eax
ret
endif
if VIBRATO_ON
S1_C4:
shr edx,4
jz donote_vib_x_ok
mov [esi+FMUSIC_CHANNEL.vibspeed-2],dl
donote_vib_x_ok:
test ebx,ebx
jz donote_vib_y_ok
mov BYTE PTR [esi+FMUSIC_CHANNEL.vibdepth-2],bl
donote_vib_y_ok:
if VIBRATOVOLSLIDE_ON
xor eax,eax
else
; cptr+2 : ESI
jmp Vibrato
endif
endif
if VIBRATOVOLSLIDE_ON
S1_C6:
jz donote_xm_vibvolsl_end
mov [esi+FMUSIC_CHANNEL.volslide-2],dl
donote_xm_vibvolsl_end:
; cptr+2 : ESI
jmp Vibrato
endif
if TREMOLO_ON
S1_C7:
shr edx,4
jz donote_trem_x_ok
mov [esi+FMUSIC_CHANNEL.tremolospeed-2],dl
donote_trem_x_ok:
test ebx,ebx
jz donote_trem_y_ok
mov [esi+FMUSIC_CHANNEL.tremolodepth-2],bl
donote_trem_y_ok:
ret
endif
if SETPANPOSITION_ON
if PANSLIDE_ON
else
S1_C8:
mov [esi+FMUSIC_CHANNEL.pan-2],edx
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
ret
endif
endif
if SETSAMPLEOFFSET_ON
S1_C9:
shl edx,8
jz donote_soffset_ok
mov [esi+FMUSIC_CHANNEL.sampleoffset-2],edx
donote_soffset_ok:
mov ecx,[ebp+donote_sptr]
mov edx,[ecx+FSOUND_SAMPLE.loopstart]
add edx,[ecx+FSOUND_SAMPLE.looplen]
mov eax,[esi+FMUSIC_CHANNEL.sampleoffset-2]
cmp eax,edx
mov ecx,[esi+FMUSIC_CHANNEL.cptr-2]
jb donote_set_offset
xor eax,eax
and BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],NOT_FMUSIC_TRIGGER
mov [ecx+FSOUND_CHANNEL.mixpos],eax
mov [ecx+FSOUND_CHANNEL.mixposlo],eax
donote_set_offset:
mov [ecx+FSOUND_CHANNEL.fsampleoffset],eax
ret
endif
if VOLUMESLIDE_ON
S1_C10:
jz donote_volslide_ok
mov [esi+FMUSIC_CHANNEL.volslide-2],dl
donote_volslide_ok:
ret
endif
if PATTERNJUMP_ON
S1_C11:
mov eax,[ebp+var_mod]
and DWORD PTR [eax+FMUSIC_MODULE.nextrow-36],0
mov [eax+FMUSIC_MODULE.nextorder-36],edx
if PATTERNBREAK_ON
inc BYTE PTR [ebp+donote_jumpflag]
donote_set_nextord:
endif
movzx ecx,WORD PTR [eax+FMUSIC_MODULE.numorders-36]
cmp [eax+FMUSIC_MODULE.nextorder-36],ecx
jl donote_nextorder_ok
and DWORD PTR [eax+FMUSIC_MODULE.nextorder-36],0
donote_nextorder_ok:
ret
endif
if PATTERNBREAK_ON
S1_C13:
shr edx,4
lea edx,[edx+edx*4]
lea ecx,[ebx+edx*2] ; paramx*10+paramy
mov eax,[ebp+var_mod]
mov [eax+FMUSIC_MODULE.nextrow-36],ecx
if PATTERNJUMP_ON
cmp BYTE PTR [ebp+donote_jumpflag],0
jne donote_nextorder_ok
endif
mov ecx,[eax+FMUSIC_MODULE.order-36]
inc ecx
mov [eax+FMUSIC_MODULE.nextorder-36],ecx
if PATTERNJUMP_ON
jmp donote_set_nextord
else
movzx ecx,WORD PTR [eax+FMUSIC_MODULE.numorders-36]
cmp [eax+FMUSIC_MODULE.nextorder-36],ecx
jl donote_jump_pat
and DWORD PTR [eax+FMUSIC_MODULE.nextorder-36],0
donote_jump_pat:
ret
endif
endif
if SETSPEED_ON
S1_C15:
cmp dl,20h
mov ecx,edx
jae donote_setbpm
mov eax,[ebp+var_mod]
mov [eax+FMUSIC_MODULE.speed-36],ecx
ret
donote_setbpm:
; bpm : ECX
jmp SetBPM
endif
if GLOBALVOLSLIDE_ON
S1_C17:
jz donote_globalvsl_ok
mov ecx,[ebp+var_mod]
mov [ecx+FMUSIC_MODULE.globalvsl-36],dl
donote_globalvsl_ok:
ret
endif
if SETENVELOPEPOS_ON
S1_C21:
test BYTE PTR [ecx+FMUSIC_INSTRUMENT.VOLtype],1
je donote_envelope_r
lea ebx,[ecx+FMUSIC_INSTRUMENT.VOLPoints+4]
; Search and reinterpolate new envelope position
movzx ecx,BYTE PTR [ecx+FMUSIC_INSTRUMENT.VOLnumpoints]
xor eax,eax
cmp dx,[ebx]
jbe donote_env_endwhile
donote_envwhile:
cmp eax,ecx ; if(currpos == iptr->VOLnumpoints) break
je donote_env_endwhile
inc eax
cmp dx,[ebx+eax*4] ; if(current->eparam > iptr->VOLPoints[(currpos+1)<<1]) break
ja donote_envwhile
donote_env_endwhile:
mov [esi+FMUSIC_CHANNEL.envvolpos-2],eax
; if it is at the last position, abort the envelope and continue last volume
dec ecx
cmp eax,ecx
setnl [esi+FMUSIC_CHANNEL.envvolstopped-2]
jl donote_env_continue
movzx eax,WORD PTR [ebx+ecx*4-2]
mov [esi+FMUSIC_CHANNEL.envvol-2],eax ; cptr->envvol = iptr->VOLPoints[((iptr->VOLnumpoints-1)<<1)+1]
donote_envelope_r:
ret
donote_env_continue:
mov [esi+FMUSIC_CHANNEL.envvoltick-2],edx
mov ecx,[ebx+eax*4-4] ; get tick at this point + VOL at this point
mov edx,ecx
movzx ecx,cx
mov [ebp+donote_currtick],ecx
mov ecx,[ebx+eax*4] ; get tick at next point + VOL at next point
mov eax,ecx
movzx ecx,cx
xor dx,dx
; interpolate 2 points to find delta step
sub ecx,[ebp+donote_currtick]
push edx
jz donote_no_tickdiff
xor ax,ax
sub eax,edx
cdq
idiv ecx
xchg eax,ecx
donote_no_tickdiff:
mov [esi+FMUSIC_CHANNEL.envvoldelta-2],ecx
mov eax,[esi+FMUSIC_CHANNEL.envvoltick-2]
sub eax,[ebp+donote_currtick]
imul ecx
pop edx
add eax,edx
mov [esi+FMUSIC_CHANNEL.envvolfrac-2],eax
sar eax,16
mov [esi+FMUSIC_CHANNEL.envvol-2],eax
inc DWORD PTR [esi+FMUSIC_CHANNEL.envvolpos-2]
ret
endif
if PANSLIDE_ON
S1_C25:
jz donote_panslide_ok
mov [esi+FMUSIC_CHANNEL.panslide-2],dl
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
donote_panslide_ok:
ret
endif
if MULTIRETRIG_ON
S1_C27:
jz donote_multiretrig_ok
shr edx,4
mov dh,bl
mov WORD PTR [esi+FMUSIC_CHANNEL.retrigx-2],dx
donote_multiretrig_ok:
ret
endif
if TREMOR_ON
S1_C29:
jz donote_do_tremor
shr edx,4
mov dh,bl
mov WORD PTR [esi+FMUSIC_CHANNEL.tremoron-2],dx
donote_do_tremor:
; cptr : ESI
jmp Tremor
endif
if EXTRAFINEPORTA_ON
S1_C33:
shr edx,4
dec edx
jnz donote_paramx_n1
test ebx,ebx
jz donote_paramy_z1
mov [esi+FMUSIC_CHANNEL.xtraportaup-2],bl
donote_paramy_z1:
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.xtraportaup-2]
sub [esi+FMUSIC_CHANNEL.freq-2],eax
donote_paramx_n1:
dec edx
jnz donote_paramx_n2
test ebx,ebx
jz donote_paramy_z2
mov [esi+FMUSIC_CHANNEL.xtraportadown-2],bl
donote_paramy_z2:
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.xtraportadown-2]
add [esi+FMUSIC_CHANNEL.freq-2],eax
donote_paramx_n2:
endif
S2_r:
ret
S1_C14:
shr edx,4
dec edx ; skip FMUSIC_XM_SETFILTER
if FINEPORTAUP_ON
else
dec edx
endif
if PATTERNDELAY_ON
cmp dl,13
else
if NOTEDELAY_ON
cmp dl,12
else
if FINEVOLUMESLIDE_ON
cmp dl,10
else
if SETPANPOSITION16_ON
cmp dl,7
else
if SETTREMOLOWAVE_ON
cmp dl,6
else
if PATTERNLOOP_ON
cmp dl,5
else
cmp dl,4
endif
endif
endif
endif
endif
endif
if FINEPORTAUP_ON
ja S2_r
else
jae S2_r
endif
donote_do_special:
test ebx,ebx
jmp DWORD PTR [edx*4+S2_TBL]
S2_TBL:
if FINEPORTAUP_ON
dd S2_C1
endif
if FINEPORTADOWN_ON
dd S2_C2
else
dd S2_r
endif
dd S2_r ; skip FMUSIC_XM_SETGLISSANDO
if SETVIBRATOWAVE_ON
dd S2_C4
else
dd S2_r
endif
if SETFINETUNE_ON
dd S2_C5
else
dd S2_r
endif
if PATTERNDELAY_ON
if PATTERNLOOP_ON
dd S2_C6
else
dd S2_r
endif
if SETTREMOLOWAVE_ON
dd S2_C7
else
dd S2_r
endif
if SETPANPOSITION16_ON
dd S2_C8
else
dd S2_r
endif
dd S2_r ; skip FMUSIC_XM_RETRIG
if FINEVOLUMESLIDE_ON
dd S2_C10
dd S2_C11
else
dd S2_r
dd S2_r
endif
dd S2_r ; skip FMUSIC_XM_NOTECUT
if NOTEDELAY_ON
dd S2_C13
else
dd S2_r
endif
dd S2_C14
else
if NOTEDELAY_ON
if PATTERNLOOP_ON
dd S2_C6
else
dd S2_r
endif
if SETTREMOLOWAVE_ON
dd S2_C7
else
dd S2_r
endif
if SETPANPOSITION16_ON
dd S2_C8
else
dd S2_r
endif
dd S2_r ; skip FMUSIC_XM_RETRIG
if FINEVOLUMESLIDE_ON
dd S2_C10
dd S2_C11
else
dd S2_r
dd S2_r
endif
dd S2_r
dd S2_C13
else
if FINEVOLUMESLIDE_ON
if PATTERNLOOP_ON
dd S2_C6
else
dd S2_r
endif
if SETTREMOLOWAVE_ON
dd S2_C7
else
dd S2_r
endif
if SETPANPOSITION16_ON
dd S2_C8
else
dd S2_r
endif
dd S2_r
dd S2_C10
dd S2_C11
else
if SETPANPOSITION16_ON
if PATTERNLOOP_ON
dd S2_C6
else
dd S2_r
endif
if SETTREMOLOWAVE_ON
dd S2_C7
else
dd S2_r
endif
dd S2_C8
else
if SETTREMOLOWAVE_ON
if PATTERNLOOP_ON
dd S2_C6
else
dd S2_r
endif
dd S2_C7
else
if PATTERNLOOP_ON
dd S2_C6
endif
endif
endif
endif
endif
endif
if FINEPORTAUP_ON
S2_C1:
jz donote_finepup_ok
mov [esi+FMUSIC_CHANNEL.fineportaup-2],bl
donote_finepup_ok:
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.fineportaup-2]
shl eax,2
sub [esi+FMUSIC_CHANNEL.freq-2],eax
ret
endif
if FINEPORTADOWN_ON
S2_C2:
jz donote_finepdown_ok
mov [esi+FMUSIC_CHANNEL.fineportadown-2],bl
donote_finepdown_ok:
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.fineportadown-2]
shl eax,2
add [esi+FMUSIC_CHANNEL.freq-2],eax
ret
endif
if SETVIBRATOWAVE_ON
S2_C4:
and BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],0F0h
or BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],bl
ret
endif
if SETFINETUNE_ON
S2_C5:
mov eax,[ebp+donote_sptr]
mov [eax+FSOUND_SAMPLE.finetune],bl
ret
endif
if PATTERNLOOP_ON
S2_C6:
jnz donote_not_paramy
mov eax,[ebp+var_mod]
mov eax,[eax+FMUSIC_MODULE.row-36]
mov [esi+FMUSIC_CHANNEL.patlooprow-2],eax
ret
donote_not_paramy:
mov cl,[esi+FMUSIC_CHANNEL.patloopno-2]
dec cl
jns donote_patloopno_ok
mov ecx,ebx
donote_patloopno_ok:
mov [esi+FMUSIC_CHANNEL.patloopno-2],cl
jz donote_patloopno_end
mov eax,[esi+FMUSIC_CHANNEL.patlooprow-2]
mov ecx,[ebp+var_mod]
mov [ecx+FMUSIC_MODULE.nextrow-36],eax
donote_patloopno_end:
ret
endif
if SETTREMOLOWAVE_ON
S2_C7:
and BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],0Fh
shl ebx,4
or BYTE PTR [esi+FMUSIC_CHANNEL.wavecontrol-2],bl
ret
endif
if SETPANPOSITION16_ON
S2_C8:
shl ebx,4
mov [esi+FMUSIC_CHANNEL.pan-2],ebx
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
ret
endif
if FINEVOLUMESLIDE_ON
S2_C10:
neg ebx
S2_C11:
jz donote_finevols_ok
mov [esi+FMUSIC_CHANNEL.finevslup-2],bl
donote_finevols_ok:
movsx eax,BYTE PTR [esi+FMUSIC_CHANNEL.finevslup-2]
sub [esi+FMUSIC_CHANNEL.volume-2],eax
ret
endif
if NOTEDELAY_ON
S2_C13:
mov eax,[ebp+donote_oldfreq]
mov edx,[ebp+donote_currtick]
mov [esi+FMUSIC_CHANNEL.freq-2],eax
mov eax,[ebp+donote_oldpan]
mov [esi+FMUSIC_CHANNEL.pan-2],eax
mov BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],0
if SETVOLUME_ON
else
mov [esi+FMUSIC_CHANNEL.volume-2],edx
ret
endif
endif
if SETVOLUME_ON
S1_C12:
mov [esi+FMUSIC_CHANNEL.volume-2],edx
ret
endif
if PATTERNDELAY_ON
S2_C14:
mov ecx,[ebp+var_mod]
imul ebx,DWORD PTR [ecx+FMUSIC_MODULE.speed-36]
mov [ecx+FMUSIC_MODULE.patterndelay-36],ebx
ret
endif
 
DoEffs:
; mod+36 = ESI
; var_mod equ -4
doeff_current equ -8
; Point our note pointer to the correct pattern buffer, and to the
; correct offset in this buffer indicated by row and number of channels
mov eax,[esi+FMUSIC_MODULE.order-36]
push ebp
mov bl,[eax+esi+FMUSIC_MODULE.orderlist-36]
mov eax,[esi+FMUSIC_MODULE.row-36]
mul DWORD PTR [esi+FMUSIC_MODULE.numchannels-36]
lea eax,[eax+eax*4] ; x SIZE FMUSIC_NOTE
mov ebp,esp
; mod->pattern[mod->orderlist[mod->order]].data+(mod->row*mod->numchannels)
add eax,[ecx+ebx*FMUSIC_PATTERN_size+FMUSIC_PATTERN.data]
push esi ; -> var_mod
push eax ; -> doeff_current
mov eax,[esi+FMUSIC_MODULE.numchannels-36]
shl eax,7 ; x FMUSIC_CHANNEL_size
push esi
mov esi,[esi+FMUSIC_MODULE.uFMOD_Ch-36]
inc esi
inc esi
add eax,esi
doeff_for_channels:
push eax
movzx edi,BYTE PTR [esi+FMUSIC_CHANNEL.inst-2]
mov edx,[ebp+var_mod]
imul edi,FMUSIC_INSTRUMENT_size
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.note-2]
add edi,[edx+FMUSIC_MODULE.instrument-36]
cdq
mov al,[eax+edi+FMUSIC_INSTRUMENT.keymap]
cmp al,16
jae doeff_set_sptr
mov edx,[edi+eax*4+FMUSIC_INSTRUMENT.sample]
doeff_set_sptr:
test edx,edx
jnz doeff_valid_sptr
mov edx,OFFSET DummySamp
doeff_valid_sptr:
xor ebx,ebx
if INSTRUMENTVIBRATO_ON
push edi ; iptr
endif
push edx ; sptr
mov [esi+FMUSIC_CHANNEL.voldelta-2],ebx
mov [esi+FMUSIC_CHANNEL.freqdelta-2],ebx
mov [esi+FMUSIC_CHANNEL.notectrl-2],bl
; PROCESS ENVELOPES
if VOLUMEENVELOPE_ON
test BYTE PTR [edi+FMUSIC_INSTRUMENT.VOLtype],1
je doeff_no_voltype
mov al,FMUSIC_VOLUME
mov ecx,edi
; cptr+2 : ESI
; env_iptr : ECX
; control : AL
call Envelope
doeff_no_voltype:
endif
if PANENVELOPE_ON
test BYTE PTR [edi+FMUSIC_INSTRUMENT.PANtype],1
je doeff_no_pantype
mov al,FMUSIC_PAN
mov ecx,edi
; cptr+2 : ESI
; env_iptr : ECX
; control : AL
call Envelope
doeff_no_pantype:
endif
; PROCESS VOLUME FADEOUT
cmp [esi+FMUSIC_CHANNEL.keyoff-2],bl
je doeff_fadevol_ok
movzx eax,WORD PTR [edi+FMUSIC_INSTRUMENT.VOLfade]
sub [esi+FMUSIC_CHANNEL.fadeoutvol-2],eax
jns doeff_fadevol_ns
mov [esi+FMUSIC_CHANNEL.fadeoutvol-2],ebx
doeff_fadevol_ns:
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
doeff_fadevol_ok:
if VOLUMEBYTE_ON
mov eax,[ebp+doeff_current]
movzx eax,BYTE PTR [eax+FMUSIC_NOTE.uvolume]
mov ecx,eax
shr eax,4
and cl,0Fh
sub al,6
jz doeff_case_vol6
dec eax
jz doeff_case_vol7
if VIBRATO_ON
sub al,4
jz doeff_case_volB
dec eax
dec eax
else
sub al,6
endif
jz doeff_case_volD
dec eax
if PORTATO_ON
jz doeff_case_volE
dec eax
jnz doeff_volbyte_end
; cptr+2 : ESI
call Portamento
jmp doeff_volbyte_end
else
jnz doeff_volbyte_end
endif
doeff_case_volE:
neg ecx
doeff_case_volD:
sub [esi+FMUSIC_CHANNEL.pan-2],ecx
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
jmp doeff_volbyte_end
if VIBRATO_ON
doeff_case_volB:
mov [esi+FMUSIC_CHANNEL.vibdepth-2],cl
; cptr+2 : ESI
call Vibrato
jmp doeff_volbyte_end
endif
doeff_case_vol6:
neg ecx
doeff_case_vol7:
add [esi+FMUSIC_CHANNEL.volume-2],ecx
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
doeff_volbyte_end:
endif ; VOLUMEBYTE_ON
mov edx,[ebp+doeff_current]
movzx ebx,BYTE PTR [edx+FMUSIC_NOTE.eparam]
mov ecx,ebx
and ebx,0Fh ; grab the effect parameter y
movzx eax,BYTE PTR [edx+FMUSIC_NOTE.effect]
shr cl,4 ; grab the effect parameter x
if ARPEGGIO_ON
else
dec eax
endif
if TREMOR_ON
cmp al,29
else
if MULTIRETRIG_ON
cmp al,27
else
if PANSLIDE_ON
cmp al,25
else
if GLOBALVOLSLIDE_ON
cmp al,17
else
if RETRIG_ON
cmp al,14
else
if NOTECUT_ON
cmp al,14
else
if NOTEDELAY_ON
cmp al,14
else
cmp al,10
endif
endif
endif
endif
endif
endif
endif
if ARPEGGIO_ON
ja doeff_s3_brk
else
jae doeff_s3_brk
endif
call DWORD PTR [eax*4+S3_TBL]
doeff_s3_brk:
; cptr+2 : ESI
call DoFlags
sub esi,-(FMUSIC_CHANNEL_size)
pop eax
add DWORD PTR [ebp+doeff_current],FMUSIC_NOTE_size
cmp esi,eax
jl doeff_for_channels
pop esi
doeff_R:
leave
S3_r:
ret
S3_TBL:
if ARPEGGIO_ON
dd S3_C0
endif
if PORTAUP_ON
dd S3_C1
else
dd S3_r
endif
if PORTADOWN_ON
dd S3_C2
else
dd S3_r
endif
if PORTATO_ON
; cptr+2 : ESI
dd Portamento
else
dd S3_r
endif
if VIBRATO_ON
; cptr+2 : ESI
dd Vibrato
else
dd S3_r
endif
if PORTATOVOLSLIDE_ON
dd S3_C5
else
dd S3_r
endif
if VIBRATOVOLSLIDE_ON
dd S3_C6
else
dd S3_r
endif
if TREMOLO_ON
; cptr+2 : ESI
dd Tremolo
else
dd S3_r
endif
dd S3_r ; skip FMUSIC_XM_SETPANPOSITION
dd S3_r ; skip FMUSIC_XM_SETSAMPLEOFFSET
if VOLUMESLIDE_ON
dd S3_C10
else
dd S3_r
endif
if TREMOR_ON
dd S3_r ; skip FMUSIC_XM_PATTERNJUMP
dd S3_r ; slip FMUSIC_XM_SETVOLUME
dd S3_r ; skip FMUSIC_XM_PATTERNBREAK
dd S3_C14
dd S3_r ; skip FMUSIC_XM_SETSPEED
dd S3_r ; skip FMUSIC_XM_SETGLOBALVOLUME
if GLOBALVOLSLIDE_ON
dd S3_C17
else
dd S3_r
endif
dd S3_r ; unassigned effect ordinal [18]
dd S3_r ; unassigned effect ordinal [19]
dd S3_r ; skip FMUSIC_XM_KEYOFF
dd S3_r ; skip FMUSIC_XM_SETENVELOPEPOS
dd S3_r ; unassigned effect ordinal [22]
dd S3_r ; unassigned effect ordinal [23]
dd S3_r ; unassigned effect ordinal [24]
if PANSLIDE_ON
dd S3_C25
else
dd S3_r
endif
dd S3_r ; unassigned effect ordinal [26]
if MULTIRETRIG_ON
dd S3_C27
else
dd S3_r
endif
dd S3_r ; unassigned effect ordinal [28]
; case FMUSIC_XM_TREMOR
; cptr : ESI
dd Tremor
else
if MULTIRETRIG_ON
dd S3_r
dd S3_r
dd S3_r
dd S3_C14
dd S3_r
dd S3_r
if GLOBALVOLSLIDE_ON
dd S3_C17
else
dd S3_r
endif
dd S3_r
dd S3_r
dd S3_r
dd S3_r
dd S3_r
dd S3_r
dd S3_r
if PANSLIDE_ON
dd S3_C25
else
dd S3_r
endif
dd S3_r
dd S3_C27
else
if PANSLIDE_ON
dd S3_r
dd S3_r
dd S3_r
dd S3_C14
dd S3_r
dd S3_r
if GLOBALVOLSLIDE_ON
dd S3_C17
else
dd S3_r
endif
dd S3_r
dd S3_r
dd S3_r
dd S3_r
dd S3_r
dd S3_r
dd S3_r
dd S3_C25
else
if GLOBALVOLSLIDE_ON
dd S3_r
dd S3_r
dd S3_r
dd S3_C14
dd S3_r
dd S3_r
dd S3_C17
else
if RETRIG_ON
dd S3_r
dd S3_r
dd S3_r
dd S3_C14
else
if NOTECUT_ON
dd S3_r
dd S3_r
dd S3_r
dd S3_C14
else
if NOTEDELAY_ON
dd S3_r
dd S3_r
dd S3_r
dd S3_C14
endif
endif
endif
endif
endif
 
endif
endif
if VIBRATOVOLSLIDE_ON
S3_C6:
; cptr+2 : ESI
call Vibrato
if VOLUMESLIDE_ON
if PORTATOVOLSLIDE_ON
jmp S3_C10
endif
else
mov cl,[esi+FMUSIC_CHANNEL.volslide-2]
mov eax,ecx
and eax,0Fh
shr ecx,4
jz doeff_volslide_ok
; Slide up takes precedence over down
xchg eax,ecx
neg eax
doeff_volslide_ok:
sub [esi+FMUSIC_CHANNEL.volume-2],eax
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
ret
endif
endif
if PORTATOVOLSLIDE_ON
S3_C5:
; cptr+2 : ESI
call Portamento
if VOLUMESLIDE_ON
xor ecx,ecx
else
movzx ecx,BYTE PTR [esi+FMUSIC_CHANNEL.volslide-2]
mov eax,ecx
and eax,0Fh
shr ecx,4
jz doeff_volslide_ok
; Slide up takes precedence over down
xchg eax,ecx
neg eax
doeff_volslide_ok:
sub [esi+FMUSIC_CHANNEL.volume-2],eax
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
ret
endif
endif
if VOLUMESLIDE_ON
S3_C10:
mov cl,[esi+FMUSIC_CHANNEL.volslide-2]
mov eax,ecx
and eax,0Fh
shr ecx,4
jz doeff_volslide_ok
; Slide up takes precedence over down
xchg eax,ecx
neg eax
doeff_volslide_ok:
sub [esi+FMUSIC_CHANNEL.volume-2],eax
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
ret
endif
if PORTADOWN_ON
S3_C2:
mov al,[esi+FMUSIC_CHANNEL.portaupdown-2]
DoFreqSlide:
mov ecx,[esi+FMUSIC_CHANNEL.freq-2]
lea ecx,[ecx+eax*4]
cmp ecx,1
jge DoFreqSlide_ok
push 1
pop ecx
DoFreqSlide_ok:
mov [esi+FMUSIC_CHANNEL.freq-2],ecx
and DWORD PTR [esi+FMUSIC_CHANNEL.freqdelta-2],0
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
ret
endif
if PORTAUP_ON
S3_C1:
mov al,[esi+FMUSIC_CHANNEL.portaupdown-2]
if PORTADOWN_ON
neg eax
jmp DoFreqSlide
else
shl eax,2
mov ecx,[esi+FMUSIC_CHANNEL.freq-2]
sub ecx,eax
cmp ecx,1
jge DoFreqSlide_ok
push 1
pop ecx
DoFreqSlide_ok:
mov [esi+FMUSIC_CHANNEL.freq-2],ecx
and DWORD PTR [esi+FMUSIC_CHANNEL.freqdelta-2],0
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
ret
endif
endif
if ARPEGGIO_ON
S3_C0:
cmp BYTE PTR [edx+FMUSIC_NOTE.eparam],ch
jbe doeff_arpeggio_ok
mov eax,[ebp+var_mod]
mov eax,[eax+FMUSIC_MODULE.tick-36]
push 3
cdq
pop edi
idiv edi
dec edx
jz doeff_arpeg_c1
dec edx
jne doeffs_enable_freq
mov ecx,ebx
doeff_arpeg_c1:
mov eax,[ebp+var_mod]
test BYTE PTR [eax+FMUSIC_MODULE.flags-36],1
je doeffs_flagsn1
doeffs_arpeggio_freqd:
shl ecx,6
mov [esi+FMUSIC_CHANNEL.freqdelta-2],ecx
if AMIGAPERIODS_ON
jmp doeffs_enable_freq
endif
doeffs_flagsn1:
if AMIGAPERIODS_ON
movzx eax,BYTE PTR [esi+FMUSIC_CHANNEL.realnote-2]
mov edi,eax
add eax,ecx ; note : EAX
mov ecx,[esp+4] ; [sptr] : ECX
; ESI != 0
call AmigaPeriod
xchg eax,edi ; note : EAX
mov ecx,[esp+4] ; [sptr] : ECX
; ESI != 0
call AmigaPeriod
sub edi,eax
mov [esi+FMUSIC_CHANNEL.freqdelta-2],edi
endif
doeffs_enable_freq:
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
doeff_arpeggio_ok:
ret
endif
if MULTIRETRIG_ON
S3_C27:
mov cl,[esi+FMUSIC_CHANNEL.retrigy-2]
test ecx,ecx
jz doeff_multiretrig_ok
mov eax,[ebp+var_mod]
mov eax,[eax+FMUSIC_MODULE.tick-36]
cdq
idiv ecx
test edx,edx
jnz doeff_multiretrig_ok
mov cl,[esi+FMUSIC_CHANNEL.retrigx-2]
and ecx,0Fh
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_TRIGGER
dec ecx
mov eax,[esi+FMUSIC_CHANNEL.volume-2]
js doeff_multiretrig_ok
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
call DWORD PTR [ecx*4+S4_TBL]
mov [esi+FMUSIC_CHANNEL.volume-2],eax
S4_C2:
dec eax
S4_C1:
dec eax
doeff_multiretrig_ok:
ret
S4_C5:
sub eax,8
S4_C4:
sub eax,4
S4_C3:
sub eax,4
ret
S4_C6:
shl eax,1
push 3
cdq
pop ecx
idiv ecx
ret
S4_C14:
lea eax,[eax+eax*2]
S4_C7:
sar eax,1
ret
S4_C10:
inc eax
S4_C9:
inc eax
ret
S4_C13:
add eax,8
S4_C12:
add eax,4
S4_C11:
add eax,4
ret
S4_C15:
shl eax,1
S4_r:
ret
S4_TBL:
dd S4_C1
dd S4_C2
dd S4_C3
dd S4_C4
dd S4_C5
dd S4_C6
dd S4_C7
dd S4_r
dd S4_C9
dd S4_C10
dd S4_C11
dd S4_C12
dd S4_C13
dd S4_C14
dd S4_C15
endif
if PANSLIDE_ON
S3_C25:
mov cl,[esi+FMUSIC_CHANNEL.panslide-2]
mov eax,ecx
and eax,0Fh
mov edx,[esi+FMUSIC_CHANNEL.pan-2]
shr ecx,4
; Slide right takes precedence over left
jnz doeff_pan_slide_right
sub edx,eax
jns doeff_panslide_ok
mov edx,ecx
jmp doeff_panslide_ok
doeff_pan_slide_right:
add ecx,edx
cdq
dec dl ; edx = 255
cmp ecx,edx
jg doeff_panslide_ok
mov edx,ecx
doeff_panslide_ok:
if SETPANPOSITION_ON
S1_C8:
endif
mov [esi+FMUSIC_CHANNEL.pan-2],edx
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
ret
endif
if GLOBALVOLSLIDE_ON
S3_C17:
mov ecx,[ebp+var_mod]
mov edx,[ecx+FMUSIC_MODULE.globalvolume-36]
mov al,[ecx+FMUSIC_MODULE.globalvsl-36]
test al,0F0h
; Slide up takes precedence over down
jnz doeff_gvsl_slide_up
and eax,0Fh
sub edx,eax
jns set_global_vol
cdq
xor eax,eax
doeff_gvsl_slide_up:
shr eax,4
add edx,eax
set_global_vol:
if SETGLOBALVOLUME_ON
else
cmp edx,64
jle doeff_setglobalvol
push 64
pop edx
doeff_setglobalvol:
mov [ecx+FMUSIC_MODULE.globalvolume-36],edx
ret
endif
endif
if SETGLOBALVOLUME_ON
S1_C16:
cmp edx,64
mov ecx,[ebp+var_mod]
jle do_setglobalvol
push 64
pop edx
do_setglobalvol:
mov [ecx+FMUSIC_MODULE.globalvolume-36],edx
ret
endif
S3_C14:
if RETRIG_ON
cmp cl,FMUSIC_XM_RETRIG
je doeff_do_retrig
endif
if NOTECUT_ON
sub cl,FMUSIC_XM_NOTECUT
jz doeff_do_notecut
endif
if NOTEDELAY_ON
if NOTECUT_ON
dec cl
else
cmp cl,FMUSIC_XM_NOTEDELAY
endif
jne doeff_special_r
mov ecx,[ebp+var_mod]
xor eax,eax
cmp [ecx+FMUSIC_MODULE.tick-36],ebx
jne doeff_notectrl_z
mov edx,[esp+4]
mov DWORD PTR [esi+FMUSIC_CHANNEL.fadeoutvol-2],65536
movzx edx,BYTE PTR [edx+FSOUND_SAMPLE.defvol]
lea ecx,[eax+9]
mov [esi+FMUSIC_CHANNEL.volume-2],edx
mov edx,[esi+FMUSIC_CHANNEL.envvol-2]
lea edi,[esi+FMUSIC_CHANNEL.envvoltick-2]
cmp ecx,edx
sbb edx,edx
and edx,64
mov [esi+FMUSIC_CHANNEL.envvol-2],edx
; memset(&cptr->envvoltick,0,36)
rep stosd
; Retrigger tremolo and vibrato waveforms
mov cl,[esi+FMUSIC_CHANNEL.wavecontrol-2]
cmp cl,4Fh
jge z2_tremolopos_ok
mov BYTE PTR [esi+FMUSIC_CHANNEL.tremolopos-2],al ; = 0
z2_tremolopos_ok:
test cl,0Ch
jnz z2_vibpos_ok
mov BYTE PTR [esi+FMUSIC_CHANNEL.vibpos-2],al ; = 0
z2_vibpos_ok:
mov eax,[esi+FMUSIC_CHANNEL.period-2]
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOL_OR_FREQ_OR_TR
mov [esi+FMUSIC_CHANNEL.freq-2],eax
if VOLUMEBYTE_ON
mov eax,[ebp+doeff_current]
movzx edx,BYTE PTR [eax+FMUSIC_NOTE.uvolume]
; volume : EDX
; cptr : ESI
jmp VolByte
else
ret
endif
doeff_notectrl_z:
mov BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],al
doeff_special_r:
endif
ret
if NOTECUT_ON
doeff_do_notecut:
mov ecx,[ebp+var_mod]
cmp [ecx+FMUSIC_MODULE.tick-36],ebx
jne doeff_notecut_ok
and DWORD PTR [esi+FMUSIC_CHANNEL.volume-2],0
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
doeff_notecut_ok:
ret
endif
if RETRIG_ON
doeff_do_retrig:
test ebx,ebx
jz doeff_retrig_ok
mov eax,[ebp+var_mod]
mov eax,[eax+FMUSIC_MODULE.tick-36]
cdq
idiv ebx
test edx,edx
jne doeff_retrig_ok
or BYTE PTR [esi+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOL_OR_FREQ_OR_TR
doeff_retrig_ok:
ret
endif
 
; DESCRIPTION: Process sample flags
DoFlags:
; cptr+2 - ESI
flags_iptr equ 16
flags_sptr equ 12
mov ebx,esi
push esi
push edi
if INSTRUMENTVIBRATO_ON
; THIS GETS ADDED TO PREVIOUS FREQDELTAS
mov esi,[esp+flags_iptr]
xor eax,eax
movzx edx,BYTE PTR [esi+FMUSIC_INSTRUMENT.VIBtype]
lea edi,[ebx+FMUSIC_CHANNEL.ivibpos-2]
dec edx ; switch(iptr->VIBtype)
js ivib_case_0
mov al,128
jz ivib_case_1
dec edx
jz ivib_case_2
; case 3 / default
mov dl,-128 ; -128 = 384 on a 1byte scope
sub edx,[edi]
trim:
movzx edx,dl
sub eax,edx
sar eax,1 ; delta = (128-((384-cptr->ivibpos)&0xFF))>>1 (case 3)
; delta = (128-((cptr->ivibpos+128)&0xFF))>>1 (case 2)
jmp ivib_end_switch
ivib_case_2:
mov edx,[edi]
sub edx,eax
jmp trim
ivib_case_1:
cmp [edi],eax
sbb edx,edx
and edx,eax
lea eax,[edx-64] ; delta = +/- 64
jmp ivib_end_switch
ivib_case_0:
; delta = 64 sin(2 Pi x/256)
mov ecx,[edi]
mov edx,ecx
and ecx,7Fh
cmp ecx,65
adc eax,-1
xor ecx,eax
and eax,129
add ecx,eax
shr edx,8
movzx eax,BYTE PTR [OFFSET sin64+ecx]
sbb edx,edx
xor eax,edx
sub eax,edx
ivib_end_switch:
movzx edx,BYTE PTR [esi+FMUSIC_INSTRUMENT.iVIBdepth]
imul edx,eax ; delta *= iptr->iVIBdepth
movzx eax,BYTE PTR [esi+FMUSIC_INSTRUMENT.VIBsweep]
test eax,eax
jz sweep_ok
push edi
xchg eax,edi
mov eax,[ebx+FMUSIC_CHANNEL.ivibsweeppos-2]
imul edx
idiv edi
xchg eax,edx ; delta *= cptr->ivibsweeppos/iptr->VIBsweep
xchg eax,edi ; iptr->VIBsweep
pop edi
sweep_ok:
sar edx,6
add [ebx+FMUSIC_CHANNEL.freqdelta-2],edx ; cptr->freqdelta += delta>>6
mov edx,[ebx+FMUSIC_CHANNEL.ivibsweeppos-2]
inc edx
cmp edx,eax
jle sweeppos_ok
xchg eax,edx
sweeppos_ok:
movzx eax,BYTE PTR [esi+FMUSIC_INSTRUMENT.VIBrate]
add eax,[edi] ; cptr->ivibpos += iptr->VIBrate
mov [ebx+FMUSIC_CHANNEL.ivibsweeppos-2],edx
neg ah
or BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
neg ah
sbb ah,0 ; ivibpos - 256
mov [edi],eax
endif ; INSTRUMENTVIBRATO_ON
mov esi,[ebx+FMUSIC_CHANNEL.cptr-2]
test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_TRIGGER
jz no_trig
; TRIGGER: allocate a channel
cmp DWORD PTR [esi+FSOUND_CHANNEL.fsptr],0
jz no_swap
; Swap between channels to avoid sounds cutting each other off and causing a click
mov ecx,esi
sub ecx,DWORD PTR [OFFSET _mod+FMUSIC_MODULE.Channels]
shr ecx,7 ; /FSOUND_CHANNEL_size + 1
sbb edi,edi
and edi,-FSOUND_CHANNEL_size*2
lea edi,[esi+edi+FSOUND_CHANNEL_size]
push edi
; Copy the whole channel except it's trailing data
push (FSOUND_CHANNEL_size-20)/4
mov [ebx+FMUSIC_CHANNEL.cptr-2],edi
pop ecx
rep movsd
; This should cause the old channel to ramp out nicely
mov [esi+FSOUND_CHANNEL.actualvolume-FSOUND_CHANNEL.fsptr],ecx
mov [esi+FSOUND_CHANNEL.leftvolume-FSOUND_CHANNEL.fsptr],ecx
mov [esi+FSOUND_CHANNEL.rightvolume-FSOUND_CHANNEL.fsptr],ecx
pop esi
no_swap:
lea edi,[esi+FSOUND_CHANNEL.fsptr]
mov eax,[esp+flags_sptr]
stosd ; fsptr
; START THE SOUND!
xor eax,eax
mov edx,[esi+FSOUND_CHANNEL.fsampleoffset]
stosd ; mixposlo
stosd ; ramp_leftvolume
stosd ; ramp_rightvolume
stosd ; ramp_count, speeddir
mov [esi+FSOUND_CHANNEL.fsampleoffset],eax
mov [esi+FSOUND_CHANNEL.mixpos],edx
no_trig:
mov eax,[ebx+FMUSIC_CHANNEL.volume-2]
xor ecx,ecx
cdq
not edx
and eax,edx
cmp eax,64
jle volume_le64
lea eax,[ecx+64]
volume_le64:
dec cl ; ecx <- 255
mov [ebx+FMUSIC_CHANNEL.volume-2],eax
test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_VOLUME
jz no_volume
add eax,[ebx+FMUSIC_CHANNEL.voldelta-2] ; 6 bit (64)
imul DWORD PTR [ebx+FMUSIC_CHANNEL.envvol-2] ; 6 bit (64)
imul DWORD PTR [_mod+FMUSIC_MODULE.globalvolume] ; 6 bit (64)
imul ecx ; eax *= 255
imul DWORD PTR [ebx+FMUSIC_CHANNEL.fadeoutvol-2] ; 16 bit (65536)
; eax:edx /= (2 * 64 * 64 * 64 * 65536)
sar edx,3
mov eax,[esi+FSOUND_CHANNEL.actualpan]
mov [esi+FSOUND_CHANNEL.actualvolume],edx
mov edi,edx
imul edx
idiv ecx
mov [esi+FSOUND_CHANNEL.leftvolume],eax ; leftvolume <- volume*actualpan/255
mov eax,ecx
sub eax,[esi+FSOUND_CHANNEL.actualpan]
imul edi
idiv ecx
mov [esi+FSOUND_CHANNEL.rightvolume],eax
no_volume:
test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_PAN
jz no_pan
mov edi,128
mov eax,[ebx+FMUSIC_CHANNEL.pan-2]
sub eax,edi
cdq
xor eax,edx
sub eax,edx
sub edi,eax
mov eax,[ebx+FMUSIC_CHANNEL.envpan-2]
sar edi,5
sub eax,32
imul edi
add eax,[ebx+FMUSIC_CHANNEL.pan-2]
cdq
not edx
and eax,edx ; if(pan < 0) pan = 0
mov edi,[esi] ; actualvolume
cmp eax,ecx
mov edx,ecx
xchg eax,edi
jae pan_ae255
imul edi
idiv ecx
mov edx,edi
pan_ae255:
xchg eax,edx
mov [esi+FSOUND_CHANNEL.actualpan],eax
mov [esi+FSOUND_CHANNEL.leftvolume],edx
not al ; 255 - pan
imul DWORD PTR [esi] ; actualvolume
idiv ecx
mov [esi+FSOUND_CHANNEL.rightvolume],eax
no_pan:
test BYTE PTR [ebx+FMUSIC_CHANNEL.notectrl-2],FMUSIC_FREQ
jz no_freq
mov ecx,[ebx+FMUSIC_CHANNEL.freq-2]
xor edx,edx
add ecx,[ebx+FMUSIC_CHANNEL.freqdelta-2]
lea eax,[edx+40] ; f = 40 Hz
jle freq_bounds_ok
test BYTE PTR [_mod+FMUSIC_MODULE.flags],1
jnz modflags_n1
mov eax,0DA7790h
div ecx
xor edx,edx
jmp freq_bounds_ok
modflags_n1:
mov eax,4608
sub eax,[ebx+FMUSIC_CHANNEL.freq-2]
add eax,[ebx+FMUSIC_CHANNEL.freqdelta-2]
push eax
fild DWORD PTR [esp]
fmul DWORD PTR [f0_0013]
fld st0
frndint
fsub st1,st0
fxch st1
f2xm1
fld1
faddp st1,st0
fscale
fstp st1
fmul DWORD PTR [f8363_0]
fistp DWORD PTR [esp]
pop eax ; freq = 625.271028*exp2((4608-period)/64)
freq_bounds_ok:
mov ebx,FSOUND_MixRate
div ebx
mov [esi+FSOUND_CHANNEL.speedhi],eax
div ebx
mov [esi+FSOUND_CHANNEL.speedlo],eax
no_freq:
pop edi
pop esi
if INSTRUMENTVIBRATO_ON
ret 8
else
ret 4
endif
/programs/develop/libraries/ufmod/eff.inc
0,0 → 1,60
; XM-file: full.xm
 
; uFMOD optional features:
INFO_API_ON equ 1 ; enable InfoAPI
NOLOOP_ON equ 1 ; enable XM_NOLOOP
PAUSE_RESUME_ON equ 1 ; enable pause/resume and XM_SUSPENDED
VOL_CONTROL_ON equ 1 ; enable volume control
JUMP_TO_PAT_ON equ 1 ; enable Jump2Pattern
XM_FILE_ON equ 1 ; enable file loading
 
; Special flags:
INSTRUMENTVIBRATO_ON equ 1
VOLUMEENVELOPE_ON equ 1
PANENVELOPE_ON equ 1
VOLUMEBYTE_ON equ 1
ADPCM_ON equ 1
AMIGAPERIODS_ON equ 1
 
; XM effects:
ARPEGGIO_ON equ 1
PORTAUP_ON equ 1
PORTADOWN_ON equ 1
PORTATO_ON equ 1
VIBRATO_ON equ 1
PORTATOVOLSLIDE_ON equ 1
VIBRATOVOLSLIDE_ON equ 1
TREMOLO_ON equ 1
SETPANPOSITION_ON equ 1
SETSAMPLEOFFSET_ON equ 1
VOLUMESLIDE_ON equ 1
PATTERNJUMP_ON equ 1
SETVOLUME_ON equ 1
PATTERNBREAK_ON equ 1
SETSPEED_ON equ 1
SETGLOBALVOLUME_ON equ 1
GLOBALVOLSLIDE_ON equ 1
KEYOFF_ON equ 1
SETENVELOPEPOS_ON equ 1
PANSLIDE_ON equ 1
MULTIRETRIG_ON equ 1
TREMOR_ON equ 1
EXTRAFINEPORTA_ON equ 1
FINEPORTAUP_ON equ 1
FINEPORTADOWN_ON equ 1
SETVIBRATOWAVE_ON equ 1
SETFINETUNE_ON equ 1
PATTERNLOOP_ON equ 1
SETTREMOLOWAVE_ON equ 1
SETPANPOSITION16_ON equ 1
RETRIG_ON equ 1
NOTECUT_ON equ 1
NOTEDELAY_ON equ 1
PATTERNDELAY_ON equ 1
PORTAUP_OR_DOWN_ON equ 1
VIBRATO_OR_VOLSLIDE equ 1
VIBRATO_OR_TREMOLO equ 1
PORTATO_OR_VOLSLIDE equ 1
VOLUME_OR_PANENVELOPE equ 1
ROWCOMMANDS_ON equ 1
FINEVOLUMESLIDE_ON equ 1
/programs/develop/libraries/ufmod/fasm.asm
0,0 → 1,342
; FASM.ASM
; --------
; uFMOD public source code release. Provided as-is.
 
; *** This stub allows compiling uFMOD sources using FASM.
 
; *** CONSTANTS ***
 
if UF_FREQ eq 44100
FSOUND_MixRate = 44100
FREQ_40HZ_p = 1DB8Bh
FREQ_40HZ_f = 3B7160h
PCM_format = 3 ; PCM_2_16_44
else
if UF_FREQ eq 22050
FSOUND_MixRate = 22050
FREQ_40HZ_p = 3B716h
FREQ_40HZ_f = 76E2C0h
PCM_format = 9 ; PCM_2_16_22
else
if UF_FREQ eq 48000
else
display 'UF_FREQ not specified (defaulting to 48KHz)',13,10
end if
FSOUND_MixRate = 48000
FREQ_40HZ_p = 1B4E8h
FREQ_40HZ_f = 369D00h
PCM_format = 1 ; PCM_2_16_48
end if
end if
 
if UF_RAMP eq NONE
RAMP_NONE = 1
RAMP_WEAK = 0
RAMP_STRONG = 0
else
if UF_RAMP eq WEAK
RAMP_NONE = 0
RAMP_WEAK = 1
RAMP_STRONG = 0
else
if UF_RAMP eq STRONG
else
display 'UF_RAMP not specified (defaulting to STRONG)',13,10
end if
RAMP_NONE = 0
RAMP_WEAK = 0
RAMP_STRONG = 1
end if
end if
 
UCODE equ 0
 
if UF_MODE eq UNSAFE
display 'WARNING! Unsafe mod is ON. Library may crash while loading damaged XM tracks!',13,10
CHK4VALIDITY = 0
AC97SND_ON = 0
else
CHK4VALIDITY = 1
if UF_MODE eq AC97SND
AC97SND_ON = 1
else
AC97SND_ON = 0
end if
end if
 
if NOLINKER
else
format MS COFF
section '.text' code readable executable
end if
 
; *** STRUCTS ***
 
; Sample type - contains info on sample
struc FSOUND_SAMPLE{
 
; Don't change order .:.
._length dd ? ; sample length
.loopstart dd ? ; loop start
.looplen dd ? ; loop length
.defvol db ? ; default volume
.finetune db ? ; finetune value from -128 to 127
.bytes db ? ; type [b 0-1] : 0 - no loop
; 1 - forward loop
; 2 - bidirectional loop (aka ping-pong)
; [b 4] : 0 - 8-bit sample data
; 1 - 16-bit sample data
.defpan db ? ; default pan value from 0 to 255
.relative db ? ; relative note (signed value)
.Resved db ? ; reserved, known values: 00h - regular delta packed sample data
; ADh - ModPlug 4-bit ADPCM packed sample data
; .:.
 
.loopmode db ?
._align db ?
.buff db ?,? ; sound data
}
virtual at 0
FSOUND_SAMPLE FSOUND_SAMPLE
FSOUND_SAMPLE_size = $-FSOUND_SAMPLE
end virtual
 
 
; Channel type - contains information on a mixing channel
struc FSOUND_CHANNEL{
.actualvolume dd ? ; driver level current volume
.actualpan dd ? ; driver level panning value
.fsampleoffset dd ? ; sample offset (sample starts playing from here)
.leftvolume dd ? ; mixing information. adjusted volume for left channel (panning involved)
.rightvolume dd ? ; mixing information. adjusted volume for right channel (panning involved)
.mixpos dd ? ; mixing information. high part of 32:32 fractional position in sample
.speedlo dd ? ; mixing information. playback rate - low part fractional
.speedhi dd ? ; mixing information. playback rate - high part fractional
.ramp_lefttarget dw ?
.ramp_righttarget dw ?
.ramp_leftspeed dd ?
.ramp_rightspeed dd ?
 
; Don't change order .:.
.fsptr dd ? ; pointer to FSOUND_SAMPLE currently playing sample
.mixposlo dd ? ; mixing information. low part of 32:32 fractional position in sample
.ramp_leftvolume dd ?
.ramp_rightvolume dd ?
.ramp_count dw ?
.speeddir db ?,? ; mixing information. playback direction - forwards or backwards
; .:.
 
}
virtual at 0
FSOUND_CHANNEL FSOUND_CHANNEL
FSOUND_CHANNEL_size = $-FSOUND_CHANNEL
end virtual
 
; Single note type - contains info on 1 note in a pattern
struc FMUSIC_NOTE{
.unote db ? ; note to play at (0-97) 97=keyoff
.number db ? ; sample being played (0-128)
.uvolume db ? ; volume column value (0-64) 255=no volume
.effect db ? ; effect number (0-1Ah)
.eparam db ? ; effect parameter (0-255)
}
virtual at 0
FMUSIC_NOTE FMUSIC_NOTE
FMUSIC_NOTE_size = $-FMUSIC_NOTE
end virtual
 
; Pattern data type
struc FMUSIC_PATTERN{
.rows dw ?
.patternsize dw ?
.data dd ? ; pointer to FMUSIC_NOTE
}
virtual at 0
FMUSIC_PATTERN FMUSIC_PATTERN
FMUSIC_PATTERN_size = $-FMUSIC_PATTERN
end virtual
 
; Multi sample extended instrument
struc FMUSIC_INSTRUMENT{
.sample rd 16 ; 16 pointers to FSOUND_SAMPLE per instrument
 
; Don't change order .:.
.keymap rb 96 ; sample keymap assignments
.VOLPoints rw 24 ; volume envelope points
.PANPoints rw 24 ; panning envelope points
.VOLnumpoints db ? ; number of volume envelope points
.PANnumpoints db ? ; number of panning envelope points
.VOLsustain db ? ; volume sustain point
.VOLLoopStart db ? ; volume envelope loop start
.VOLLoopEnd db ? ; volume envelope loop end
.PANsustain db ? ; panning sustain point
.PANLoopStart db ? ; panning envelope loop start
.PANLoopEnd db ? ; panning envelope loop end
.VOLtype db ? ; type of envelope,bit 0:On 1:Sustain 2:Loop
.PANtype db ? ; type of envelope,bit 0:On 1:Sustain 2:Loop
.VIBtype db ? ; instrument vibrato type
.VIBsweep db ? ; time it takes for vibrato to fully kick in
.iVIBdepth db ? ; depth of vibrato
.VIBrate db ? ; rate of vibrato
.VOLfade dw ? ; fade out value
; .:.
 
}
virtual at 0
FMUSIC_INSTRUMENT FMUSIC_INSTRUMENT
FMUSIC_INSTRUMENT_size = $-FMUSIC_INSTRUMENT
end virtual
 
; Channel type - contains information on a mod channel
struc FMUSIC_CHANNEL{
.note db ? ; last note set in channel
.samp db ? ; last sample set in channel
.notectrl db ? ; flags for DoFlags proc
.inst db ? ; last instrument set in channel
.cptr dd ? ; pointer to FSOUND_CHANNEL system mixing channel
.freq dd ? ; current mod frequency period for this channel
.volume dd ? ; current mod volume for this channel
.voldelta dd ? ; delta for volume commands... tremolo/tremor, etc
.freqdelta dd ? ; delta for frequency commands... vibrato/arpeggio, etc
.pan dd ? ; current mod pan for this channel
 
; Don't change order .:.
.envvoltick dd ? ; tick counter for envelope position
.envvolpos dd ? ; envelope position
.envvoldelta dd ? ; delta step between points
.envpantick dd ? ; tick counter for envelope position
.envpanpos dd ? ; envelope position
.envpandelta dd ? ; delta step between points
.ivibsweeppos dd ? ; instrument vibrato sweep position
.ivibpos dd ? ; instrument vibrato position
.keyoff db ?,? ; flag whether keyoff has been hit or not
.envvolstopped db ? ; flag to say whether envelope has finished or not
.envpanstopped db ? ; flag to say whether envelope has finished or not
; .:.
 
.envvolfrac dd ? ; fractional interpolated envelope volume
.envvol dd ? ; final interpolated envelope volume
.fadeoutvol dd ? ; volume fade out
.envpanfrac dd ? ; fractional interpolated envelope pan
.envpan dd ? ; final interpolated envelope pan
.period dd ? ; last period set in channel
.sampleoffset dd ? ; sample offset for this channel in SAMPLES
.portatarget dd ? ; note to porta to
.patloopno db ?,?,?,? ; pattern loop variables for effect E6x
.patlooprow dd ?
.realnote db ? ; last realnote set in channel
.recenteffect db ? ; previous row's effect... used to correct tremolo volume
.portaupdown db ? ; last porta up/down value
db ? ; unused
.xtraportadown db ? ; last porta down value
.xtraportaup db ? ; last porta up value
.volslide db ? ; last volume slide value
.panslide db ? ; pan slide parameter
.retrigx db ? ; last retrig volume slide used
.retrigy db ? ; last retrig tick count used
.portaspeed db ? ; porta speed
.vibpos db ? ; vibrato position
.vibspeed db ? ; vibrato speed
.vibdepth db ? ; vibrato depth
.tremolopos db ? ; tremolo position
.tremolospeed db ? ; tremolo speed
.tremolodepth db ? ; tremolo depth
.tremorpos db ? ; tremor position
.tremoron db ? ; remembered parameters for tremor
.tremoroff db ? ; remembered parameters for tremor
.wavecontrol db ? ; waveform type for vibrato and tremolo (4bits each)
.finevslup db ? ; parameter for fine volume slide down
.fineportaup db ? ; parameter for fine porta slide up
.fineportadown db ? ; parameter for fine porta slide down
}
virtual at 0
FMUSIC_CHANNEL FMUSIC_CHANNEL
FMUSIC_CHANNEL_size = $-FMUSIC_CHANNEL
end virtual
 
; Song type - contains info on song
struc FMUSIC_MODULE{
 
; Don't change order .:.
.pattern dd ? ; pointer to FMUSIC_PATTERN array for this song
.instrument dd ? ; pointer to FMUSIC_INSTRUMENT array for this song
.mixer_samplesleft dd ?
.globalvolume dd ? ; global mod volume
.tick dd ? ; current mod tick
.speed dd ? ; speed of song in ticks per row
.order dd ? ; current song order position
.row dd ? ; current row in pattern
.patterndelay dd ? ; pattern delay counter
.nextorder dd ? ; current song order position
.nextrow dd ? ; current row in pattern
.unused1 dd ?
.numchannels dd ? ; number of channels
.Channels dd ? ; channel pool
.uFMOD_Ch dd ? ; channel array for this song
.mixer_samplespertick dd ?
.numorders dw ? ; number of orders (song length)
.restart dw ? ; restart position
.numchannels_xm db ?
.globalvsl db ? ; global mod volume
.numpatternsmem dw ? ; number of allocated patterns
.numinsts dw ? ; number of instruments
.flags dw ? ; flags such as linear frequency, format specific quirks, etc
.defaultspeed dw ?
.defaultbpm dw ?
.orderlist rb 256 ; pattern playing order list
; .:.
 
}
virtual at 0
FMUSIC_MODULE FMUSIC_MODULE
FMUSIC_MODULE_size = $-FMUSIC_MODULE
end virtual
 
OFFSET equ
PTR equ
endif equ end if
 
include 'ufmod.asm'
include 'core.asm'
 
if NOLINKER
uFMOD_IMG_END: ; End of uFMOD's code. BSS follows.
align 16
else
section '.bss' readable writeable align 16
end if
 
; Don't change order!
_mod rb FMUSIC_MODULE_size ; currently playing track
mmt rd 3
ufmod_heap dd ?
dd ? ; unused
if AC97SND_ON
extrn hSound
dd ?
else
hSound dd ?
endif
hBuff dd ?
SW_Exit dd ?
; mix buffer memory block (align 16!)
MixBuf rb FSOUND_BlockSize*8
ufmod_noloop db ?
ufmod_pause_ db ?
mix_endflag rb 2
mmf rd 4
ufmod_vol dd ? ; global volume scale
; * LPCALLBACKS *
uFMOD_fopen dd ?
uFMOD_fread dd ?
file_struct rd 7
cache_offset dd ?
if INFO_API_ON
time_ms dd ?
L_vol dw ? ; L channel RMS volume
R_vol dw ? ; R channel RMS volume
s_row dw ?
s_order dw ?
szTtl rb 24
end if
DummySamp rb FSOUND_SAMPLE_size
/programs/develop/libraries/ufmod/makeobj.bat
0,0 → 1,68
@echo off
rem Make the uFMOD libraries in COFF object format
rem Target OS: KolibriOS
 
rem *** CONFIG START
rem *** Check the Readme docs for a complete reference
rem *** on configuring the following options
 
rem Pathes:
SET UF_MASM=\masm32\bin
SET UF_NASM=\nasm
SET UF_FASM=\fasm
 
rem Select compiler: MASM, NASM or FASM
SET UF_ASM=FASM
 
rem Select mixing rate: 22050, 44100 or 48000 (22.05 KHz, 44.1 KHz or 48 KHz)
SET UF_FREQ=48000
 
rem Set volume ramping mode (interpolation): NONE, WEAK or STRONG
SET UF_RAMP=STRONG
 
rem Set build mode: NORMAL, UNSAFE or AC97SND
SET UF_MODE=NORMAL
rem *** CONFIG END
 
if %UF_ASM%==MASM goto MASM
if %UF_ASM%==NASM goto NASM
if %UF_ASM%==FASM goto FASM
echo %UF_ASM% not supported
goto TheEnd
 
:MASM
if not exist "%UF_MASM%\ml.exe" goto Err1
"%UF_MASM%\ml" /c /coff /nologo /Df%UF_FREQ% /D%UF_RAMP% /D%UF_MODE% /Fo ufmod.obj src\masm.asm
goto TheEnd
 
:NASM
if not exist "%UF_NASM%\nasmw.exe" goto Err2
"%UF_NASM%\nasmw" -O4 -t -fwin32 -dNODEBUG -df%UF_FREQ% -d%UF_RAMP% -d%UF_MODE% -isrc\ -oufmod.obj src\nasm.asm
goto TheEnd
 
:FASM
if not exist "%UF_FASM%\fasm.exe" goto Err3
echo UF_FREQ equ %UF_FREQ% >tmp.asm
echo UF_RAMP equ %UF_RAMP% >>tmp.asm
echo UF_MODE equ %UF_MODE% >>tmp.asm
echo DEBUG equ 0 >>tmp.asm
echo NOLINKER equ 0 >>tmp.asm
echo include 'src\eff.inc' >>tmp.asm
echo include 'src\fasm.asm' >>tmp.asm
"%UF_FASM%\fasm" tmp.asm ufmod.obj
del tmp.asm
goto TheEnd
 
:Err1
echo Couldn't find ml.exe in %UF_MASM%\
goto TheEnd
:Err2
echo Couldn't find nasmw.exe in %UF_NASM%\
goto TheEnd
:Err3
echo Couldn't find fasm.exe in %UF_FASM%\
 
:TheEnd
pause
@echo on
cls
/programs/develop/libraries/ufmod/masm.asm
0,0 → 1,270
; MASM.ASM
; --------
; uFMOD public source code release. Provided as-is.
 
; *** This stub allows compiling uFMOD sources using MASM32.
 
.386
.model flat
 
ifdef f44100
FSOUND_MixRate = 44100
FREQ_40HZ_p = 1DB8Bh
FREQ_40HZ_f = 3B7160h
PCM_format = 3
else
ifdef f22050
FSOUND_MixRate = 22050
FREQ_40HZ_p = 3B716h
FREQ_40HZ_f = 76E2C0h
PCM_format = 9
else
ifndef f48000
echo UF_FREQ not specified (defaulting to 48KHz)
endif
FSOUND_MixRate = 48000
FREQ_40HZ_p = 1B4E8h
FREQ_40HZ_f = 369D00h
PCM_format = 1
endif
endif
 
RAMP_NONE = 0
RAMP_WEAK = 0
RAMP_STRONG = 0
ifdef NONE
RAMP_NONE = 1
else
ifdef WEAK
RAMP_WEAK = 1
else
ifndef STRONG
echo UF_RAMP not specified (defaulting to STRONG)
endif
RAMP_STRONG = 1
endif
endif
 
UCODE = 0
DEBUG = 0
 
CHK4VALIDITY = 1
ifdef UNSAFE
echo WARNING! Unsafe mod is ON. Library may crash while loading damaged XM tracks!
CHK4VALIDITY = 0
endif
 
AC97SND_ON = 0
ifdef AC97SND
AC97SND_ON = 1
endif
 
include eff.inc
 
FSOUND_SAMPLE STRUC
_length dd ?
loopstart dd ?
looplen dd ?
defvol db ?
finetune db ?
bytes db ?
defpan db ?
relative db ?
Resved db ?
loopmode db ?
_align db ?
buff db ?,?
FSOUND_SAMPLE ENDS
 
FSOUND_CHANNEL STRUC
actualvolume dd ?
actualpan dd ?
fsampleoffset dd ?
leftvolume dd ?
rightvolume dd ?
mixpos dd ?
speedlo dd ?
speedhi dd ?
ramp_lefttarget dw ?
ramp_righttarget dw ?
ramp_leftspeed dd ?
ramp_rightspeed dd ?
fsptr dd ?
mixposlo dd ?
ramp_leftvolume dd ?
ramp_rightvolume dd ?
ramp_count dw ?
speeddir db ?,?
FSOUND_CHANNEL ENDS
 
FMUSIC_NOTE STRUC
unote db ?
number db ?
uvolume db ?
effect db ?
eparam db ?
FMUSIC_NOTE ENDS
 
FMUSIC_PATTERN STRUC
rows dw ?
patternsize dw ?
data dd ?
FMUSIC_PATTERN ENDS
 
FMUSIC_INSTRUMENT STRUC
sample dd 16 dup (?)
keymap db 96 dup (?)
VOLPoints dw 24 dup (?)
PANPoints dw 24 dup (?)
VOLnumpoints db ?
PANnumpoints db ?
VOLsustain db ?
VOLLoopStart db ?
VOLLoopEnd db ?
PANsustain db ?
PANLoopStart db ?
PANLoopEnd db ?
VOLtype db ?
PANtype db ?
VIBtype db ?
VIBsweep db ?
iVIBdepth db ?
VIBrate db ?
VOLfade dw ?
FMUSIC_INSTRUMENT ENDS
 
FMUSIC_CHANNEL STRUC
note db ?
samp db ?
notectrl db ?
inst db ?
cptr dd ?
freq dd ?
volume dd ?
voldelta dd ?
freqdelta dd ?
pan dd ?
envvoltick dd ?
envvolpos dd ?
envvoldelta dd ?
envpantick dd ?
envpanpos dd ?
envpandelta dd ?
ivibsweeppos dd ?
ivibpos dd ?
keyoff db ?,?
envvolstopped db ?
envpanstopped db ?
envvolfrac dd ?
envvol dd ?
fadeoutvol dd ?
envpanfrac dd ?
envpan dd ?
period dd ?
sampleoffset dd ?
portatarget dd ?
patloopno db ?,?,?,?
patlooprow dd ?
realnote db ?
recenteffect db ?
portaupdown db ?
db ?
xtraportadown db ?
xtraportaup db ?
volslide db ?
panslide db ?
retrigx db ?
retrigy db ?
portaspeed db ?
vibpos db ?
vibspeed db ?
vibdepth db ?
tremolopos db ?
tremolospeed db ?
tremolodepth db ?
tremorpos db ?
tremoron db ?
tremoroff db ?
wavecontrol db ?
finevslup db ?
fineportaup db ?
fineportadown db ?
FMUSIC_CHANNEL ENDS
 
FMUSIC_MODULE STRUC
pattern dd ?
instrument dd ?
mixer_samplesleft dd ?
globalvolume dd ?
tick dd ?
speed dd ?
order dd ?
row dd ?
patterndelay dd ?
nextorder dd ?
nextrow dd ?
unused1 dd ?
numchannels dd ?
Channels dd ?
uFMOD_Ch dd ?
mixer_samplespertick dd ?
numorders dw ?
restart dw ?
numchannels_xm db ?
globalvsl db ?
numpatternsmem dw ?
numinsts dw ?
flags dw ?
defaultspeed dw ?
defaultbpm dw ?
orderlist db 256 dup (?)
FMUSIC_MODULE ENDS
 
FMUSIC_MODULE_size = SIZE FMUSIC_MODULE
FSOUND_CHANNEL_size = SIZE FSOUND_CHANNEL
FMUSIC_CHANNEL_size = SIZE FMUSIC_CHANNEL
FMUSIC_INSTRUMENT_size = SIZE FMUSIC_INSTRUMENT
FMUSIC_PATTERN_size = SIZE FMUSIC_PATTERN
FMUSIC_NOTE_size = SIZE FMUSIC_NOTE
 
; FPU register stack
st0 TEXTEQU <st(0)>
st1 TEXTEQU <st(1)>
 
.CODE
include ufmod.asm
include core.asm
 
.DATA?
_mod = $
FMUSIC_MODULE<>
mmt dd ?,?,?
ufmod_heap dd ?,?
if AC97SND_ON
EXTERN hSound:DWORD
dd ?
else
hSound dd ?
endif
hBuff dd ?
SW_Exit dd ?
MixBuf db FSOUND_BlockSize*8 dup (?)
ufmod_noloop db ?
ufmod_pause_ db ?
mix_endflag db ?,?
mmf dd ?,?,?,?
ufmod_vol dd ?
uFMOD_fopen dd ?
uFMOD_fread dd ?
file_struct dd 7 dup (?)
cache_offset dd ?
if INFO_API_ON
time_ms dd ?
L_vol dw ?
R_vol dw ?
s_row dw ?
s_order dw ?
szTtl db 24 dup (?)
endif
DummySamp FSOUND_SAMPLE<>
end
/programs/develop/libraries/ufmod/media/BLITZXMK.XM
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/develop/libraries/ufmod/media/blitz.eff.inc
0,0 → 1,60
; XM-file: BLITZXMK.XM
 
; uFMOD optional features:
INFO_API_ON equ 0 ; disable InfoAPI
NOLOOP_ON equ 0 ; disable XM_NOLOOP
PAUSE_RESUME_ON equ 1 ; enable pause/resume and XM_SUSPENDED
VOL_CONTROL_ON equ 0 ; disable volume control
JUMP_TO_PAT_ON equ 1 ; enable Jump2Pattern
XM_FILE_ON equ 0 ; disable file loading
 
; Special flags:
INSTRUMENTVIBRATO_ON equ 1
VOLUMEENVELOPE_ON equ 1
PANENVELOPE_ON equ 0
VOLUMEBYTE_ON equ 1
ADPCM_ON equ 0
AMIGAPERIODS_ON equ 0
 
; XM effects:
ARPEGGIO_ON equ 0
PORTAUP_ON equ 0
PORTADOWN_ON equ 0
PORTATO_ON equ 1
VIBRATO_ON equ 1
PORTATOVOLSLIDE_ON equ 0
VIBRATOVOLSLIDE_ON equ 0
TREMOLO_ON equ 0
SETPANPOSITION_ON equ 0
SETSAMPLEOFFSET_ON equ 0
VOLUMESLIDE_ON equ 0
PATTERNJUMP_ON equ 1
SETVOLUME_ON equ 0
PATTERNBREAK_ON equ 0
SETSPEED_ON equ 1
SETGLOBALVOLUME_ON equ 0
GLOBALVOLSLIDE_ON equ 0
KEYOFF_ON equ 0
SETENVELOPEPOS_ON equ 0
PANSLIDE_ON equ 0
MULTIRETRIG_ON equ 0
TREMOR_ON equ 0
EXTRAFINEPORTA_ON equ 0
FINEPORTAUP_ON equ 0
FINEPORTADOWN_ON equ 0
SETVIBRATOWAVE_ON equ 0
SETFINETUNE_ON equ 0
PATTERNLOOP_ON equ 0
SETTREMOLOWAVE_ON equ 0
SETPANPOSITION16_ON equ 0
RETRIG_ON equ 0
NOTECUT_ON equ 1
NOTEDELAY_ON equ 1
PATTERNDELAY_ON equ 0
PORTAUP_OR_DOWN_ON equ 0
VIBRATO_OR_VOLSLIDE equ 1
VIBRATO_OR_TREMOLO equ 1
PORTATO_OR_VOLSLIDE equ 1
VOLUME_OR_PANENVELOPE equ 1
ROWCOMMANDS_ON equ 1
FINEVOLUMESLIDE_ON equ 0
/programs/develop/libraries/ufmod/media/mini.eff.inc
0,0 → 1,60
; XM-file: mini.xm
 
; uFMOD optional features:
INFO_API_ON equ 0 ; disable InfoAPI
NOLOOP_ON equ 0 ; disable XM_NOLOOP
PAUSE_RESUME_ON equ 0 ; disable pause/resume and XM_SUSPENDED
VOL_CONTROL_ON equ 0 ; disable volume control
JUMP_TO_PAT_ON equ 0 ; disable Jump2Pattern
XM_FILE_ON equ 0 ; disable file loading
 
; Special flags:
INSTRUMENTVIBRATO_ON equ 0
VOLUMEENVELOPE_ON equ 1
PANENVELOPE_ON equ 0
VOLUMEBYTE_ON equ 0
ADPCM_ON equ 0
AMIGAPERIODS_ON equ 0
 
; XM effects:
ARPEGGIO_ON equ 0
PORTAUP_ON equ 0
PORTADOWN_ON equ 0
PORTATO_ON equ 0
VIBRATO_ON equ 0
PORTATOVOLSLIDE_ON equ 0
VIBRATOVOLSLIDE_ON equ 0
TREMOLO_ON equ 0
SETPANPOSITION_ON equ 0
SETSAMPLEOFFSET_ON equ 0
VOLUMESLIDE_ON equ 1
PATTERNJUMP_ON equ 0
SETVOLUME_ON equ 0
PATTERNBREAK_ON equ 0
SETSPEED_ON equ 0
SETGLOBALVOLUME_ON equ 0
GLOBALVOLSLIDE_ON equ 0
KEYOFF_ON equ 0
SETENVELOPEPOS_ON equ 0
PANSLIDE_ON equ 0
MULTIRETRIG_ON equ 0
TREMOR_ON equ 0
EXTRAFINEPORTA_ON equ 0
FINEPORTAUP_ON equ 0
FINEPORTADOWN_ON equ 0
SETVIBRATOWAVE_ON equ 0
SETFINETUNE_ON equ 0
PATTERNLOOP_ON equ 1
SETTREMOLOWAVE_ON equ 0
SETPANPOSITION16_ON equ 0
RETRIG_ON equ 0
NOTECUT_ON equ 0
NOTEDELAY_ON equ 0
PATTERNDELAY_ON equ 0
PORTAUP_OR_DOWN_ON equ 0
VIBRATO_OR_VOLSLIDE equ 0
VIBRATO_OR_TREMOLO equ 0
PORTATO_OR_VOLSLIDE equ 0
VOLUME_OR_PANENVELOPE equ 1
ROWCOMMANDS_ON equ 1
FINEVOLUMESLIDE_ON equ 0
/programs/develop/libraries/ufmod/media/mini.xm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/develop/libraries/ufmod/media
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/develop/libraries/ufmod/nasm.asm
0,0 → 1,278
; NASM.ASM
; --------
; uFMOD public source code release. Provided as-is.
 
; *** This stub allows compiling uFMOD sources using NASM.
; Everything documented in fasm stub!
 
; %error directive in NASM causes multiple prompts to appear due to
; multiple passes :( So, we'd better avoid using %error.
 
ifdef f44100
FSOUND_MixRate equ 44100
FREQ_40HZ_p equ 1DB8Bh
FREQ_40HZ_f equ 3B7160h
PCM_format equ 3
else
ifdef f22050
FSOUND_MixRate equ 22050
FREQ_40HZ_p equ 3B716h
FREQ_40HZ_f equ 76E2C0h
PCM_format equ 9
else
FSOUND_MixRate equ 48000
FREQ_40HZ_p equ 1B4E8h
FREQ_40HZ_f equ 369D00h
PCM_format equ 1
endif
endif
 
ifdef NONE
RAMP_NONE equ 1
RAMP_WEAK equ 0
RAMP_STRONG equ 0
else
ifdef WEAK
RAMP_NONE equ 0
RAMP_WEAK equ 1
RAMP_STRONG equ 0
else
RAMP_NONE equ 0
RAMP_WEAK equ 0
RAMP_STRONG equ 1
endif
endif
 
UCODE equ 0
 
ifdef NODEBUG
DEBUG equ 0
else
DEBUG equ 1
endif
 
ifdef UNSAFE
CHK4VALIDITY equ 0
AC97SND_ON equ 0
else
CHK4VALIDITY equ 1
ifdef AC97SND
AC97SND_ON equ 1
else
AC97SND_ON equ 0
endif
endif
 
ifndef NOLINKER
%include "eff.inc"
 
[segment .text align=4]
endif
 
STRUC FSOUND_SAMPLE
FSOUND_SAMPLE._length resd 1
FSOUND_SAMPLE.loopstart resd 1
FSOUND_SAMPLE.looplen resd 1
FSOUND_SAMPLE.defvol resb 1
FSOUND_SAMPLE.finetune resb 1
FSOUND_SAMPLE.bytes resb 1
FSOUND_SAMPLE.defpan resb 1
FSOUND_SAMPLE.relative resb 1
FSOUND_SAMPLE.Resved resb 1
FSOUND_SAMPLE.loopmode resb 1
FSOUND_SAMPLE._align resb 1
FSOUND_SAMPLE.buff resb 2
ENDSTRUC
 
STRUC FSOUND_CHANNEL
FSOUND_CHANNEL.actualvolume resd 1
FSOUND_CHANNEL.actualpan resd 1
FSOUND_CHANNEL.fsampleoffset resd 1
FSOUND_CHANNEL.leftvolume resd 1
FSOUND_CHANNEL.rightvolume resd 1
FSOUND_CHANNEL.mixpos resd 1
FSOUND_CHANNEL.speedlo resd 1
FSOUND_CHANNEL.speedhi resd 1
FSOUND_CHANNEL.ramp_lefttarget resw 1
FSOUND_CHANNEL.ramp_righttarget resw 1
FSOUND_CHANNEL.ramp_leftspeed resd 1
FSOUND_CHANNEL.ramp_rightspeed resd 1
FSOUND_CHANNEL.fsptr resd 1
FSOUND_CHANNEL.mixposlo resd 1
FSOUND_CHANNEL.ramp_leftvolume resd 1
FSOUND_CHANNEL.ramp_rightvolume resd 1
FSOUND_CHANNEL.ramp_count resw 1
FSOUND_CHANNEL.speeddir resb 2
ENDSTRUC
 
STRUC FMUSIC_NOTE
FMUSIC_NOTE.unote resb 1
FMUSIC_NOTE.number resb 1
FMUSIC_NOTE.uvolume resb 1
FMUSIC_NOTE.effect resb 1
FMUSIC_NOTE.eparam resb 1
ENDSTRUC
 
STRUC FMUSIC_PATTERN
FMUSIC_PATTERN.rows resw 1
FMUSIC_PATTERN.patternsize resw 1
FMUSIC_PATTERN.data resd 1
ENDSTRUC
 
STRUC FMUSIC_INSTRUMENT
FMUSIC_INSTRUMENT.sample resd 16
FMUSIC_INSTRUMENT.keymap resb 96
FMUSIC_INSTRUMENT.VOLPoints resw 24
FMUSIC_INSTRUMENT.PANPoints resw 24
FMUSIC_INSTRUMENT.VOLnumpoints resb 1
FMUSIC_INSTRUMENT.PANnumpoints resb 1
FMUSIC_INSTRUMENT.VOLsustain resb 1
FMUSIC_INSTRUMENT.VOLLoopStart resb 1
FMUSIC_INSTRUMENT.VOLLoopEnd resb 1
FMUSIC_INSTRUMENT.PANsustain resb 1
FMUSIC_INSTRUMENT.PANLoopStart resb 1
FMUSIC_INSTRUMENT.PANLoopEnd resb 1
FMUSIC_INSTRUMENT.VOLtype resb 1
FMUSIC_INSTRUMENT.PANtype resb 1
FMUSIC_INSTRUMENT.VIBtype resb 1
FMUSIC_INSTRUMENT.VIBsweep resb 1
FMUSIC_INSTRUMENT.iVIBdepth resb 1
FMUSIC_INSTRUMENT.VIBrate resb 1
FMUSIC_INSTRUMENT.VOLfade resw 1
ENDSTRUC
 
STRUC FMUSIC_CHANNEL
FMUSIC_CHANNEL.note resb 1
FMUSIC_CHANNEL.samp resb 1
FMUSIC_CHANNEL.notectrl resb 1
FMUSIC_CHANNEL.inst resb 1
FMUSIC_CHANNEL.cptr resd 1
FMUSIC_CHANNEL.freq resd 1
FMUSIC_CHANNEL.volume resd 1
FMUSIC_CHANNEL.voldelta resd 1
FMUSIC_CHANNEL.freqdelta resd 1
FMUSIC_CHANNEL.pan resd 1
FMUSIC_CHANNEL.envvoltick resd 1
FMUSIC_CHANNEL.envvolpos resd 1
FMUSIC_CHANNEL.envvoldelta resd 1
FMUSIC_CHANNEL.envpantick resd 1
FMUSIC_CHANNEL.envpanpos resd 1
FMUSIC_CHANNEL.envpandelta resd 1
FMUSIC_CHANNEL.ivibsweeppos resd 1
FMUSIC_CHANNEL.ivibpos resd 1
FMUSIC_CHANNEL.keyoff resb 2
FMUSIC_CHANNEL.envvolstopped resb 1
FMUSIC_CHANNEL.envpanstopped resb 1
FMUSIC_CHANNEL.envvolfrac resd 1
FMUSIC_CHANNEL.envvol resd 1
FMUSIC_CHANNEL.fadeoutvol resd 1
FMUSIC_CHANNEL.envpanfrac resd 1
FMUSIC_CHANNEL.envpan resd 1
FMUSIC_CHANNEL.period resd 1
FMUSIC_CHANNEL.sampleoffset resd 1
FMUSIC_CHANNEL.portatarget resd 1
FMUSIC_CHANNEL.patloopno resb 4
FMUSIC_CHANNEL.patlooprow resd 1
FMUSIC_CHANNEL.realnote resb 1
FMUSIC_CHANNEL.recenteffect resb 1
FMUSIC_CHANNEL.portaupdown resb 2
FMUSIC_CHANNEL.xtraportadown resb 1
FMUSIC_CHANNEL.xtraportaup resb 1
FMUSIC_CHANNEL.volslide resb 1
FMUSIC_CHANNEL.panslide resb 1
FMUSIC_CHANNEL.retrigx resb 1
FMUSIC_CHANNEL.retrigy resb 1
FMUSIC_CHANNEL.portaspeed resb 1
FMUSIC_CHANNEL.vibpos resb 1
FMUSIC_CHANNEL.vibspeed resb 1
FMUSIC_CHANNEL.vibdepth resb 1
FMUSIC_CHANNEL.tremolopos resb 1
FMUSIC_CHANNEL.tremolospeed resb 1
FMUSIC_CHANNEL.tremolodepth resb 1
FMUSIC_CHANNEL.tremorpos resb 1
FMUSIC_CHANNEL.tremoron resb 1
FMUSIC_CHANNEL.tremoroff resb 1
FMUSIC_CHANNEL.wavecontrol resb 1
FMUSIC_CHANNEL.finevslup resb 1
FMUSIC_CHANNEL.fineportaup resb 1
FMUSIC_CHANNEL.fineportadown resb 1
ENDSTRUC
 
STRUC FMUSIC_MODULE
FMUSIC_MODULE.pattern resd 1
FMUSIC_MODULE.instrument resd 1
FMUSIC_MODULE.mixer_samplesleft resd 1
FMUSIC_MODULE.globalvolume resd 1
FMUSIC_MODULE.tick resd 1
FMUSIC_MODULE.speed resd 1
FMUSIC_MODULE.order resd 1
FMUSIC_MODULE.row resd 1
FMUSIC_MODULE.patterndelay resd 1
FMUSIC_MODULE.nextorder resd 1
FMUSIC_MODULE.nextrow resd 1
FMUSIC_MODULE.unused1 resd 1
FMUSIC_MODULE.numchannels resd 1
FMUSIC_MODULE.Channels resd 1
FMUSIC_MODULE.uFMOD_Ch resd 1
FMUSIC_MODULE.mixer_samplespertick resd 1
FMUSIC_MODULE.numorders resw 1
FMUSIC_MODULE.restart resw 1
FMUSIC_MODULE.numchannels_xm resb 1
FMUSIC_MODULE.globalvsl resb 1
FMUSIC_MODULE.numpatternsmem resw 1
FMUSIC_MODULE.numinsts resw 1
FMUSIC_MODULE.flags resw 1
FMUSIC_MODULE.defaultspeed resw 1
FMUSIC_MODULE.defaultbpm resw 1
FMUSIC_MODULE.orderlist resb 256
ENDSTRUC
 
%macro PUBLIC 1
ifndef NOLINKER
GLOBAL %1
endif
%endmacro
%define OFFSET
%define PTR
 
include "ufmod.asm"
include "core.asm"
 
ifdef NOLINKER
uFMOD_IMG_END: ; End of uFMOD's code. BSS follows.
align 16
[segment .bss]
else
[segment .bss align=16]
endif
 
_mod resb FMUSIC_MODULE_size
mmt resd 3
ufmod_heap resd 2
if AC97SND_ON
extern hSound
resd 1
else
hSound resd 1
endif
hBuff resd 1
SW_Exit resd 1
MixBuf resb FSOUND_BlockSize*8
ufmod_noloop resb 1
ufmod_pause_ resb 1
mix_endflag resb 2
mmf resd 4
ufmod_vol resd 1
uFMOD_fopen resd 1
uFMOD_fread resd 1
file_struct resd 7
cache_offset resd 1
if INFO_API_ON
time_ms resd 1
L_vol resw 1
R_vol resw 1
s_row resw 1
s_order resw 1
szTtl resb 24
endif
DummySamp resb FSOUND_SAMPLE_size
/programs/develop/libraries/ufmod/readme_en.htm
0,0 → 1,34
<html><head><meta http-equiv=Content-Type content="text/html; charset=windows-1251"><title>uFMOD</title></head><body style='margin:0'><table border=0 cellpadding=0 cellspacing=0 width=100%><tr bgcolor=#E7E7E7 align=center><td height=20 style='color:#708090;font-size:9pt;font-family:Arial,Aerial'>[ English | <a href='es.htm'>Espa&#241;ol</a> | <a href='ru.htm'>Pycc&#954;u&#250;</a> ]<tr bgcolor=#708090><td height=1></table><center><h2 style='font-size:14pt;font-family:Arial,Aerial'>&#956;FMOD v1.25 for KolibriOS</h2></center><div style='font-size:10pt;font-family:Arial,Aerial;text-align:justify;margin:8'><p>uFMOD is an XM player library written in assembly language. It's perfect for size- and speed-critical applications, click free, highly reliable, easy to use, open source, multiplatform. File and direct memory playback supported. It is able to play even damaged and non-standard XM tracks. Usage examples available for the following compilers: FASM, MASM32 and NASM.<p>KolibriOS port should run correctly on any PC meeting the following requirements:<ol><li>KolibriOS SVN revision 574 or later. You can download the latest official distro and the SVN binaries from <a href='http://www.kolibrios.org/?&lang=en'>www.kolibrios.org</a>.<li>A sound card supported by the <a href='http://infinity-sound.narod.ru/'>Infinity Sound audio library</a>. It is the default KolibriOS sound driver. Currently it supports many AC'97 compatible sound cards.</ol>If your machine meets the above requirements but uFMOD doesn't run properly, let us know (check the <a href='#ci'>contact information</a> near the bottom of this page).<ul><li><a href='#1'>Getting started</a><li><a href='#2'>Tools</a><ul><li><a href='#21'>XMStrip</a><li><a href='#22'>Eff</a></ul><li><a href='#3'>Compiling the library</a><li><a href='#4'>Examples</a><li><a href='#5'>Reducing the executable file size</a><li><a href='#6'>FAQ</a><li><a href='#7'>Thanks</a></ul><p>&nbsp;<br><a name='1'><b>Getting started</b></a><p>KolibriOS is an operating system written is assembly language. That's why it is so small and extremely fast. It is very powerful as well, as you've probably found out already. That's also uFMOD's spirit ;)<p>Most of the tasks described below can be accomplished directly in Kolibri. However, since many novice Kolibri coders prefer compiling their programs in Windows and then moving them to Kolibri for testing, we'll use crosscompilation here for the sake of universality.<p>&nbsp;<br><a name='2'><b>Tools</b></a><p>There are 2 freeware tools currently available to use along with uFMOD: XMStrip and Eff. None of them has been ported to KolibriOS yet. So, you should pick one of the other platform-specific distros (Win32, Linux or Unix/BSD) and use XMStrip and Eff crossplatformly. No matter which platform-specific version you choose, both utilities have dual interface: terminal and GUI. GUI is rather self-explanatory. Next, we'll explain the terminal interface.<p><table border=0 cellpadding=0 cellspacing=0 bgcolor=#708090 style='font-size:9pt;font-family:Arial,Aerial'><tr><td colspan=3 height=1><tr height=18><td style='color:#E7E7E7'><b>&nbsp;SVN&nbsp;</b><td bgcolor=#E7E7E7>&nbsp;<a href='http://ufmod.svn.sourceforge.net/viewvc/ufmod'>Complete source code available</a>&nbsp;<td width=1><tr><td colspan=3 height=1></table><p><a name='21'><b><i>XMStrip</i></b></a> expects an XM filename on input, repacks the file contents to make it smaller, without losing sound quality. What it does exactly is removing overhead data (dummy instruments, patterns and junk metadata), stripping reserved and currently unused bytes, repacking pattern data. Running <code>xmstrip /h</code> produces the following output:<p><center><table border=0 cellpadding=8><tr bgcolor=#000000><td><pre><font color=#FFFFFF> USAGE: xmstrip [options] file [output]
file - input file name.
output - optional output file name.
options:
/c - clean only (don't strip)
When [output] is not specified, XMSTRIP
attempts to overwrite the input. If file
name contains spaces, enclose it in "".</font></table></center><p>Keep in mind, that other XM players whould probably reject a 'stripped' XM file. The <b>/c</b> option is useful for 'recovering' such a stripped file or just cleaning a regular file intended to be played with any other XM player.<p><a name='22'><b><i>Eff</i></b></a> is useful for advanced users, willing to squeeze every single byte out of their applications. The general idea is to extract only those features you do mean to use in your application, recompile the uFMOD library from source and obtain the smallest possible footprint. Running <code>eff /h</code> requests the following prompt:<p><center><table border=0 cellpadding=8><tr bgcolor=#000000><td><pre><font color=#FFFFFF> USAGE: eff [options] file
file - input file name
options:
/Dm - generate a masm32/tasm dump
/Dd - generate a Pascal (Delphi) dump
/Dc - generate a C/C++ dump
/Ds - generate an RCDATA resource dump
/Di - disable infoAPI:
uFMOD_GetStats, uFMOD_GetRowOrder,
uFMOD_GetTitle and uFMOD_GetTime
/Dp - disable uFMOD_Pause, uFMOD_Resume
and XM_SUSPENDED
/Dv - disable volume control
/Dj - disable Jump2Pattern
/Df - disable loading XM from file
/Dl - disable XM_NOLOOP
/M - mark & clear unused chunks of
+<p>There are currently 2 examples available: mini and jmp2pat. Precompiled executables are located in bin/. None of the executables are packed/compressed.<ul><li><b>mini</b> is the simplest example showing how to play an XM track from memory with proper error handling.<li><b>jmp2pat</b> is a bit more complex example showing how to use the Jump2Pattern feature and pause/resume. It uses a composite XM tracked by Kim (aka norki). For more information on composite XM files and the Jump2Pattern feature, refer to the following section.</ul><p>&nbsp;<br><a name='5'><b>Reducing the executable file size</b></a><p>Use <a href='#22'>Eff</a> to optimize the library and make it smaller.<p>When embedding the XM track directly into the executable or attaching it as a raw binary resource, it's sometimes worth it trying to optimize the XM itself. Modplug Player features ADPCM compression, which makes the XM somewhat smaller, but it's a lossy compression! Use <a href='#22'>XMStrip</a> for lossless (in terms of sound quality) size optimization.<p>If you're sure all XM tracks your application is going to use are valid (not damaged or otherwise modified), rebuild the library in UNSAFE mode.<p>Packers, such as mtappack by diamond, make executables smaller. Anyway, to make things fair, the sample executables are not compressed at all!<p>Let's talk some more about optimizing the XM file size:<p>An advanced XM file size optimization method involves merging various XM tracks in a single composite file. Since you can share the instruments in a composite file, the resulting file size could be a lot smaller than the sum of the separate file sizes before merging. Even without sharing the instruments it will be smaller because of the XM file header being declared only once. Let's see an example with 3 XM files:<pre>
+<b>File 1 :</b> XM1_HEADER P11 P12 P13 I11 I12
+<b>File 2 :</b> XM2_HEADER P21 P22 P23 P24 I21 I22 I23 I24
+<b>File 3 :</b> XM3_HEADER P31 I31
+</pre><i><b>Legend:</b> XMn_HEADER is the header of the n-th XM file. Pni is the i-th pattern of the n-th XM file. Ini is the i-th instrument of the n-th XM file.</i><p>First, let's merge them in a single file without sharing the instruments:<pre>
+<b>File 4 :</b> XM4_HEADER P11 P12 P13 P21 P22 P23 P24 P31 I11 I12 I21 I22 I23 I24 I31
+</pre>Now, let's say I12 is very similar or even equal to I23 and I24 is the same as I31. So, we can modify P2n to make them use I12 instead of I23 and P31 to use I24, so that we can remove I23 and I31:<pre>
+<b>File 4 :</b> XM4_HEADER P11 P12 P13 P21 P22 P23 P24 P31 I11 I12 I21 I22 I24
+</pre>You'll have to modify the looping and pattern jumping commands and the references to instruments in "files" 2 and 3. Obviously, you can merge just 2 files or more than 3. XM file format limits the amount of patterns and instruments in a single file. That's the general idea. You'd have to learn how to use a tracker in order to perform this kind of optimization. Once you've got all your files merged, you can issue a single uFMOD_PlaySong function call and trigger all the "files" with uFMOD_Jump2Pattern. For example, uFMOD_Jump2Pattern(3) will start playing the 2nd "file", uFMOD_Jump2Pattern(7) will launch the 3rd and uFMOD_Jump2Pattern(0) will reset to the first "file". The exact indexes depend on your pattern layout. The <b>jmp2pat</b> example uses this feature.<p>Using Jump2Pattern has another advantage: switching is done much faster (practically in no time), as opposed to stopping and reloading a track. So, you can use this feature when quickly switching the background music is required.<p>&nbsp;<br><a name='6'><b>FAQ</b></a><p><span style='color:#008080'><b>Q:</b> Is uFMOD free for any type of use? Even commercial?</span><br><b>A:</b> Yes, currently it is.<p><span style='color:#008080'><b>Q:</b> Where can I get XM files from?</span><br><b>A:</b> Try visiting <a href='http://modarchive.org/'>The Mod Archive</a>. They have a huge archive of free tracker music in XM, IT, S3M and MOD format. You can use <a href='http://www.modplug.com/'>Open Modplug Tracker</a> to convert IT, S3M and MOD tracks to XM format without apparent degradation. There are many talented composers out there in the web sharing their music at no cost. Just don't forget the copyright!<p><span style='color:#008080'><b>Q:</b> Is uFMOD related in some way to Firelight Technologies&#174; FMOD and miniFMOD sound libraries?</span><br><b>A:</b> Not any more. Up until 2004 uFMOD was based on the latest miniFMOD public source code release. Since then, library sources had been completely rewritten, introducing many new features. So, uFMOD is in no way representative of FMOD and miniFMOD sources.<p><span style='color:#008080'><b>Q:</b> Some XM player libraries claim to add only N kilobytes to the executable file. How many Kb does uFMOD add exactly to the executable's size?</span><br><b>A:</b> It is impossible to tell an exact value, because it depends on library features used (especially, when using the Eff utility), test program code layout, XM file size (when embedding the XM into the executable file). It also depends on the linker options. For example, bin/mini is 4.768 bytes without compression.<p><span style='color:#008080'><b>Q:</b> Where can I get the official XM file format specification from?</span><br><b>A:</b> No official and up to date specification exists. However, you can take a look at <a href='http://sourceforge.net/project/showfiles.php?group_id=158498&package_id=234625'>"The Unofficial XM File Format Specification: FastTracker II, ADPCM and Stripped Module Subformats"</a>. This document covers most aspects of the original XM file format and all the non-standard extensions currently supported by uFMOD. ModePlug's public source code (it's C++) also serves as reference material on module file formats.<p>&nbsp;<br><a name='7'><b>Thanks go out to</b></a><p>antarman, Barracuda, bogrus, chris_b, cresta, dododo, flaith, Four-F, GL#0M, norki, q_q, SofT MANiAC, S_T_A_S_, voodooattack and yoxola for reporting bugs, requesting interesting features, submitting usage examples and otherwise helping us improve uFMOD.<p><a href='http://wasm.ru'>[WASM.RU]</a> and <a href='http://sf.net'>SourceForge.net</a> for support and hosting.<p>&nbsp;<br><b>Copyright</b><p>uFMOD sources, binaries and utility programs &#169; 2005 - 2007 Asterix and Quantum.<br>All rights reserved.<p>Sample tunes:<ul><li>Minimal III &#169; 2006 - 2007 SofT MANiAC (CoolPHat).<li>BlitzXMK.XM from Jump2Pat example &#169; 2007 Kim (aka norki).</ul></div><table border=0 cellpadding=0 cellspacing=0 width=100%><tr bgcolor=#708090><td height=1><tr bgcolor=#E7E7E7><td height=52 style='color:#708090;font-size:10pt;font-family:Arial,Aerial' align=center>Found a bug? Got a question or a suggestion?<br>Starting to develop a cool application using uFMOD? Please, let us know: <a href='mailto:ufmod@users.sf.net' name='ci'>ufmod@users.sf.net</a></table></body></html>
\ No newline at end of file
/programs/develop/libraries/ufmod/readme_es.htm
0,0 → 1,36
<html lang=es><head><meta http-equiv=Content-Type content="text/html; charset=windows-1251"><title>uFMOD</title></head><body style='margin:0'><table border=0 cellpadding=0 cellspacing=0 width=100%><tr bgcolor=#E7E7E7 align=center><td height=20 style='color:#708090;font-size:9pt;font-family:Arial,Aerial'>[ <a href='en.htm'>English</a> | Espa&#241;ol | <a href='ru.htm'>Pycc&#954;u&#250;</a> ]<tr bgcolor=#708090><td height=1></table><center><h2 style='font-size:14pt;font-family:Arial,Aerial'>&#956;FMOD v1.25 para KolibriOS</h2></center><div style='font-size:10pt;font-family:Arial,Aerial;text-align:justify;margin:8'><p>uFMOD es una librer&#237;a para reproducir m&#250;sica en formato XM, desarrollada completamente en lenguaje ensamblador. Es perfecta para aplicaciones de tama&#241;o y tiempo cr&#237;tico, libre de defectos audibles, altamente confiable, f&#225;cil de usar, de c&#243;digo fuente abierto y multiplataforma. Permite reproducir ficheros y arreglos est&#225;ticos en memoria. Es capaz de reproducir inclusive ficheros corruptos y/o modificados. Ejemplos de uso disponibles para los siguientes compiladores: FASM, MASM32 y NASM.<p>La versi&#243;n para KolibriOS debe funcionar en cualquier PC, siempre y cuando se cumplan los siguientes requisitos:<ol><li>KolibriOS revisi&#243;n SVN 574 &#243; posterior. Puede descargar el &#250;ltimo distributivo oficial y las actualizaciones SVN de <a href='http://www.kolibrios.org/?&lang=en'>www.kolibrios.org</a>.<li>Una tarjeta de sonido soportada por la librer&#237;a <a href='http://infinity-sound.narod.ru/'>Infinity Sound</a>. Este controlador de audio viene preinstalado en KolibriOS. Actualmente soporta muchas tarjetas de sonido compatibles con AC'97.</ol>Si su m&#225;quina cumple con dichos requisitos pero uFMOD no funciona correctamente, por favor, rep&#243;rtenos este hecho. (Ver <a href='#ci'>informaci&#243;n de contacto</a> en la parte inferior de esta p&#225;gina.)<p><ul><li><a href='#1'>Antes de comenzar</a><li><a href='#2'>Herramientas</a><ul><li><a href='#21'>XMStrip</a><li><a href='#22'>Eff</a></ul><li><a href='#3'>Compilando la librer&#237;a</a><li><a href='#4'>Ejemplos</a><li><a href='#5'>C&#243;mo lograr un ejecutable m&#225;s compacto</a><li><a href='#6'>Preguntas frecuentes</a><li><a href='#7'>Agradecimientos</a></ul><p>&nbsp;<br><a name='1'><b>Antes de comenzar</b></a><p>KolibriOS es un sistema operativo desarrollado en lenguaje ensamblador. Por eso es tan compacto y r&#225;pido. Adem&#225;s, es bastante vers&#225;til, como probablemente ya se habr&#225; podido dar cuenta. Ese tambi&#233;n es el esp&#237;ritu de uFMOD ;)<p>La mayor parte de los pasos descritos a continuaci&#243;n se puede llevar a cabo dir&#233;ctamente en Kolibri. Sin embargo, como muchos programadores principiantes en Kolibri prefieren compilar sus programas en Windows y luego transferirlos a Kolibri para hacer pruebas, vamos a usar compilaci&#243;n cruzada en esta gu&#237;a en aras de generalizar la metodolog&#237;a.<p>&nbsp;<br><a name='2'><b>Herramientas</b></a><p>Hay 2 herramientas gratuitas para usar con uFMOD: XMStrip y Eff. Ninguna de las dos ha sido portada a KolibriOS a&#250;n. Por lo tanto, se recomienda descargar alguno de los otros distributivos uFMOD (Win32, Linux o Unix/BSD) y usar Eff y XMStrip desde otra plataforma. Sin importar la plataforma elegida, ambas herramientas poseen interfaz de usuario dual: consola y gr&#225;fica (GUI). El modo GUI es bastante intuitivo. Vamos a exponer el modo de consola.<p><table border=0 cellpadding=0 cellspacing=0 bgcolor=#708090 style='font-size:9pt;font-family:Arial,Aerial'><tr><td colspan=3 height=1><tr height=18><td style='color:#E7E7E7'><b>&nbsp;SVN&nbsp;</b><td bgcolor=#E7E7E7>&nbsp;<a href='http://ufmod.svn.sourceforge.net/viewvc/ufmod'>C&#243;digo fuente completo disponible</a>&nbsp;<td width=1><tr><td colspan=3 height=1></table><p><a name='21'><b><i>XMStrip</i></b></a> recibe un fichero XM como entrada, modifica su contenido para minimizar el tama&#241;o, sin que esto afecte la calidad del sonido. Concretamente, XMStrip elimina los datos no utilizados (instrumentos y patrones redundantes, comentarios, etc.) y agrupa los patrones de notas para optimizar el tiempo de lectura y procesamiento del XM. Al ingresar <code>xmstrip /h</code> obtenemos la siguiente respuesta:<p><center><table border=0 cellpadding=8><tr bgcolor=#000000><td><pre><font color=#FFFFFF> USAGE: xmstrip [options] file [output]
file - input file name.
output - optional output file name.
options:
/c - clean only (don't strip)
When [output] is not specified, XMSTRIP
attempts to overwrite the input. If file
name contains spaces, enclose it in "".</font></table></center><p>Si no especifica el nombre del fichero de salida, XMStrip intentar&#225; sobreescribir el fichero de entrada. Si el nombre del fichero contiene espacios, enci&#233;rrelo entre comillas dobles ("").<p>Tenga presente, que otros reproductores de XM, probablemente, rechacen los ficheros producidos por XMStrip. Especifique <b>/c</b> para 'recuperar' un fichero as&#237; o s&#237;mplemente para procesar un fichero normal que desea poder usar en otros reproductores de XM.<p><a name='22'><b><i>Eff</i></b></a> es &#250;til para los usuarios avanzados, que desean ahorrar hasta el &#250;ltimo byte en sus aplicaciones. La idea es extraer s&#243;lo aquellas opciones que realmente se van a usar en la aplicaci&#243;n, recompilar la librer&#237;a uFMOD y obtener el menor tama&#241;o posible. Comencemos abriendo una sesi&#243;n de terminal y escribiendo <code>eff /h</code> para obtener el siguiente res&#250;men:<p><center><table border=0 cellpadding=8><tr bgcolor=#000000><td><pre><font color=#FFFFFF> USAGE: eff [options] file
file - input file name
options:
/Dm - generate a masm32/tasm dump
/Dd - generate a Pascal (Delphi) dump
/Dc - generate a C/C++ dump
/Ds - generate an RCDATA resource dump
/Di - disable infoAPI:
uFMOD_GetStats, uFMOD_GetRowOrder,
uFMOD_GetTitle and uFMOD_GetTime
/Dp - disable uFMOD_Pause, uFMOD_Resume
and XM_SUSPENDED
/Dv - disable volume control
/Dj - disable Jump2Pattern
/Df - disable loading XM from file
/Dl - disable XM_NOLOOP
/M - mark & clear unused chunks of
+ Opciones adicionales:<ul><li><b>/Dm</b> genera un volcado hexadecimal a partir del fichero XM dado, para ser usado en MASM32 o TASM. La sintaxis es compatible con FASM y NASM. Sin embargo, tanto FASM como NASM permiten incluir el contenido de un fichero binario directamente. Es necesario especificar esta opci&#243;n para poder usar <b>/M</b> (ver mas adelante).<li><b>/Dd</b> y <b>/Dc</b> generan volcados para Pascal (Delphi, Kylix, FreePascal) y C/C++ respectivamente.<li><b>/Ds</b> produce un volcado en formato RCDATA, usado en scripts de recursos. No tiene utilidad en KolibriOS.<li>Especifique <b>/Di</b> para deshabilitar todas las funciones informativas: uFMOD_GetStats, uFMOD_GetRowOrder, uFMOD_GetTitle y uFMOD_GetTime. Eliminarlas reduce el tama&#241;o de la librer&#237;a y mejora un poco el rendimiento.<li><b>/Dp</b> elimina las funciones uFMOD_Pause y uFMOD_Resume y hace que uFMOD ignore la bandera XM_SUSPENDED. Si no necesita pausar/reanudar, agregue esta opci&#243;n a la linea de comandos para ahorrar otros tantos bytes.<li>uFMOD_SetVolume no s&#243;lo hace la librer&#237;a m&#225;s grande, sino que tambi&#233;n consume tiempo adicional de CPU. Utilice <b>/Dv</b> para deshabilitar esta funci&#243;n y recuperar algunos bytes y ciclos de reloj ;)<li><b>/Dj</b> deshabilita la funci&#243;n Jump2Pattern. Esta es una funci&#243;n avanzada, no usada en la mayoria de las aplicaciones. Consulte la secci&#243;n <a href='#5'>"C&#243;mo lograr un ejecutable m&#225;s compacto"</a> para mayor informaci&#243;n sobre el uso de Jump2Pattern.<li>&#191;No va a reproducir ficheros - s&#243;lo arreglos est&#225;ticos? Entonces, querr&#225; aprovechar la opci&#243;n <b>/Df</b> para minimizar el tama&#241;o de la librer&#237;a.<li><b>/Dl</b> (L min&#250;scula) hace que la librer&#237;a ignore la bandera XM_NOLOOP (esto tambi&#233;n reduce el tama&#241;o y mejora la eficiencia).<li>Por &#250;ltimo, hay una opci&#243;n de optimizaci&#243;n realmente extrema, disponible s&#243;lo para los programadores en lenguaje ensamblador. En cada fichero XM hay secuencias de bytes que se encuentran reservadas para versiones futuras del formato XM o contienen metadatos (comentarios, publicidad, etc.) <b>/M</b> delimita y resalta estos 'huecos' en el volcado y los habilita para ser usados con mayor utilidad. Por ejemplo, puede almacenar datos y hasta c&#243;digo ejecutable en dichos 'huecos'. El ejemplo src/Masm32/ utiliza esta opci&#243;n.</ul>Si no se presenta error alguno, Eff debe generar un fichero EFF.INC y un volcado hexadecimal, si &#233;ste fue solicitado. Algunos ejemplos (todos son correctos):<p><b>eff /Dmpvjfl /M ejemplo.xm<br>eff /M /Dm /Dp /Dv /Dj /Df /Dl ejemplo.xm<br>eff -M -Dmpvjfl ejemplo.xm</b><p>Cualquiera de estas sentencias produce un volcado en lenguaje ensamblador con todos los 'huecos' delimitados y rellenos con ceros por defecto. El fichero de cabecera EFF.INC recopila los efectos XM que realmente se utilizan en el fichero XM dado, m&#225;s algunas banderas adicionales para deshabilitar las funciones de pausar/reanudar, control de volumen, Jump2Pattern, soporte para ficheros y XM_NOLOOP. Copie EFF.INC en src/ufmodlib/src/ y recompile la librer&#237;a. Consulte la siguiente secci&#243;n para mayor informaci&#243;n sobre c&#243;mo recompilar uFMOD. Acaba de compilar su propia versi&#243;n ultraoptimizada de uFMOD, pero recuerde que &#233;sta contiene un subconjunto de efectos XM. Entonces, &#161;s&#243;lo servir&#225; para reproducir correctamente el fichero XM especificado como par&#225;metro!
+</ul>Una vez terminada la modificaci&#243;n del c&#243;digo fuente, si desea recompilar ufmod.obj, abra el fichero de procesamiento por lotes src/ufmodlib/makeobj.bat en un editor de texto plano. Todo lo contenido entre las siguientes l&#237;neas:<pre>rem *** CONFIG START</pre>y<pre>rem *** CONFIG END</pre>es configurable. Verifique los valores en la secci&#243;n <code>Pathes</code>. Una de las opciones dice:<pre>SET UF_NASM=\nasm</pre>Si Ud. tiene instalado NASM, aseg&#250;rese de que el camino all&#237; especificado apunte exactamente a la ubicaci&#243;n de nasmw.exe. Supongamos que NASM se encuentra instalado en <code>D:\TOOLS\NASM</code>. Entonces, vamos a modificar el camino de la siguiente forma:<pre>SET UF_NASM=D:\TOOLS\NASM</pre>No todos los caminos deben ser configurados correctamente para recompilar la librer&#237;a. Por ejemplo, si Ud. prefiere usar FASM como el ensamblador por defecto, no es necesario configurar el camino de NASM. Aseg&#250;rese de que todos los caminos necesarios para recompilar la librer&#237;a sean correctos. Luego, configure las opciones disponibles, de acuerdo con la siguiente tabla:<p><table border=0 cellpadding=4 cellspacing=2 style='font-size:10pt;font-family:Arial,Aerial'><tr bgcolor=#708090 style='color:#E7E7E7;font-weight:bold'><td>Opci&#243;n<td>Descripci&#243;n<td width=200>Valores disponibles<tr valign=top><td>UF_RAMP<td>Esta opci&#243;n controla el acoplador de vol&#250;men (interpolaci&#243;n). Esto sirve para suprimir cierto tipo de defecto de sonido conocido como clic, com&#250;n en m&#250;sica sintetizada. Sin embargo, la interpolaci&#243;n en algunos casos puede generar distorsi&#243;n. STRONG (fuerte) es el valor por defecto, recomendado para la mayor&#237;a de las aplicaciones. En este modo, el acoplador detecta variaciones de vol&#250;men y las suaviza mediante interpolaci&#243;n lineal de 128 etapas. En modo WEAK (d&#233;bil) hay s&#243;lo 16 etapas. WEAK es menos efectivo que STRONG, pero la probabilidad de distorsi&#243;n tambi&#233;n es menor. NONE deshabilita el acoplador. Si no hay interpolaci&#243;n, no puede haber distorsi&#243;n, pero los clics quedar&#237;an al descubierto, a menos que el contenido del XM se encuentre perfectamente balanceado.<td>NONE, WEAK, STRONG<tr bgcolor=#E7E7E7 valign=top><td>UF_FREQ<td>Frecuencia de muestreo (en Hz). 48KHz es el valor recomendado para la mayor&#237;a de las aplicaciones.<td>22050, 44100, 48000<tr valign=top><td>UF_ASM<td>Ensamblador. La librer&#237;a uFMOD se puede compilar con diferentes ensambladores. Escoja su favorito :)<td>MASM, NASM, FASM<tr bgcolor=#E7E7E7 valign=top><td>UF_MODE<td>NORMAL es el valor por defecto. No tiene nada de especial. UNSAFE deshabilida la comprobaci&#243;n de validez del formato XM a la hora de cargar el fichero. Si Ud. est&#225; seguro de que todos los ficheros XM est&#225;n correctos (puede verificarlos con Eff o con XMStrip), puede recompilar uFMOD en modo UNSAFE para reducir el tama&#241;o de la librer&#237;a y el tiempo de carga. Tenga en cuenta que &#161;Un XM corrupto podr&#237;a ocasionar un fallo en modo UNSAFE! El modo AC97SND hace que ufmod.obj contenga una versi&#243;n especial de la librer&#237;a uFMOD. Esta versi&#243;n se usa en el reproductor de MP3 de Serge que viene preinstalado en KolibriOS. Tambi&#233;n puede servir en otras aplicaciones orientadas al uso de codecs. Para mayor informaci&#243;n puede consultar el fichero ufmod-codec.h.<td>NORMAL, UNSAFE, AC97SND</table><p>Ejecute el fichero de procesamiento por lotes para generar la librer&#237;a. &#161;Eso es todo!<p>&nbsp;<br><a name='4'><b>Ejemplos</b></a><p>Hay 2 ejemplos disponibles actualmente: mini y jmp2pat. Los ejecutables precompilados se encuentran en bin/. Estos ejecutables no estan empaquetados ni comprimidos.<ul><li><b>mini</b> es el ejemplos m&#225;s simple. Presenta c&#243;mo reproducir una pista XM en memoria, con manejo adecuado de errores.<li><b>jmp2pat</b> es un ejemplo de uso de la funci&#243;n Jump2Pattern. Utiliza un XM compuesto de varias pistas, proporcionado por Kim (tambi&#233;n conocido como norki). Consulte la secci&#243;n siguiente para mayor informaci&#243;n sobre pistas compuestas y la funci&#243;n Jump2Pattern.</ul><p>&nbsp;<br><a name='5'><b>C&#243;mo lograr un ejecutable m&#225;s compacto</b></a><p>Utilice <a href='#22'>Eff</a> para optimizar la librer&#237;a uFMOD y hacerla mas peque&#241;a.<p>Si desea embeber la pista XM directamente en el ejecutable, puede intentar primero optimizar el fichero XM. Modplug Player permite comprimir un fichero XM usando ADPCM, &#161;pero es un tipo de compresi&#243;n con p&#233;rdidas! Utilice <a href='#21'>XMStrip</a> para optimizaci&#243;n sin p&#233;rdidas (en t&#233;rminos de calidad del sonido.)<p>Si tiene plena certeza de que todos los XM que va a reproducir la aplicaci&#243;n son v&#225;lidos (ninguno puede estar corrupto o modificado), recompile la librer&#237;a en modo UNSAFE.<p>Empaquetadores, como mtappack desarrollado por diamond, logran reducir el tama&#241;o del ejecutable. Sin embargo, para mayor objetividad, los ejecutables de ejemplo &#161;no estan comprimidos!<p>Ahora veamos otra t&#233;cnica interesante para minimizar el tama&#241;o de los ficheros XM:<p>Es posible unir varias pistas XM en un solo fichero compuesto. Ya que es posible compartir los instrumentos entre las pistas en el fichero compuesto, el tama&#241;o resultante de este fichero puede ser mucho menor que la suma de los tama&#241;os de los ficheros por separado. A&#250;n sin compartir los instrumentos el tama&#241;o debe ser menor, puesto que s&#243;lo se usa un &#250;nico ejemplar de cabecera XM. Veamos un ejemplo con 3 ficheros XM:<pre>
+<b>Fichero 1 :</b> CABECERA_XM1 P11 P12 P13 I11 I12
+<b>Fichero 2 :</b> CABECERA_XM2 P21 P22 P23 P24 I21 I22 I23 I24
+<b>Fichero 3 :</b> CABECERA_XM3 P31 I31
+</pre><i><b>Leyenda:</b> CABECERA_XMn es la cabecera del n-&#233;simo fichero. Pni es el i-&#233;simo patr&#243;n del n-&#233;simo fichero. Ini es el i-&#233;simo instrumento del n-&#233;simo fichero.</i><p>Primero, vamos a unir los 3 ficheros en uno solo sin compartir los instrumentos:<pre>
+<b>Fichero 4 :</b> CABECERA_XM4 P11 P12 P13 P21 P22 P23 P24 P31 I11 I12 I21 I22 I23 I24 I31
+</pre>Supongamos que I12 es muy similar o identico a I23 y que I24 es igual que I31. Podemos modificar P2n para hacer que utilicen I12 en vez de I23 y enlazar P31 con I24. Entonces, podremos eliminar I23 e I31:<pre>
+<b>Fichero 4 :</b> CABECERA_XM4 P11 P12 P13 P21 P22 P23 P24 P31 I11 I12 I21 I22 I24
+</pre>Al final tendr&#225; que modificar los comandos de ciclos y saltos de patrones y las referencias a instrumentos en los "ficheros" 2 y 3. Obviamente, tambi&#233;n es posible unir apenas 2 o m&#225;s de 3 ficheros, aunque el formato XM establece l&#237;mites para el n&#250;mero m&#225;ximo de patrones e instrumentos en un fichero. Esa es, en general, la idea. Es necesario saber usar un tracker para realizar todas estas operaciones sobre un fichero XM. Una vez unidas todas las pistas en un fichero compuesto, podr&#225; iniciar la reproducci&#243;n con un &#250;nico llamado a uFMOD_PlaySong y "activar" las pistas por separado con llamados a uFMOD_Jump2Pattern. Por ejemplo, uFMOD_Jump2Pattern(3) pasaria a reproducir la segunda pista, uFMOD_Jump2Pattern(7) saltaria a la tercera y uFMOD_Jump2Pattern(0) regresaria a la primera. Los indices exactos en cada caso dependen de los patrones asignados con el tracker. El ejemplo <b>jmp2pat</b> emplea esta clase de optimizaci&#243;n.<p>El uso de Jump2Pattern tiene otra ventaja: la conmutaci&#243;n de pistas se realiza mucho m&#225;s r&#225;pido (casi de inmediato) que el proceso habitual de parar la pista actual y cargar una pista nueva. Por lo tanto, puede usar esta t&#233;cnica cuando necesite conmutar las pistas de audio de la manera m&#225;s r&#225;pida posible.<p>&nbsp;<br><a name='6'><b>Preguntas frecuentes</b></a><p><span style='color:#008080'><b>P:</b> &#191;Es uFMOD gratis para cualquier tipo de uso, incluido el comercial?</span><br><b>R:</b> Si, actualmente as&#237; es.<p><span style='color:#008080'><b>P:</b> &#191;En donde puedo conseguir m&#250;sica en formato XM?</span><br><b>R:</b> En <a href='http://modarchive.org/'>The Mod Archive</a> hay un enorme archivo de m&#250;sica gratis en formatos XM, IT, S3M y MOD. Puede usar el <a href='http://www.modplug.com/'>Open Modplug Tracker</a> para convertir ficheros IT, S3M y MOD a formato XM sin perder la calidad. Hay muchos compositores talentosos en la red dispuestos a compartir su m&#250;sica de manera gratuita. &#161;Pero no olvide el copyright!<p><span style='color:#008080'><b>P:</b> &#191;Existe alguna relaci&#243;n entre el proyecto uFMOD y las librer&#237;as FMOD y/o miniFMOD de Firelight Technologies&#174;?</span><br><b>R:</b> Ya no. Hasta el a&#241;o 2004 uFMOD se bas&#243; en el c&#243;digo fuente abierto de la librer&#237;a miniFMOD. Desde ese entonces, el c&#243;digo fuente de uFMOD fue completamente reescrito, optimizado y depurado. Tambi&#233;n fueron agregadas muchas funciones nuevas. Por lo tanto, la versi&#243;n actual de uFMOD no tiene relaci&#243;n alguna con FMOD o miniFMOD.<p><span style='color:#008080'><b>P:</b> Algunas librer&#237;as aseguran incrementar el tama&#241;o del ejecutable en N kilobytes. &#191;En cuanto se incrementa el tama&#241;o de un ejecutable con uFMOD?</span><br><b>R:</b> No es posible establecer un valor exacto, ya que el tama&#241;o depende de muchos factores, a saber: funciones usadas (en especial, si se utiliza la herramienta EFF), c&#243;digo de la aplicaci&#243;n principal, tama&#241;o del fichero XM (cuando el XM es embebido en el ejecutable). Tambi&#233;n depende de las opciones del linker. El ejemplo bin/mini ocupa &#250;nicamente 4.768 bytes sin compresi&#243;n.<p><span style='color:#008080'><b>P:</b> &#191;En d&#243;nde puedo conseguir la especificaci&#243;n oficial del formato XM?</span><br><b>R:</b> No existe especificaci&#243;n oficial actualizada. En cambio, puede estudiar el documento <a href='http://sourceforge.net/project/showfiles.php?group_id=158498&package_id=234625'>"The Unofficial XM File Format Specification: FastTracker II, ADPCM and Stripped Module Subformats"</a> (s&#243;lo en ingl&#233;s). Este documento describe la mayor&#237;a de los aspectos relevantes del formato XM original, al igual que todas las extensiones extraoficiales actualmente soportadas por uFMOD. Los c&#243;digos fuente de ModPlug (en C++) sirven de referencia sobre formatos derivados del MOD, XM, IT, S3M y muchos otros.<p>&nbsp;<br><a name='7'><b>Agradecemos a</b></a><p>antarman, Barracuda, bogrus, chris_b, cresta, dododo, flaith, Four-F, GL#0M, norki, q_q, SofT MANiAC, S_T_A_S_, voodooattack y yoxola por reportar errores, sugerir nuevas ideas, aportar ejemplos de uso y de otras formas ayudarnos a mejorar uFMOD.<p><a href='http://wasm.ru'>[WASM.RU]</a> y <a href='http://sf.net'>SourceForge.net</a> por el soporte y hosting.<p>&nbsp;<br><b>Copyright</b><p>Los c&#243;digos fuente y ficheros binarios de uFMOD &#169; 2005 - 2007 Asterix y Quantum.<br>Todos los derechos reservados.<p>Pistas de ejemplo:<ul><li>Minimal III &#169; 2006 - 2007 SofT MANiAC (CoolPHat).<li>BlitzXMK.XM del ejemplo Jump2Pat &#169; 2007 Kim (tambi&#233;n conocido como norki).</ul></div><table border=0 cellpadding=0 cellspacing=0 width=100%><tr bgcolor=#708090><td height=1><tr bgcolor=#E7E7E7><td height=52 style='color:#708090;font-size:10pt;font-family:Arial,Aerial' align=center>&#191;Desea reportar un error? &#191;Tiene preguntas o sugerencias?<br> &#191;Est&#225; desarrollando un gran proyecto usando uFMOD? Por favor, mantenganos al tanto: <a href='mailto:ufmod@users.sf.net' name='ci'>ufmod@users.sf.net</a></table></body></html>
\ No newline at end of file
/programs/develop/libraries/ufmod/readme_ru.htm
0,0 → 1,34
<html lang=ru><head><meta http-equiv=Content-Type content="text/html; charset=windows-1251"><title>uFMOD</title></head><body style='margin:0'><table border=0 cellpadding=0 cellspacing=0 width=100%><tr bgcolor=#E7E7E7 align=center><td height=20 style='color:#708090;font-size:9pt;font-family:Arial,Aerial'>[ <a href='en.htm'>English</a> | <a href='es.htm'>Espa&#241;ol</a> | Pycc&#954;u&#250; ]<tr bgcolor=#708090><td height=1></table><center><h2 style='font-size:14pt;font-family:Arial,Aerial'>&#956;FMOD v1.25 äëÿ KolibriOS</h2></center><div style='font-size:10pt;font-family:Arial,Aerial;text-align:justify;margin:8'><p>uFMOD - ýòî êîìïàêòíàÿ, øóñòðàÿ, íàä¸æíàÿ, ìóëüòèïëàòôîðìåííàÿ áèáëèîòåêà äëÿ êà÷åñòâåííîãî âîñïðîèçâåäåíèÿ àóäèî â ôîðìàòå XM, ðàçðàáîòàííàÿ ïîëíîñòüþ íà àññåìáëåðå. XM ìîæåò õðàíèòüñÿ â îòäåëüíîì ôàéëå èëè ïðåäâàðèòåëüíî çàãðóæåí â ïàìÿòü. Ïîääåðæèâàþòñÿ òàêæå áèòûå è íå ñîâñåì ñòàíäàðòíûå ôàéëû. Áèáëèîòåêà ðàñïðîñòðàíÿåòñÿ ñ îòêðûòûì èñõîäíûì êîäîì è ïðèìåðàìè äëÿ ñëåäóþùèõ êîìïèëÿòîðîâ: FASM, MASM32 è NASM.<p>Âåðñèÿ äëÿ KolibriOS äîëæíà èñïðàâíî ðàáîòàòü íà ëþáûõ êîíôèãóðàöèÿõ, óäîâëåòâîðÿþùèõ ñëåäóþùèì òðåáîâàíèÿì:<ol><li>Ìèíèìàëüíàÿ ðåâèçèÿ SVN ÿäðà è äðàéâåðîâ KolibriOS: 574. Ïîñëåäíèå âåðñèè äèñòðèáóòèâîâ è îáíîâëåíèÿ SVN ìîæíî ñêà÷àòü ñ îôèöèàëüíîãî ñàéòà: <a href='http://www.kolibrios.org/'>www.kolibrios.org</a>.<li>Çâóêîâàÿ êàðòî÷êà, ïîääåðæèâàåìàÿ àóäèî-áèáëèîòåêîé <a href='http://infinity-sound.narod.ru/'>Infinity Sound</a> - ýòî âñòðîåííûé çâóêîâîé äðàéâåð KolibriOS. Íà äàííûé ìîìåíò äðàéâåð ïîääåðæèâàåò ìíîãèå âñòðîåííûå êîäåêè ñîâìåñòèìûå ñî ñòàíäàðòîì AC'97.</ol>Âàøà êîíôèãóðàöèÿ óäîâëåòâîðÿåò âûøåïåðå÷èñëåííûì òðåáîâàíèÿì, íî uFMOD íà íåé îòêàçûâàåòñÿ ðàáîòàòü? - Ïîæàëóéñòà, ñîîáùèòå íàì îá ýòîì (<a href='#ci'>êîíòàêòíûå äàííûå</a> ïðèâîäÿòñÿ â íèçó äàííîé ñòðàíèöû).<p><ul><li><a href='#1'>Ïðåæäå ÷åì íà÷àòü</a><li><a href='#2'>Óòèëèòû</a><ul><li><a href='#21'>XMStrip</a><li><a href='#22'>Eff</a></ul><li><a href='#3'>Êîìïèëÿöèÿ áèáëèîòåêè</a><li><a href='#4'>Ïðèìåðû</a><li><a href='#5'>Äîïîëíèòåëüíîå óìåíüøåíèå ðàçìåðà</a><li><a href='#6'>×àÂî</a><li><a href='#7'>Áëàãîäàðíîñòè</a></ul><p>&nbsp;<br><a name='1'><b>Ïðåæäå ÷åì íà÷àòü</b></a><p>KolibriOS - ýòî îïåðàöèîííàÿ ñèñòåìà, íàïèñàííàÿ íà àññåìáëåðå. Ïîýòîìó ó íå¸ òàêîé ìàëåíüêèé ðàçìåð è òàêàÿ âûñîêàÿ ïðîèçâîäèòåëüíîñòü, íî òîëüêî íå â óùåðá âîçìîæíîñòÿì ýòîé ïîëíîöåííîé îïåðàöèîíêè, êàê Âû, âîçìîæíî, óæå óáåäèëèñü. Àíàëîãè÷íàÿ èäåîëîãèÿ ïîääåðæèâàåòñÿ è â ïðîåêòå uFMOD ;)<p>Îñíîâíóþ ÷àñòü äàííîãî ðóêîâîäñòâà ìîæíî óñïåøíî âûïîëíèòü ïðÿìî â ñàìîé ñèñòåìå Kolibri. Òåì íå ìåíåå, òàê êàê ìíîãèå íîâè÷êè â ïðîãðàììèðîâàíèè Kolibri ïðåäïî÷èòàþò êîìïèëèðîâàòü ñâîè ïðîåêòû â Windows è ïîòîì ïåðåíîñèòü èõ â Kolibri äëÿ òåñòèðîâàíèÿ, â äàííîì ðóêîâîäñòâå ìû ïðèìåíèì êðîññêîìïèëÿöèþ.<p>&nbsp;<br><a name='2'><b>Óòèëèòû</b></a><p>Åñòü ïàðà áåñïëàòíûõ óòèëèò äëÿ èñïîëüçîâàíèÿ ñîâìåñòíî ñ uFMOD: XMStrip è Eff. Ïîêà ÷òî íè îäíà èç íèõ íå ïîðòèðîâàíà â Kolibri. Ïîýòîìó ìîæåòå ñêà÷àòü ëþáîé èç äðóãèõ äèñòðèáóòèâîâ uFMOD (äëÿ Win32, Linux èëè Unix/BSD) è èñïîëüçîâàòü óòèëèòû êðîññïëàòôîðìåííî. Íåçàâèñèìî îò âûáðàííîãî äèñòðèáóòèâà, îáå óòèëèòû ñîâìåùàþò â ñåáå êîíñîëüíûé è ãðàôè÷åñêèé (GUI) èíòåðôåéñû. Ðåæèì GUI èíòóèòèâíî ïîíÿòåí. Äàâàéòå ðàññìîòðèì êîíñîëüíûé èíòåðôåéñ.<p><table border=0 cellpadding=0 cellspacing=0 bgcolor=#708090 style='font-size:9pt;font-family:Arial,Aerial'><tr><td colspan=3 height=1><tr height=18><td style='color:#E7E7E7'><b>&nbsp;SVN&nbsp;</b><td bgcolor=#E7E7E7>&nbsp;<a href='http://ufmod.svn.sourceforge.net/viewvc/ufmod'>Èñõîäíèêè äîñòóïíû ÷åðåç SVN</a>&nbsp;<td width=1><tr><td colspan=3 height=1></table><p><a name='21'><b><i>XMStrip</i></b></a> îáðàáàòûâàåò çàäàííûé XM ôàéë ñ öåëüþ óìåíüøåíèÿ ðàçìåðà, áåç ïîòåðè êà÷åñòâà çâó÷àíèÿ.  ïðîöåññå îáðàáîòêè, XMStrip óäàëÿåò íåèñïîëüçóþùèåñÿ èíñòðóìåíòû è ïàðòèòóðû, âûðåçàåò êîììåíòàðèè è ïåðåïàêîâûâàåò âíóòðåííèå ñòðóêòóðû ôàéëà äëÿ óìåíüøåíèÿ ðàçìåðà è ïîâûøåíèÿ ñêîðîñòè çàãðóçêè. Äëÿ íà÷àëà, îòêðîåì êîíñîëü è ââåä¸ì <code>xmstrip /h</code>, ÷òîáû ïîëó÷èòü ñëåäóþùåå ñîîáùåíèå:<p><center><table border=0 cellpadding=8><tr bgcolor=#000000><td><pre><font color=#FFFFFF> USAGE: xmstrip [options] file [output]
file - input file name.
output - optional output file name.
options:
/c - clean only (don't strip)
When [output] is not specified, XMSTRIP
attempts to overwrite the input. If file
name contains spaces, enclose it in "".</font></td></tr></table></center><p>Åñëè èìÿ ñîõðàíÿåìîãî ôàéëà íå óêàçàíî, XMStrip ïåðåçàïèøåò çàäàííûé ôàéë. Åñëè èìÿ ôàéëà ñîäåðæèò ïðîáåëû, åãî íåîáõîäèìî çàêëþ÷èòü â êàâû÷êè ("").<p>Èìåéòå â âèäó, ÷òî äðóãèå ïðîèãðûâàòåëè XM ôàéëîâ, âîçìîæíî, îòêàæóòñÿ âîñïðîèçâîäèòü ôàéë, îáðàáîòàííûé XMStrip. Îïöèÿ <b>/c</b> ïðåäóñìîòðåíà äëÿ âîññòàíîâëåíèÿ òàêèõ ôàéëîâ èëè îáðàáîòêè îáû÷íûõ XM ôàéëîâ, êîòîðûå ïëàíèðóåòñÿ ïðîèãðûâàòü íå òîëüêî â uFMOD.<p><a name='22'><b><i>Eff</i></b></a> ïðåäíàçíà÷àåòñÿ äëÿ îïûòíûõ êîäåðîâ, æåëàþùèõ ñýêîíîìèòü êàæäûé áàéò â ñâîèõ ïðèëîæåíèÿõ. Äëÿ ýòîãî íóæíî âûäåëèòü òîëüêî òå ôóíêöèè uFMOD, êîòîðûå äåéñòâèòåëüíî áóäóò èñïîëüçîâàíû â öåëåâîì ïðèëîæåíèè, ïåðåêîìïèëèðîâàòü áèáëèîòåêó è ïîëó÷èòü íàèìåíüøèé âîçìîæíûé ðàçìåð. Âîò, ÷òî âûäà¸ò <code>eff /h</code> :<p><center><table border=0 cellpadding=8><tr bgcolor=#000000><td><pre><font color=#FFFFFF> USAGE: eff [options] file
file - input file name
options:
/Dm - generate a masm32/tasm dump
/Dd - generate a Pascal (Delphi) dump
/Dc - generate a C/C++ dump
/Ds - generate an RCDATA resource dump
/Di - disable infoAPI:
uFMOD_GetStats, uFMOD_GetRowOrder,
uFMOD_GetTitle and uFMOD_GetTime
/Dp - disable uFMOD_Pause, uFMOD_Resume
and XM_SUSPENDED
/Dv - disable volume control
/Dj - disable Jump2Pattern
/Df - disable loading XM from file
/Dl - disable XM_NOLOOP
/M - mark & clear unused chunks of
+<li><span style='color:#800080'><b>eff.inc</b></span> - ýòîò çàãîëîâî÷íûé ôàéë ñîçäà¸òñÿ óòèëèòîé <a href='#22'>Eff</a>. Íå ðåêîìåíäóåòñÿ ðåäàêòèðîâàòü äàííûé ôàéë âðó÷íóþ! Íàñòîÿùèå êîäåðû íå îáðàùàþò âíèìàíèÿ íà ïîäîáíûå ïðåäóïðåæäåíèÿ, íî âñ¸ æå... :)<li><span style='color:#800080'><b>ufmod.inc</b></span> ñîäåðæèò ïîäðîáíîå îïèñàíèå API uFMOD äëÿ èñïîëüçîâàíèÿ â ïðîåêòàõ íà ASM/C/C++.<li><span style='color:#800080'><b>ufmod-codec.h</b></span> ñîäåðæèò îïèñàíèå àëüòåðíàòèâíîãî API uFMOD, êîòîðîå ïðåäîñòàâëÿåòñÿ áèáëèîòåêîé â ðåæèìå AC97SND - ýòîò ðåæèì ïðåäíàçíà÷åí äëÿ èñïîëüçîâàíèÿ â ïëååðàõ àóäèî-ôàéëîâ, âðîäå AC'97 MP3 Player Serge'ÿ.<li> <span style='color:#008080'><b>core.asm</b></span> íàõîäèòñÿ áîëüøàÿ ÷àñòü èñõîäíîãî êîäà uFMOD. Ýòîò ñàìûé ôàéë ïðèñóòñòâóåò âî âñåõ äèñòðèáóòèâàõ áèáëèîòåêè: KolibriOS, Unix/BSD, Linux è Win32. Çàãðóçêà XM-ôàéëà, ñìåøèâàíèå êàíàëîâ, íàëîæåíèå ýôôåêòîâ è ìíîãèå äðóãèå îáùèå äëÿ âñåõ äèñòðèáóòèâîâ àëãîðèòìû ðåàëèçîâàíû â äàííîì ôàéëå.<li><span style='color:#008080'><b>ufmod.asm</b></span> ñîäåðæèò ïëàòôîðìîçàâèñèìûå ïðîöåäóðû: ôàéëîâûé Â/Â, îáùåíèå ñî çâóêîâûì äðàéâåðîì è ò.ä. Ïîýòîìó, ñîäåðæèìîå äàííîãî ôàéëà ðàçëè÷àåòñÿ â äèñòðèáóòèâàõ äëÿ ðàçíûõ ÎÑåé.<li><span style='color:#008080'><b>fasm.asm</b></span> õðàíèò îïðåäåëåíèÿ êîíñòàíò, ñòðóêòóð è ò.ä. ïîä ñèíòàêñèñ Flat Assembler (FASM). Ýòîò ôàéë ïîçâîëÿåò ñîáèðàòü áèáëèîòåêó ñ ïîìîùüþ FASM.<li><span style='color:#008080'><b>masm.asm</b></span> õðàíèò îïðåäåëåíèÿ êîíñòàíò, ñòðóêòóð è ò.ä. ïîä ñèíòàêñèñ MASM32. Ýòîò ôàéë ïîçâîëÿåò ñîáèðàòü áèáëèîòåêó ñ ïîìîùüþ MASM32.<li><span style='color:#008080'><b>nasm.asm</b></span> õðàíèò îïðåäåëåíèÿ êîíñòàíò, ñòðóêòóð è ò.ä. ïîä ñèíòàêñèñ Netwide Assembler (NASM). Ýòîò ôàéë ïîçâîëÿåò ñîáèðàòü áèáëèîòåêó ñ ïîìîùüþ NASM.</ul>Ñëåäóþùèì ïîñëå âíåñåíèÿ èçìåíåíèé â èñõîäíèêè øàãîì ÿâëÿåòñÿ êîìïèëÿöèÿ. ×òîáû ïåðåñîáðàòü ufmod.obj, ñíà÷àëà îòêðîéòå â òåêñòîâîì ðåäàêòîðå áàòíèê src/ufmodlib/makeobj.bat. Âñ¸, ÷òî íàõîäèòñÿ ìåæäó ñëåäóþùèõ ñòðîê:<pre>rem *** CONFIG START</pre>è<pre>rem *** CONFIG END</pre>ïîäëåæèò íàñòðîéêå. Îáðàòèòå âíèìàíèå íà ñåêöèþ <code>Pathes</code>. Òàì åñòü òàêàÿ îïöèÿ:<pre>SET UF_NASM=\nasm</pre>Åñëè ó Âàñ óñòàíîâëåí NASM, óäîñòîâåðüòåñü, ÷òî ïóòü â äàííîé îïöèè óêàçûâàåò òî÷íî òóäà, ãäå íàõîäèòñÿ nasmw.exe. Äîïóñòèì, NASM óñòàíîâëåí â <code>D:\TOOLS\NASM</code>.  òàêîì ñëó÷àå, íåîáõîäèìî ñêîððåêòèðîâàòü îïöèþ ñëåäóþùèì îáðàçîì:<pre>SET UF_NASM=D:\TOOLS\NASM</pre>Íå âñå ïóòè íåîáõîäèìû äëÿ óñïåøíîé êîìïèëÿöèè. Íàïðèìåð, åñëè Âû íàìåðåíû èñïîëüçîâàòü FASM, íå íóæíî íàñòðàèâàòü UF_NASM. Ïðîâåðüòå ïðàâèëüíîñòü âñåõ ïóòåé, íåîáõîäèìûõ äëÿ êîìïèëÿöèè. Òåïåðü íàñòðîéòå ïàðàìåòðû êîíôèãóðàöèè, ñîãëàñíî ñëåäóþùåé òàáëèöå:<p><table border=0 cellpadding=4 cellspacing=2 style='font-size:10pt;font-family:Arial,Aerial'><tr bgcolor=#708090 style='color:#E7E7E7;font-weight:bold'><td>Îïöèÿ<td>Îïèñàíèå<td width=200>Çíà÷åíèÿ<tr valign=top><td>UF_RAMP<td>Äàííàÿ îïöèÿ ïîçâîëÿåò íàñòðîèòü ìåõàíèçì èíòåðïîëÿöèè, êîòîðûé ïðåäíàçíà÷åí äëÿ ïîãàøåíèÿ ùåë÷êîâ - ðåçêèå ïåðåïàäû àìïëèòóäû ñèãíàëà, õàðàêòåðíûå äëÿ òðåêåðñêîé ìóçûêè. Ñ äðóãîé ñòîðîíû, èíòåðïîëÿöèÿ âíîñèò èñêàæåíèå â âûñîêî÷àñòîòíûå ñïåêòðàëüíûå ñîñòàâëÿþùèå ñèãíàëà, ÷òî èíîãäà áûâàåò çàìåòíî. STRONG - ýòî çíà÷åíèå ïî óìîë÷àíèþ, ðåêîìåíäóåìîå äëÿ áîëüøèíñòâà ïðèëîæåíèé.  äàííîì ðåæèìå ìèêñåð ñãëàæèâàåò ðåçêèå ïåðåïàäû àìïëèòóäû, ïðèìåíÿÿ ëèíåéíóþ 128-ñòóïåí÷àòóþ èíòåðïîëÿöèþ. WEAK íàêëàäûâàåò ëèøü 16 ñòóïåíåé - ýòîò ðåæèì ìåíåå ýôôåêòèâåí, ÷åì STRONG, íî çàòî âåðîÿòíîñòü äåãðàäàöèè ñèãíàëà â ýòîì ðåæèìå íèæå. NONE âîîáùå îòêëþ÷àåò èíòåðïîëÿöèþ. Áåç ñãëàæèâàíèÿ íå áóäåò è äåãðàäàöèè, íî áîëüøèíñòâî êîìïîçèöèé áåç ñãëàæèâàíèÿ áóäåò çâó÷àòü çàìåòíî õóæå èç-çà íàëîæåíèÿ ùåë÷êîâ. Îñîáûì îáðàçîì ñáàëàíñèðîâàííûå êîìïîçèöèè áåç ñãëàæèâàíèÿ ìîãóò çâó÷àòü ëó÷øå.<td>NONE, WEAK, STRONG<tr bgcolor=#E7E7E7 valign=top><td>UF_FREQ<td>×àñòîòà äèñêðåòèçàöèè (â Ãö). 48ÊÃö ÿâëÿåòñÿ çíà÷åíèåì, ðåêîìåíäóåìûì äëÿ áîëüøèíñòâà ïðèëîæåíèé.<td>22050, 44100, 48000<tr valign=top><td>UF_ASM<td>Àññåìáëåð. Äà, uFMOD ìîæíî ñîáèðàòü ðàçíûìè àññåìáëåðàìè - âûáèðàéòå òîò, êîòîðûé áîëüøå íðàâèòñÿ :)<td>MASM, NASM, FASM<tr bgcolor=#E7E7E7 valign=top><td>UF_MODE<td>NORMAL - ýòî çíà÷åíèå ïî óìîë÷àíèþ. Íè÷åãî îñîáåííîãî. UNSAFE îòêëþ÷àåò ïðîâåðêó ïðàâèëüíîñòè ôîðìàòà XM ïåðåä çàãðóçêîé êîìïîçèöèè. Åñëè Âû óâåðåíû, ÷òî âñå êîìïîçèöèè, êîòîðûå áóäóò ïðîèãðûâàòüñÿ â âàøåì ïðèëîæåíèè, êîððåêòíû (ïðàâèëüíîñòü ôîðìàòà XM-ôàéëà ìîæíî ïðîâåðèòü â Eff èëè XMStrip), ìîæåòå ïåðåñîáðàòü áèáëèîòåêó â ðåæèìå UNSAFE, ÷òîáû âûéãðàòü â ðàçìåðå è ñêîðîñòè çàãðóçêè. Èìåéòå â âèäó, ÷òî çàãðóçêà íåïðàâèëüíîãî XM-ôàéëà â ðåæèìå UNSAFE ìîæåò ïðèâåñòè ê êðàõó!  ðåæèìå AC97SND áèáëèîòåêà ïðåäñòàâëÿåò ñîáîé êîäåê äëÿ ïðîèãðûâàòåëÿ AC'97 MP3 Player Serge'ÿ. Äàííûé ðåæèì ìîæåò áûòü ïîëåçåí è äëÿ äðóãèõ ïðîåêòîâ ñõîäíîé íàïðàâëåííîñòè. Îïèñàíèå API äàííîãî ðåæèìà ìîæíî íàéòè â ufmod-codec.h.<td>NORMAL, UNSAFE, AC97SND</table><p>Çàïóñòèòå áàòíèê, ÷òîáû ñîáðàòü áèáëèîòåêó. Âîò è âñ¸!<p>&nbsp;<br><a name='4'><b>Ïðèìåðû</b></a><p> äàííûé äèñòðèáóòèâ âîøëè 2 ïðèìåðà: mini è jmp2pat. Îòêîìïèëèðîâàííûå ýêçåøíèêè íàõîäÿòñÿ â bin/. Çàìåòüòå, ÷òî ýêçåøíèêè ïðåäñòàâëåíû áåç ñæàòèÿ.<ul><li><b>mini</b> - ýòî ïðîñòåéøèé ïðèìåð ôîíîâîãî ïðîèãðûâàíèÿ ìóçûêè èç ïàìÿòè.<li><b>jmp2pat</b> - ýòî ïðèìåð èñïîëüçîâàíèÿ ôóíêöèè Jump2Pattern.  äàííîì ïðèìåðå ïðîèãðûâàåòñÿ êîìïîçèòíûé XM, ëþáåçíî ïðåäîñòàâëåííûé òîâàðèùåì Kim (îí æå norki). Îïèñàíèå òåõíèêè ñîçäàíèÿ è èñïîëüçîâàíèÿ ïîäîáíûõ êîìïîçèöèé ìîæíî íàéòè â ñëåäóþùåì ðàçäåëå.</ul><p>&nbsp;<br><a name='5'><b>Äîïîëíèòåëüíîå óìåíüøåíèå ðàçìåðà</b></a><p>Óòèëèòà <a href='#22'>Eff</a> ïðåäíàçíà÷åíà äëÿ îïòèìèçàöèè è óìåíüøåíèÿ ðàçìåðà áèáëèîòåêè uFMOD.<p>Åñëè Âû ñîáèðàåòåñü âêëþ÷èòü XM ñòàòè÷åñêè â ýêçåøíèê, ìîæåòå ïîïðîáîâàòü îïòèìèçèðîâàòü ñíà÷àëà ñàì XM. Modplug Player óìååò ñæèìàòü XM-êîìïîçèöèè ïî ñõåìå APDCM, íî ó÷òèòå, ÷òî ýòîò òèï ñæàòèÿ ïàãóáíî âëèÿåò íà êà÷åñòâî çâó÷àíèÿ! Óòèëèòà <a href='#21'>XMStrip</a> ïåðåïàêîâûâàåò XM ôàéë áåç ïîòåðè êà÷åñòâà.<p>Åñëè Âû óâåðåíû â êîððåêòíîñòè ôîðìàòà âñåõ êîìïîçèöèé, êîòîðûå áóäóò èñïîëüçîâàíû â ïðèëîæåíèè, ìîæåòå ïåðåñîáðàòü áèáëèîòåêó â ðåæèìå UNSAFE.<p>Óïàêîâùèêè, âðîäå mtappack diamond'à, óìåþò óæèìàòü ýêçåøíèêè. Òåì íå ìåíåå, äëÿ íàãëÿäíîñòè, âñå ïðèìåðû ïðåäîñòàâëåíû áåç ñæàòèÿ!<p>Åñòü åù¸ îäèí õèòðûé ñïîñîá îïòèìèçàöèè ðàçìåðà XM-ôàéëîâ, êîòîðûé çàêëþ÷àåòñÿ â ñîâìåùåíèè ñðàçó íåñêîëüêèõ êîìïîçèöèé â îäíîì ôàéëå. Ïðè ýòîì ìîæíî óäàëÿòü ëèøíèå ýêçåìïëÿðû ïîâòîðÿþùèõñÿ èíñòðóìåíòîâ, åñëè òàêîâûå èìåþòñÿ, ÷òî î÷åíü çàìåòíî ñêàçûâàåòñÿ íà ðàçìåðå êîíå÷íîãî ôàéëà. Äàæå áåç îïòèìèçàöèè èíñòðóìåíòîâ ðàçìåð êîìïîçèòíîãî ôàéëà äîëæåí ïîëó÷èòüñÿ ìåíüøå ñóììû ðàçìåðîâ îòäåëüíûõ ôàéëîâ, òàê êàê çàãîëîâêè âñåõ ôàéëîâ çàìåíÿþòñÿ îäíèì îáùèì. Äàâàéòå ðàññìîòðèì ïðèìåð ñ òðåìÿ ôàéëàìè:<pre>
+<b>Ôàéë 1 :</b> XM1_HEADER P11 P12 P13 I11 I12
+<b>Ôàéë 2 :</b> XM2_HEADER P21 P22 P23 P24 I21 I22 I23 I24
+<b>Ôàéë 3 :</b> XM3_HEADER P31 I31
+</pre><i><b>Ïîÿñíåíèå:</b> XMn_HEADER - ýòî çàãîëîâîê n-íîãî ôàéëà. Pnm - ýòî m-íàÿ ïàðòèòóðà n-íîãî ôàéëà. Inm - ýòî m-íûé èíñòðóìåíò n-íîãî ôàéëà.</i><p>Äëÿ íà÷àëà, ñîâìåñòèì âñå 3 êîìïîçèöèè áåç îïòèìèçàöèè èíñòðóìåíòîâ:<pre>
+<b>Ôàéë 4 :</b> XM4_HEADER P11 P12 P13 P21 P22 P23 P24 P31 I11 I12 I21 I22 I23 I24 I31
+</pre>Ïðåäñòàâüòå, ÷òî I12 î÷åíü ïîõîæ èëè èäåíòè÷åí I23; I24 è I31 òîæå ïðàêòè÷åñêè îäèíàêîâû. Ìû ìîæåì çàñòàâèòü ïàðòèòóðû P2n èñïîëüçîâàòü I12 âìåñòî I23, à P31 ïåðåêëþ÷èòü íà I24. Òîãäà ìû ñìîæåì óäàëèòü I23 è I31:<pre>
+<b>Ôàéë 4 :</b> XM4_HEADER P11 P12 P13 P21 P22 P23 P24 P31 I11 I12 I21 I22 I24
+</pre>Íåîáõîäèìî ñêîððåêòèðîâàòü êîìàíäû çàöèêëèâàíèÿ è ññûëêè íà ïàðòèòóðû â êîìïîçèöèÿõ 2 è 3 ïîñëå ñîâìåùåíèÿ. Êîíå÷íî, ìîæíî ñîâìåùàòü è áîëüøåå êîëè÷åñòâî êîìïîçèöèé, íî ôîðìàò XM èìååò îãðàíè÷åíèÿ íà ìàêñèìàëüíîå êîëè÷åñòâî ïàðòèòóð è èíñòðóìåíòîâ â ôàéëå. Âñå îïåðàöèè íàä XM-ôàéëàìè íàäëåæèò ïðîâîäèòü â ñïåöèàëüíîì ÏÎ - òðåêåðå. Äëÿ ïðîèãðûâàíèÿ êîìïîçèòíîãî ôàéëà äîñòàòî÷íî îäíîãî âûçîâà ôóíêöèè uFMOD_PlaySong. Äàëåå íóæíî èñïîëüçîâàòü ôóíêöèþ uFMOD_Jump2Pattern äëÿ ïðîèãðûâàíèÿ îòäåëüíûõ êîìïîçèöèé èç îáùåãî ôàéëà â ïðîèçâîëüíîé ïîñëåäîâàòåëüíîñòè. Íàïðèìåð, uFMOD_Jump2Pattern(3) ïåðåêëþ÷èòñÿ íà âòîðóþ êîìïîçèöèþ, uFMOD_Jump2Pattern(7) íà÷í¸ò ïðîèãðûâàòü òðåòüþ, à uFMOD_Jump2Pattern(0) âåðí¸òñÿ îáðàòíî ê ïåðâîé. Òî÷íûå çíà÷åíèÿ èíäåêñîâ ñòàðòîâûõ ïàðòèòóð êàæäîé êîìïîçèöèè ïîñëå ñîâìåùåíèÿ ëåãêî âû÷èñëèòü â óìå, íî ìîæíî è â òðåêåðå ïîäñìîòðåòü :) Ïðèìåð <b>jmp2pat</b> èñïîëüçóåò äàííûé ñïîñîá îïòèìèçàöèè.<p> èñïîëüçîâàíèè Jump2Pattern åñòü åù¸ îäèí ïëþñ - ïåðåêëþ÷åíèå ïðîèñõîäèò ãîðàçäî áûñòðåå (ïðàêòè÷åñêè ìîìåíòàëüíî) ÷åì ïðè îñòàíîâêå òåêóùåé êîìïîçèöèè è ïîñëåäóþùåé çàãðóçêå íîâîé. Ìîæåòå áðàòü íà âîîðóæåíèå ýòó ôèøêó äëÿ ðåàëèçàöèè ðåøåíèé, òðåáóþùèõ ìàêñèìàëüíî áûñòðîãî ïåðåêëþ÷åíèÿ ìóçûêàëüíîãî ôîíà.<p>&nbsp;<br><a name='6'><b>×àÂî</b></a><p><span style='color:#008080'><b>Â:</b> Áèáëèîòåêà uFMOD äåéñòâèòåëüíî áåñïëàòíà äëÿ ëþáîãî èñïîëüçîâàíèÿ, âêëþ÷àÿ êîììåð÷åñêîå?</span><br><b>Î:</b> Äà, òåêóùàÿ âåðñèÿ àáñîëþòíî áåñïëàòíà äëÿ èñïîëüçîâàíèÿ â ëþáûõ öåëÿõ.<p><span style='color:#008080'><b>Â:</b> Ãäå áû äîñòàòü êîìïîçèöèè â ôîðìàòå XM?</span><br><b>Î:</b> <a href='http://modarchive.org/'>The Mod Archive</a> ñîäåðæèò âíóøèòåëüíûõ ðàçìåðîâ àðõèâ ñ áåñïëàòíûìè òðåêåðñêèìè êîìïîçèöèÿìè â ôîðìàòå XM, IT, S3M è MOD. <a href='http://www.modplug.com/'>Open Modplug Tracker</a> óìååò êîíâåðòèðîâàòü IT, S3M è MOD â XM áåç ïîòåðè êà÷åñòâà.  ñåòè ìíîãî òàëàíòëèâûõ êîìïîçèòîðîâ, êîòîðûå áåñïëàòíî âûêëàäûâàþò ñâîè ðàáîòû. Íå çàáûâàéòå óêàçûâàòü ñîîòâåòñòâóþùèå ïîìåòêè îá àâòîðñòâå!<p><span style='color:#008080'><b>Â:</b> Ñóùåñòâóåò ëè êàêàÿ-ëèáî ñâÿçü ìåæäó ïðîåêòîì uFMOD è ðàçðàáîòêàìè Firelight Technologies&#174;: FMOD è miniFMOD?</span><br><b>Î:</b> Íà äàííûé ìîìåíò íèêàêîé ñâÿçè óæå íåò. Äî 2004ãî ãîäà âêëþ÷èòåëüíî ïðîåêò uFMOD îñíîâûâàëñÿ íà èñõîäíûõ êîäàõ áèáëèîòåêè miniFMOD. Ñ òåõ ïîð, êîä uFMOD áûë ïîëíîñòüþ ïåðåïèñàí, îñíàù¸í íîâûìè ôóíêöèÿìè, îïòèìèçèðîâàí è îòëàæåí. Òàêèì îáðàçîì, uFMOD áîëåå íå ñâÿçàí íè ñ FMOD, íè ñ miniFMOD.<p><span style='color:#008080'><b>Â:</b> Íåêîòîðûå ðàçðàáîò÷èêè óòâåðæäàþò, ÷òî èõ áèáëèîòåêè óâåëè÷èâàþò ýêçåøíèêè íà N-íîå êîëè÷åñòâî êèëîáàéò. Íà ñêîëüêî êèëîáàéò óâåëè÷èâàåòñÿ ðàçìåð ýêçåøíèêà ïðè èñïîëüçîâàíèè uFMOD?</span><br><b>Î:</b> Òî÷íîãî îòâåòà íà ýòîò âîïðîñ íåò, òàê êàê ýòîò ðàçìåð çàâèñèò îò ìíîãèõ ôàêòîðîâ: èñïîëüçóåìûå õàðàêòåðèñòèêè áèáëèîòåêè (îñîáåííî ïðè èñïîëüçîâàíèè óòèëèòû Eff), îñíîâíîé êîä ïðîãðàììû, ðàçìåð XM-ôàéëà (åñëè XM âêëþ÷àåòñÿ â îáðàç ýêçåøíèêà). Ðàçìåð òàêæå çàâèñèò îò îïöèé ëèíêåðà. Ïðèìåð bin/mini çàíèìàåò 4768 áàéò áåç ñæàòèÿ.<p><span style='color:#008080'><b>Â:</b> Ãäå ìîæíî ðàçäîáûòü îôèöèàëüíîå îïèñàíèå ôîðìàòà XM?</span><br><b>Î:</b> Ïîëíîãî îôèöèàëüíîãî îïèñàíèÿ ñîâðåìåííîãî ôîðìàòà XM íåò. Ïîçâîëüòå ïðåäëîæèòü âçàìåí ýòîò äîêóìåíò: <a href='http://sourceforge.net/project/showfiles.php?group_id=158498&package_id=234625'>"The Unofficial XM File Format Specification: FastTracker II, ADPCM and Stripped Module Subformats"</a> (òîëüêî íà àíãë.).  äàííîì äîêóìåíòå îïèñàíû ìíîãèå òîíêîñòè ðàáîòû ñ ôîðìàòîì XM, âêëþ÷àÿ âñå íåñòàíäàðòíûå ðàñøèðåíèÿ, êîòîðûå íà äàííûé ìîìåíò ïîääåðæèâàåò uFMOD. Ê òîìó æå, èç èñõîäíèêîâ ModPlug (íà C++) ìîæíî ïî÷åðïíóòü ìàññó ïîëåçíîé èíôîðìàöèè ïî òðåêåðñêèì ôîðìàòàì ôàéëîâ.<p>&nbsp;<br><a name='7'><b>Áëàãîäàðíîñòè</b></a><p>antarman, Barracuda, bogrus, chris_b, cresta, dododo, flaith, Four-F, GL#0M, norki, q_q, SofT MANiAC, S_T_A_S_, voodooattack è yoxola çà ïîìîùü â óñòðàíåíèè îøèáîê, ïðåäëîæåíèÿ ïî óëó÷øåíèþ áèáëèîòåêè, ïðèìåðû èñïîëüçîâàíèÿ ïîä ðàçíûå êîìïèëÿòîðû è âñ¸ îñòàëüíîå, òàê èëè èíà÷å ïîìîãàþùåå íàì â ðàçâèòèè ïðîåêòà.<p><a href='http://wasm.ru'>[WASM.RU]</a> è <a href='http://sf.net'>SourceForge.net</a> çà ïîääåðæêó è õîñòèíã.<p>&nbsp;<br><b>Àâòîð&#169;òâî</b><p>Èñõîäíûå êîäû uFMOD è ñîïðîâîæäàþùèå óòèëèòàðíûå ïðèëîæåíèÿ &#169; 2005 - 2007 Asterix è Quantum.<br>Âñå ïðàâà çàùèùåíû.<p>Êîìïîçèöèè:<ul><li>Minimal III &#169; 2006 - 2007 SofT MANiAC (CoolPHat).<li>BlitzXMK.XM èç ïðèìåðà Jump2Pat &#169; 2007 Kim (îí æå - norki).</ul></div><table border=0 cellpadding=0 cellspacing=0 width=100%><tr bgcolor=#708090><td height=1><tr bgcolor=#E7E7E7><td height=52 style='color:#708090;font-size:10pt;font-family:Arial,Aerial' align=center>Íàøëè îøèáêó? Æåëàåòå çàäàòü âîïðîñ ðàçðàáîò÷èêàì èëè âûñêàçàòü ïðåäëîæåíèå ïî óëó÷øåíèþ áèáëèîòåêè?<br>Ðàçðàáàòûâàåòå èíòåðåñíûé ïðîåêò ñ èñïîëüçîâàíèåì uFMOD? Âàì ñþäà: <a href='mailto:ufmod@users.sf.net' name='ci'>ufmod@users.sf.net</a></table></body></html>
\ No newline at end of file
/programs/develop/libraries/ufmod/ufmod-codec.h
0,0 → 1,89
/*
uFMOD API reference (AC97SND mode)
=========================================================
 
NOTE: ufmod.obj should be rebuilt setting UF_MODE=AC97SND
in order to make it usable in AC97SND player.
 
The Infinity Sound driver handle should be available as
a public symbol named hSound. It is so when using Serge's
sound.lib.
*/
 
#ifdef __cplusplus
extern "C" {
#endif
 
/* HANDLE uFMOD_LoadSong(char *lpXM);
---
Description:
---
Loads the given XM song and starts playing it as soon as you
call uFMOD_WaveOut for the first time. It will stop any
currently playing song before loading the new one. Heap should
be initialized before calling this function!
---
Parameters:
---
lpXM
Specifies the filename of the song to load.
---
Return Values:
---
On success, returns a non zero value. Returns 0 on failure.
*/
int __cdecl uFMOD_LoadSong(char*);
 
/* int uFMOD_WaveOut(SNDBUF hBuff)
---
Description:
---
Updates the internal playback buffer.
---
Parameters:
---
hBuff
The Infinity Sound buffer to update.
---
Remarks:
---
Playback doesn't actually begin when calling uFMOD_LoadSong,
but when calling uFMOD_WaveOut after a successful uFMOD_LoadSong
call. Afterwards, you should call uFMOD_WaveOut repeatedly at
least once every 250 ms to prevent "buffer underruns".
uFMOD_WaveOut is a non-blocking function.
---
Return Values:
---
Returns non zero on error.
*/
int __cdecl uFMOD_WaveOut(unsigned int);
 
/* void uFMOD_StopSong(void)
---
Description:
---
Stops the currently playing song, freeing the associated
resources.
---
Remarks:
---
Does nothing if no song is playing at the time the call is made.
*/
void __cdecl uFMOD_StopSong();
 
/* unsigned char* _uFMOD_GetTitle(void)
---
Description:
---
Returns the current song's title.
---
Remarks:
---
Not every song has a title, so be prepared to get an empty string.
*/
unsigned char* __cdecl uFMOD_GetTitle();
 
#ifdef __cplusplus
}
#endif
/programs/develop/libraries/ufmod/ufmod.asm
0,0 → 1,1104
; UFMOD.ASM
; ---------
; uFMOD public source code release. Provided as-is.
 
SOUND_VERSION equ 100h ; required Infinity sound driver version
FSOUND_Block equ 10
FSOUND_BlockSize equ 1024 ; 1 << FSOUND_Block
 
if DEBUG
 
; Debug messages:
sDBGMSG1 db "uFMOD: XM track loaded",13,10,0
sDBGMSG2 db "uFMOD: Infinity driver loaded",13,10,0
sDBGMSG3 db "uFMOD: Buffer created",13,10,0
sDBGMSG4 db "uFMOD: Sound buffer destroyed",13,10,0
sDBGMSG5 db "uFMOD: Infinity version: ",0
 
; DEBUG board: print a string.
DBG_print_s:
; EDX = msg (trailing 0 is required!)
pushad
DBG_print_s_loop:
mov eax,63
mov ebx,1
mov cl,[edx]
test cl,cl
jz DBG_print_s_R
int 40h
inc edx
jmp DBG_print_s_loop
DBG_print_s_R:
popad
ret
 
; DEBUG board: print the hex value in EAX.
DBG_print_x:
; EAX = val
pushad
mov esi,eax
mov edx,OFFSET MixBuf
mov ecx,7
mov DWORD PTR [edx+8],0A0Dh
print_eax_loop:
mov eax,esi
and al,0Fh
cmp al,10
sbb al,69h
das
mov [edx+ecx],al
shr esi,4
dec ecx
jns print_eax_loop
call DBG_print_s
popad
ret
endif ; DEBUG
 
if RAMP_STRONG
volumerampsteps equ 128
volumeramps_pow equ 7
endif
 
if RAMP_WEAK
volumerampsteps equ 16
volumeramps_pow equ 4
endif
 
if RAMP_NONE
volumerampsteps equ 64
volumeramps_pow equ 6
endif
 
XM_MEMORY equ 1
XM_FILE equ 2
XM_NOLOOP equ 8
XM_SUSPENDED equ 16
FMUSIC_ENVELOPE_SUSTAIN equ 2
FMUSIC_ENVELOPE_LOOP equ 4
FMUSIC_FREQ equ 1
FMUSIC_VOLUME equ 2
FMUSIC_PAN equ 4
FMUSIC_TRIGGER equ 8
FMUSIC_VOLUME_OR_FREQ equ 3
FMUSIC_VOLUME_OR_PAN equ 6
FMUSIC_VOL_OR_FREQ_OR_TR equ 11
FMUSIC_FREQ_OR_TRIGGER equ 9
NOT_FMUSIC_TRIGGER equ 0F7h
NOT_FMUSIC_TRIGGER_OR_FRQ equ 0F6h
 
; FMUSIC_XMCOMMANDS enum:
FMUSIC_XM_PORTAUP equ 1
FMUSIC_XM_PORTADOWN equ 2
FMUSIC_XM_PORTATO equ 3
FMUSIC_XM_VIBRATO equ 4
FMUSIC_XM_PORTATOVOLSLIDE equ 5
FMUSIC_XM_VIBRATOVOLSLIDE equ 6
FMUSIC_XM_TREMOLO equ 7
FMUSIC_XM_SETPANPOSITION equ 8
FMUSIC_XM_SETSAMPLEOFFSET equ 9
FMUSIC_XM_VOLUMESLIDE equ 10
FMUSIC_XM_PATTERNJUMP equ 11
FMUSIC_XM_SETVOLUME equ 12
FMUSIC_XM_PATTERNBREAK equ 13
FMUSIC_XM_SPECIAL equ 14
FMUSIC_XM_SETSPEED equ 15
FMUSIC_XM_SETGLOBALVOLUME equ 16
FMUSIC_XM_GLOBALVOLSLIDE equ 17
FMUSIC_XM_KEYOFF equ 20
FMUSIC_XM_PANSLIDE equ 25
FMUSIC_XM_MULTIRETRIG equ 27
FMUSIC_XM_TREMOR equ 29
FMUSIC_XM_EXTRAFINEPORTA equ 33
 
; FMUSIC_XMCOMMANDSSPECIAL enum:
FMUSIC_XM_FINEPORTAUP equ 1
FMUSIC_XM_FINEPORTADOWN equ 2
FMUSIC_XM_SETGLISSANDO equ 3
FMUSIC_XM_SETVIBRATOWAVE equ 4
FMUSIC_XM_SETFINETUNE equ 5
FMUSIC_XM_PATTERNLOOP equ 6
FMUSIC_XM_SETTREMOLOWAVE equ 7
FMUSIC_XM_SETPANPOSITION16 equ 8
FMUSIC_XM_RETRIG equ 9
FMUSIC_XM_NOTECUT equ 12
FMUSIC_XM_NOTEDELAY equ 13
FMUSIC_XM_PATTERNDELAY equ 14
 
if AC97SND_ON
 
file_read:
; buf in EAX
; size in EDX
push ebx
push esi
push edi
push ebp
xchg eax,edi
file_read_begin:
test edx,edx
jg file_read_chk_cache
file_read_done:
pop ebp
pop edi
pop esi
pop ebx
ret
; *** CHECK IN THE CACHE
file_read_chk_cache:
mov ebp,OFFSET file_struct
mov esi,[ebp-24]
sub esi,[ebp+28] ; cache_offset
js file_read_cache_done
mov ecx,8192
sub ecx,esi
jle file_read_cache_done
add esi,OFFSET MixBuf
sub edx,ecx
jns file_read_do_cache
add ecx,edx
file_read_do_cache:
add [ebp-24],ecx
rep movsb
test edx,edx
jle file_read_done ; data read from the cache (no need to access the FS)
file_read_cache_done:
; *** FS BATCH READ OPERATION
mov eax,[ebp-24]
mov ecx,edx
add ecx,eax
and ecx,0FFFFE000h
sub ecx,eax
jle file_read_fs_done ; Too few data requested for a FS batch operation
sub edx,ecx
mov [ebp+4],eax ; file offset
mov [ebp+12],ecx ; NumberOfBytesToRead
mov [ebp+16],edi ; lpBuffer
mov ebx,ebp
add edi,ecx
push 70
add [ebp-24],ecx
pop eax
int 40h
file_read_fs_done:
; *** UPDATE THE CACHE
mov ecx,[ebp-24]
and ecx,0FFFFE000h
mov [ebp+4],ecx ; file offset
mov [ebp+28],ecx ; cache_offset
mov DWORD PTR [ebp+12],8192 ; NumberOfBytesToRead
mov DWORD PTR [ebp+16],OFFSET MixBuf ; lpBuffer
mov ebx,ebp
push 70
pop eax
int 40h
jmp file_read_begin
 
if INFO_API_ON
PUBLIC _uFMOD_GetTitle
_uFMOD_GetTitle:
mov eax,OFFSET szTtl
ret
endif
 
else
uFMOD_mem dd mem_open, mem_read
if XM_FILE_ON
uFMOD_fs dd file_open, file_read
endif
 
szInfinity db "INFINITY",0
 
if JUMP_TO_PAT_ON
 
; Jump to the given pattern
PUBLIC _uFMOD_Jump2Pattern
_uFMOD_Jump2Pattern:
mov eax,[esp+4]
mov ecx,OFFSET _mod+36
movzx eax,ax
and DWORD PTR [ecx+FMUSIC_MODULE.nextrow-36],0
cmp ax,[ecx+FMUSIC_MODULE.numorders-36]
sbb edx,edx
and eax,edx
mov [ecx+FMUSIC_MODULE.nextorder-36],eax
ret
endif
 
if VOL_CONTROL_ON
 
; Set global volume [0: silence, 25: max. volume]
vol_scale dw 1 ; -45 dB
dw 130 ; -24
dw 164 ; -23
dw 207 ; -22
dw 260 ; -21
dw 328 ; -20
dw 413 ; -19
dw 519 ; -18
dw 654 ; -17
dw 823 ; -16
dw 1036 ; -15
dw 1305 ; -14
dw 1642 ; -13
dw 2068 ; -12
dw 2603 ; -11
dw 3277 ; -10
dw 4125 ; -9
dw 5193 ; -8
dw 6538 ; -7
dw 8231 ; -6
dw 10362 ; -5
dw 13045 ; -4
dw 16423 ; -3
dw 20675 ; -2
dw 26029 ; -1
dw 32768 ; 0 dB
PUBLIC _uFMOD_SetVolume
_uFMOD_SetVolume:
mov eax,[esp+4]
cmp eax,25
jna get_vol_scale
push 25
pop eax
get_vol_scale:
mov ax,[vol_scale+eax*2]
mov [ufmod_vol],eax
ret
endif
 
if PAUSE_RESUME_ON
 
; Pause the currently playing song.
PUBLIC _uFMOD_Pause
_uFMOD_Pause:
mov al,1
jmp $+4
 
; Resume the currently paused song.
PUBLIC _uFMOD_Resume
_uFMOD_Resume:
xor eax,eax
mov BYTE PTR [ufmod_pause_],al
ret
endif
 
if INFO_API_ON
 
; Return currently playing signal stats:
; lo word : RMS volume in R channel
; hi word : RMS volume in L channel
PUBLIC _uFMOD_GetStats
_uFMOD_GetStats:
push 4
jmp _uFMOD_InfoApi
 
; Return currently playing row and order:
; lo word : row
; hi word : order
PUBLIC _uFMOD_GetRowOrder
_uFMOD_GetRowOrder:
push 8
jmp _uFMOD_InfoApi
 
; Return the time in milliseconds since the song was started.
PUBLIC _uFMOD_GetTime
_uFMOD_GetTime:
push 0
_uFMOD_InfoApi:
pop edx
mov eax,[time_ms+edx]
ret
endif
 
; ***********************
; * XM_MEMORY CALLBACKS *
; ***********************
mem_read:
; buf in EAX
; size in EDX
push edi
push esi
xchg eax,edi ; buf
mov esi,OFFSET mmf
lodsd
mov ecx,edx
add edx,[esi]
cmp edx,eax
jl copy
sub eax,[esi]
xchg eax,ecx
copy:
test ecx,ecx
jle mem_read_R
lodsd
add eax,[esi]
mov [esi-4],edx
mem_do_copy:
mov dl,[eax]
mov [edi],dl
inc eax
inc edi
dec ecx
jnz mem_do_copy
mem_read_R:
pop esi
pop edi
if INFO_API_ON
PUBLIC _uFMOD_GetTitle
_uFMOD_GetTitle:
mov eax,OFFSET szTtl
endif
mem_open:
ret
 
; *********************
; * XM_FILE CALLBACKS *
; *********************
if XM_FILE_ON
file_open:
; pszName in ESI
; Prepare the FILE struct for subsecuent I/O:
lea eax,[ebp+8] ; file_struct
xor edx,edx
mov [eax],edx ; +0 subfunction: 0 = read
mov [eax+8],edx ; +8 Reserved
; +12 NumberOfBytesToRead
; +16 lpBuffer
push -1
push 1
mov [eax+20],dl ; +20 db 0
mov [eax+21],esi ; +21 lpFileName
pop DWORD PTR [eax+28] ; cache_offset
pop DWORD PTR [eax-28] ; [mmf] = maximum size
ret
 
file_read:
; buf in EAX
; size in EDX
push ebx
push esi
push edi
push ebp
xchg eax,edi
file_read_begin:
test edx,edx
jg file_read_chk_cache
file_read_done:
pop ebp
pop edi
pop esi
pop ebx
ret
; *** CHECK IN THE CACHE
file_read_chk_cache:
mov ebp,OFFSET file_struct
mov esi,[ebp-24]
sub esi,[ebp+28] ; cache_offset
js file_read_cache_done
mov ecx,8192
sub ecx,esi
jle file_read_cache_done
add esi,OFFSET MixBuf
sub edx,ecx
jns file_read_do_cache
add ecx,edx
file_read_do_cache:
add [ebp-24],ecx
rep movsb
test edx,edx
jle file_read_done ; data read from the cache (no need to access the FS)
file_read_cache_done:
; *** FS BATCH READ OPERATION
mov eax,[ebp-24]
mov ecx,edx
add ecx,eax
and ecx,0FFFFE000h
sub ecx,eax
jle file_read_fs_done ; Too few data requested for a FS batch operation
sub edx,ecx
mov [ebp+4],eax ; file offset
mov [ebp+12],ecx ; NumberOfBytesToRead
mov [ebp+16],edi ; lpBuffer
mov ebx,ebp
add edi,ecx
push 70
add [ebp-24],ecx
pop eax
int 40h
file_read_fs_done:
; *** UPDATE THE CACHE
mov ecx,[ebp-24]
and ecx,0FFFFE000h
mov [ebp+4],ecx ; file offset
mov [ebp+28],ecx ; cache_offset
mov DWORD PTR [ebp+12],8192 ; NumberOfBytesToRead
mov DWORD PTR [ebp+16],OFFSET MixBuf ; lpBuffer
mov ebx,ebp
push 70
pop eax
int 40h
jmp file_read_begin
endif
 
endif ; AC97SND_ON = 0
 
uFMOD_lseek:
; pos in EAX
; org in ECX
; !org in Z
mov edx,OFFSET mmf+4
jz mem_ok
add eax,[edx]
mem_ok:
test eax,eax
js mem_seek_R
cmp eax,[edx-4]
ja mem_seek_R
mov [edx],eax
mem_seek_R:
ret
 
; Dynamic memory allocation
alloc:
; EAX: how many bytes to allocate
add eax,3
and eax,-4
jle alloc_error2
mov ecx,OFFSET ufmod_heap
alloc_lookup:
cmp DWORD PTR [ecx],0
je do_alloc
mov ecx,[ecx]
cmp [ecx+4],eax
jl alloc_lookup
sub [ecx+4],eax
mov eax,[ecx+4]
lea eax,[eax+ecx+8]
ret
do_alloc:
add eax,8
push ebx
push edi
mov ebx,eax
add ebx,8191
neg eax
and ebx,-8192
push ecx
add eax,ebx
xchg eax,edi
push 12
push 68
mov ecx,ebx
pop eax
pop ebx
int 40h
; Test for error condition
test eax,eax
pop ebx
mov edx,edi ; free space
jz alloc_error1
mov [ebx],eax
mov edi,eax
lea eax,[eax+edx+8]
mov [edi+4],edx
pop edi
pop ebx
ret
alloc_error1:
pop edi
pop ebx
alloc_error2:
xor eax,eax
pop edx ; EIP
pop ebx
leave
_alloc_R:
ret
 
; Starts playing a song.
PUBLIC _uFMOD_LoadSong
_uFMOD_LoadSong:
 
; *** FREE PREVIOUS TRACK, IF ANY
call _uFMOD_StopSong
 
if AC97SND_ON
mov ecx,[esp+4]
push ebx
push esi
push edi
push ebp
mov ebp,OFFSET uFMOD_fopen
; Prepare the FILE struct for subsecuent I/O:
lea eax,[ebp+8] ; file_struct
xor edx,edx
mov [eax],edx ; +0 subfunction: 0 = read
mov [eax+8],edx ; +8 Reserved
; +12 NumberOfBytesToRead
; +16 lpBuffer
mov [eax+20],dl ; +20 db 0
mov [eax+21],ecx ; +21 lpFileName
push -1
push 1
mov DWORD PTR [ebp+4],OFFSET file_read ; uFMOD_fread
pop DWORD PTR [eax+28] ; cache_offset
mov [eax-24],edx
pop DWORD PTR [eax-28] ; [mmf] = maximum size
else
mov eax,[esp+8] ; param
mov ecx,[esp+12] ; fdwSong
mov edx,[esp+4] ; lpXM
test edx,edx
jz _alloc_R
; *** SET I/O CALLBACKS
push ebx
push esi
push edi
push ebp
mov ebp,OFFSET uFMOD_fopen
mov [ebp-20],eax ; mmf
xor eax,eax
mov [ebp-16],eax ; mmf+4
test cl,XM_MEMORY
mov esi,OFFSET uFMOD_mem
if XM_FILE_ON
jnz set_callbacks
test cl,XM_FILE
lea esi,[esi+(uFMOD_fs-uFMOD_mem)]
endif
jz goto_StopSong
set_callbacks:
if NOLOOP_ON
test cl,XM_NOLOOP
setnz [ebp-24] ; ufmod_noloop
endif
if PAUSE_RESUME_ON
and cl,XM_SUSPENDED
mov [ebp-23],cl ; ufmod_pause_
endif
mov edi,ebp ; uFMOD_fopen
movsd
movsd
mov esi,edx ; uFMOD_fopen:lpXM <= ESI
if VOL_CONTROL_ON
cmp [ebp-4],eax ; ufmod_vol
jne play_vol_ok
mov WORD PTR [ebp-4],32768
play_vol_ok:
endif
xor edi,edi
; *** INIT THE INFINITY DRIVER
lea eax,[edi+68]
lea ebx,[edi+16]
mov ecx,OFFSET szInfinity
int 40h
test eax,eax
mov [hSound],eax
jz goto_StopSong
if DEBUG
mov edx,OFFSET sDBGMSG2
call DBG_print_s
endif
; *** CHECK THE DRIVER VERSION
push edi ; ver = 0
push esp ; &ver
mov edx,esp
push 4 ; .out_size
push edx ; .output = &&ver
push edi ; .inp_size
push edi ; .input
push edi ; .code = SRV_GETVERSION
push eax ; .handle = [hSound]
lea ebx,[edi+17]
lea eax,[edi+68]
mov ecx,esp
int 40h
add esp,28
pop eax ; ver
if DEBUG
mov edx,OFFSET sDBGMSG5
call DBG_print_s
call DBG_print_x
endif
shr eax,16
cmp eax,SOUND_VERSION
ja _uFMOD_StopSong+4 ; obsolete program version (Hint: try adjusting SOUND_VERSION!)
; *** ALLOCATE A HEAP OBJECT
lea eax,[edi+68]
lea ebx,[edi+11]
int 40h
test eax,eax
jz goto_StopSong
; *** LOAD THE TRACK
mov [ebp-12],esi ; mmf+8 <= pMem
if XM_FILE_ON
call DWORD PTR [ebp] ; uFMOD_fopen
endif
 
endif ; AC97SND_ON = 0
 
call LoadXM
test eax,eax
goto_StopSong:
jz _uFMOD_StopSong+4
if DEBUG
mov edx,OFFSET sDBGMSG1
call DBG_print_s
endif
 
if AC97SND_ON
else
xor edi,edi
; *** CREATE THE PCM BUFFER
push edi ; size (default is 64Kb)
push PCM_format ; format: 16-bit / stereo / sampling rate
mov edx,esp
push OFFSET hBuff
mov eax,esp
push 4 ; .out_size
push eax ; .output = &&hBuff
push 8 ; .inp_size
push edx ; .input
push 1 ; .code = SND_CREATE_BUFF
push DWORD PTR [hSound] ; .handle
lea eax,[edi+68]
lea ebx,[edi+17]
mov ecx,esp
int 40h
pop esi ; <- hSound
add esp,32
test eax,eax
jnz _uFMOD_StopSong+4 ; buffer not created
if DEBUG
mov edx,OFFSET sDBGMSG3
call DBG_print_s
endif
xchg eax,esi ; return the driver handle
endif ; AC97SND_ON = 0
 
; *** ENABLE PCM OUTPUT
mov [SW_Exit],eax
pop ebp
pop edi
pop esi
pop ebx
ret
 
; Stop the currently playing song, if any, and free all resources allocated for that song.
PUBLIC _uFMOD_StopSong
_uFMOD_StopSong:
push ebx
push esi
push edi
push ebp
; _uFMOD_StopSong+4
xor edi,edi
mov ebp,OFFSET ufmod_heap
; *** DISABLE PCM OUTPUT
mov [ebp+16],edi ; SW_Exit
 
if AC97SND_ON
else
; *** STOP AND DESTROY THE PCM BUFFER
mov eax,[ebp+12] ; hBuff
test eax,eax
jz SND_buffer_free
push eax ; buffer
mov edx,esp
push edi ; .out_size
push edi ; .output
push 4 ; .inp_size
push edx ; .input
push 11 ; .code = SND_STOP
push DWORD PTR [ebp+8] ; .handle = [hSound]
lea eax,[edi+68]
lea ebx,[edi+17]
mov ecx,esp
int 40h
mov DWORD PTR [esp+4],2 ; .code = SND_DESTROY_BUFF
lea eax,[edi+68]
int 40h
add esp,28
if DEBUG
mov edx,OFFSET sDBGMSG4
call DBG_print_s
endif
SND_buffer_free:
mov [ebp+12],edi ; hBuff
endif ; AC97SND_ON = 0
 
; *** FREE THE HEAP
mov esi,[ebp] ; ufmod_heap
heapfree:
test esi,esi
jz free_R
mov ecx,esi
mov esi,[esi]
lea eax,[edi+68]
lea ebx,[edi+13]
int 40h
jmp heapfree
free_R:
xor eax,eax
 
if AC97SND_ON
else
if INFO_API_ON
; *** CLEAR THE INFO API DATA
lea ecx,[eax+4]
mov edi,OFFSET time_ms
rep stosd
endif
endif ; AC97SND_ON = 0
 
mov DWORD PTR [ebp],eax ; ufmod_heap
pop ebp
pop edi
pop esi
pop ebx
ret
 
PUBLIC _uFMOD_WaveOut
_uFMOD_WaveOut:
push edi
push ebp
xor edi,edi
 
if AC97SND_ON
; *** PCM OUTPUT ENABLED?
cmp DWORD PTR [SW_Exit],edi
lea eax,[edi+1] ; return error if output not enabled
je _uFMOD_WaveOut_R
; *** COMPUTE THE NUMBER OF FREE BLOCKS AVAILABLE
lea ecx,[esp+12] ; &hBuff
push edi ; space = 0
mov edx,esp
push 4 ; .out_size
push edx ; .output = &space
push 4 ; .inp_size
push ecx ; .input
push 17 ; .code = SND_GETFREESPACE
mov ecx,[ecx]
push DWORD PTR [hSound] ; .handle
mov [hBuff],ecx
else
mov ebp,OFFSET hSound
; *** PCM OUTPUT ENABLED?
cmp [ebp+8],edi ; SW_Exit
lea eax,[edi+1] ; return error if output not enabled
je _uFMOD_WaveOut_R
; *** COMPUTE THE NUMBER OF FREE BLOCKS AVAILABLE
push edi ; space = 0
mov edx,esp
push 4 ; .out_size
lea ecx,[ebp+4] ; &hBuff
push edx ; .output = &space
push 4 ; .inp_size
push ecx ; .input
push 17 ; .code = SND_GETFREESPACE
push DWORD PTR [ebp] ; .handle = [hSound]
endif ; AC97SND_ON = 0
 
lea ebx,[edi+17]
lea eax,[edi+68]
mov ecx,esp
int 40h
add esp,24
pop edi ; <- space
shr edi,FSOUND_Block+2 ; / (FSOUND_BlockSize * 4)
jz _uFMOD_WaveOut_R ; no free blocks available
_uFMOD_WaveOut_loop:
call uFMOD_do_WaveOut
neg eax
dec edi
ja _uFMOD_WaveOut_loop
_uFMOD_WaveOut_R:
pop ebp
pop edi
ret
 
uFMOD_do_WaveOut:
mov ecx,FSOUND_BlockSize*2
push ebx
push esi
push edi
mov edi,OFFSET MixBuf
xor eax,eax
push edi ; mixbuffer <= MixBuf
push edi ; <- MixPtr
; MIXBUFFER CLEAR
mov esi,OFFSET _mod+36
rep stosd
 
if AC97SND_ON
else
if PAUSE_RESUME_ON
cmp [ufmod_pause_],al
xchg eax,ebp
jne do_swfill
endif
endif ; AC97SND_ON = 0
 
mov ebp,FSOUND_BlockSize
; UPDATE MUSIC
mov ebx,[esi+FMUSIC_MODULE.mixer_samplesleft-36]
fill_loop_1:
test ebx,ebx
jnz mixedleft_nz
; UPDATE XM EFFECTS
cmp [esi+FMUSIC_MODULE.tick-36],ebx ; new note
mov ecx,[esi+FMUSIC_MODULE.pattern-36]
jne update_effects
dec ebx
; process any rows commands to set the next order/row
mov edx,[esi+FMUSIC_MODULE.nextorder-36]
mov eax,[esi+FMUSIC_MODULE.nextrow-36]
mov [esi+FMUSIC_MODULE.nextorder-36],ebx
test edx,edx
mov [esi+FMUSIC_MODULE.nextrow-36],ebx
jl fill_nextrow
mov [esi+FMUSIC_MODULE.order-36],edx
fill_nextrow:
test eax,eax
jl update_note
mov [esi+FMUSIC_MODULE.row-36],eax
update_note:
; mod+36 : ESI
call DoNote
if ROWCOMMANDS_ON
cmp DWORD PTR [esi+FMUSIC_MODULE.nextrow-36],-1
jne inc_tick
endif
mov eax,[esi+FMUSIC_MODULE.row-36]
inc eax
; if end of pattern
; "if(mod->nextrow >= mod->pattern[mod->orderlist[mod->order]].rows)"
cmp ax,[ebx]
jl set_nextrow
mov edx,[esi+FMUSIC_MODULE.order-36]
movzx ecx,WORD PTR [esi+FMUSIC_MODULE.numorders-36]
inc edx
xor eax,eax
cmp edx,ecx
jl set_nextorder
 
if AC97SND_ON
else
; We've reached the end of the order list. So, stop playing, unless looping is enabled.
if NOLOOP_ON
cmp [ufmod_noloop],al
je set_restart
pop eax ; skip MixPtr
pop edx ; skip mixbuffer
pop edi
inc eax ; end of loop reached while XM_NOLOOP flag is enabled
pop esi
pop ebx
ret
set_restart:
endif
endif ; AC97SND_ON = 0
 
movzx edx,WORD PTR [esi+FMUSIC_MODULE.restart-36]
cmp edx,ecx
sbb ecx,ecx
and edx,ecx
set_nextorder:
mov [esi+FMUSIC_MODULE.nextorder-36],edx
set_nextrow:
mov [esi+FMUSIC_MODULE.nextrow-36],eax
jmp inc_tick
update_effects:
; mod+36 : ESI
call DoEffs
inc_tick:
mov eax,[esi+FMUSIC_MODULE.speed-36]
mov ebx,[esi+FMUSIC_MODULE.mixer_samplespertick-36]
inc DWORD PTR [esi+FMUSIC_MODULE.tick-36]
if PATTERNDELAY_ON
add eax,[esi+FMUSIC_MODULE.patterndelay-36]
endif
cmp [esi+FMUSIC_MODULE.tick-36],eax
jl mixedleft_nz
if PATTERNDELAY_ON
and DWORD PTR [esi+FMUSIC_MODULE.patterndelay-36],0
endif
and DWORD PTR [esi+FMUSIC_MODULE.tick-36],0
mixedleft_nz:
mov edi,ebp
cmp ebx,edi
jae fill_ramp
mov edi,ebx
fill_ramp:
pop edx ; <- MixPtr
sub ebp,edi
lea eax,[edx+edi*8]
push eax ; MixPtr += (SamplesToMix<<3)
; tail : [arg0]
; len : EDI
; mixptr : EDX
; _mod+36 : ESI
call Ramp
 
if AC97SND_ON
else
if INFO_API_ON
lea eax,[edi+edi*4]
cdq
shl eax,2
mov ecx,FSOUND_MixRate/50
div ecx
; time_ms += SamplesToMix*FSOUND_OOMixRate*1000
add [time_ms],eax
endif
endif ; AC97SND_ON = 0
 
sub ebx,edi ; MixedLeft -= SamplesToMix
test ebp,ebp
jnz fill_loop_1
mov [esi+FMUSIC_MODULE.mixer_samplesleft-36],ebx ; <= MixedLeft
 
if AC97SND_ON
else
if INFO_API_ON
mov ecx,[esi + FMUSIC_MODULE.row-36]
or ecx,[esi + FMUSIC_MODULE.order-2-36]
mov DWORD PTR [s_row],ecx
endif
endif ; AC97SND_ON = 0
 
do_swfill:
; *** CLIP AND COPY BLOCK TO OUTPUT BUFFER
pop eax ; skip MixPtr
pop esi ; <- mixbuffer
 
if AC97SND_ON
else
if INFO_API_ON
; ebx : L channel RMS volume
; ebp : R channel RMS volume
xor ebx,ebx
endif
endif ; AC97SND_ON = 0
 
mov edi,esi
mov ecx,FSOUND_BlockSize*2
align 4
fill_loop_2:
lodsd
 
if AC97SND_ON
mov ebx,eax
cdq
xor eax,edx
sub eax,edx
mov ebp,255*volumerampsteps/2
xor edx,edx
div ebp
cmp edx,255*volumerampsteps/4
sbb eax,-1
cmp eax,8000h
sbb edx,edx
not edx
or eax,edx
sar ebx,31
and eax,7FFFh
xor eax,ebx
sub eax,ebx
else
if INFO_API_ON
push edi
cdq
mov edi,eax
push esi
xor eax,edx
mov esi,255*volumerampsteps/2
sub eax,edx
xor edx,edx
div esi
cmp edx,255*volumerampsteps/4
pop esi
sbb eax,-1
cmp eax,8000h
sbb edx,edx
not edx
or eax,edx
sar edi,31
and eax,7FFFh
if VOL_CONTROL_ON
mul DWORD PTR [ufmod_vol]
shr eax,15
endif
; sum. the L and R channel RMS volume
ror ecx,1
sbb edx,edx
and edx,eax
add ebp,edx ; += |vol|
rol ecx,1
sbb edx,edx
not edx
and edx,eax
add ebx,edx ; += |vol|
xor eax,edi
sub eax,edi
pop edi
else
mov ebx,eax
cdq
xor eax,edx
sub eax,edx
mov ebp,255*volumerampsteps/2
xor edx,edx
div ebp
cmp edx,255*volumerampsteps/4
sbb eax,-1
cmp eax,8000h
sbb edx,edx
not edx
or eax,edx
sar ebx,31
and eax,7FFFh
if VOL_CONTROL_ON
mul DWORD PTR [ufmod_vol]
shr eax,15
endif
xor eax,ebx
sub eax,ebx
endif
endif ; AC97SND_ON = 0
 
dec ecx
stosw
jnz fill_loop_2
 
if AC97SND_ON
else
if INFO_API_ON
shr ebp,FSOUND_Block ; R_vol / FSOUND_BlockSize
shl ebx,16-FSOUND_Block ; (L_vol / FSOUND_BlockSize) << 16
mov bx,bp
mov DWORD PTR [L_vol],ebx
endif
endif ; AC97SND_ON = 0
 
; *** DISPATCH DATA TO THE AC97 DRIVER
push FSOUND_BlockSize*4 ; size
push OFFSET MixBuf ; &src
push DWORD PTR [hBuff] ; buffer
mov edx,esp
push ecx ; .out_size
push ecx ; .output
push 12 ; .inp_size
push edx ; .input
push 9 ; .code = SND_OUT
push DWORD PTR [hSound] ; .handle
lea eax,[ecx+68]
lea ebx,[ecx+17]
mov ecx,esp
int 40h
add esp,36
pop edi
pop esi
pop ebx
ret
/programs/develop/libraries/ufmod/ufmod.inc
0,0 → 1,253
; uFMOD API reference (NORMAL/UNSAFE mode)
; ====================================================================
 
; NOTE: All functions follow the cdecl calling convention!
; _uFMOD_LoadSong
; _uFMOD_WaveOut
; _uFMOD_StopSong
; _uFMOD_Jump2Pattern
; _uFMOD_Pause
; _uFMOD_Resume
; _uFMOD_GetStats
; _uFMOD_GetRowOrder
; _uFMOD_GetTime
; _uFMOD_GetTitle
; _uFMOD_SetVolume
 
; ====================================================================
; HANDLE _uFMOD_LoadSong(
; void *lpXM,
; void *param,
; int fdwSong
; )
; ---
; Description:
; ---
; Loads the given XM song and starts playing it as soon as you
; call _uFMOD_WaveOut for the first time. Playback won't begin
; if XM_SUSPENDED flag is specified. It will stop any currently
; playing song before loading the new one.
; ---
; Parameters:
; ---
; lpXM
; Specifies the song to load. If this parameter is 0, any
; currently playing song is stopped. In such a case, function
; does not return a meaningful value. fdwSong parameter
; determines whether this value is interpreted as a filename
; or as a pointer to an image of the song in memory.
; param
; If XM_MEMORY is specified, this parameter should be the size
; of the image of the song in memory.
; If XM_FILE is specified, this parameter is ignored.
; fdwSong
; Flags for playing the song. The following values are defined:
; XM_FILE lpXM points to filename. param is ignored.
; XM_MEMORY lpXM points to an image of a song in memory.
; param is the image size. Once, _uFMOD_LoadSong
; returns, it's safe to free/discard the memory
; buffer.
; XM_NOLOOP An XM track plays repeatedly by default. Specify
; this flag to play it only once.
; XM_SUSPENDED The XM track is loaded in a suspended state,
; and will not play until the _uFMOD_Resume function
; is called. This is useful for preloading a song
; or testing an XM track for validity.
; ---
; Return Values:
; ---
; On success, returns the handle of the Infinity Sound driver.
; Returns 0 on failure.
 
; ====================================================================
; int _uFMOD_WaveOut(void)
; ---
; Description:
; ---
; Updates the internal playback buffer.
; ---
; Remarks:
; ---
; This function should be called from the same thread
; _uFMOD_LoadSong was previously called. Playback doesn't actually
; begin when calling _uFMOD_LoadSong, but when calling _uFMOD_WaveOut
; after a successful _uFMOD_LoadSong call. Afterwards, you should
; call _uFMOD_WaveOut repeatedly at least once every 250 ms to
; prevent "buffer underruns".
; _uFMOD_WaveOut is a non-blocking function. The accuracy of the
; InfoAPI functions (_uFMOD_GetStats, _uFMOD_GetRowOrder and
; _uFMOD_GetTime) depends on the periodicity of this function being
; invoked.
; ---
; Return Values:
; ---
; Returns non zero on error.
 
; ====================================================================
; void _uFMOD_StopSong(void)
; ---
; Description:
; ---
; Stops the currently playing song, freeing the associated
; resources.
; ---
; Remarks:
; ---
; Does nothing if no song is playing at the time the call is made.
 
; ====================================================================
; void _uFMOD_Jump2Pattern(
; unsigned int pat
; )
; ---
; Description:
; ---
; Jumps to the specified pattern index.
; ---
; Parameters:
; ---
; pat
; Next zero based pattern index.
; ---
; Remarks:
; ---
; uFMOD doesn't automatically perform Note Off effects before jumping
; to the target pattern. In other words, the original pattern will
; remain in the mixer until it fades out. You can use this feature to
; your advantage. If you don't like it, just insert leading Note Off
; commands in all patterns intended to be used as _uFMOD_Jump2Pattern
; targets.
; if the pattern index lays outside of the bounds of the pattern order
; table, calling this function jumps to pattern 0, effectively
; rewinding playback.
 
; ====================================================================
; void _uFMOD_Pause(void)
; ---
; Description:
; ---
; Pauses the currently playing song, if any.
; ---
; Remarks:
; ---
; While paused you can still control the volume (_uFMOD_SetVolume) and
; the pattern order (_uFMOD_Jump2Pattern). The RMS volume coefficients
; (_uFMOD_GetStats) will go down to 0 and the progress tracker
; (_uFMOD_GetTime) will "freeze" while the song is paused.
; _uFMOD_Pause doesn't perform the request immediately. Instead, it
; signals to pause when playback reaches next chunk of data.
; This way, _uFMOD_Pause performs asynchronously and returns very fast.
; It is not cumulative. So, calling _uFMOD_Pause many times in a row
; has the same effect as calling it once.
; You shouldn't stop calling _uFMOD_WaveOut while the song is paused!
 
; ====================================================================
; void _uFMOD_Resume(void)
; ---
; Description:
; ---
; Resumes the currently paused song, if any.
; ---
; Remarks:
; ---
; _uFMOD_Resume doesn't perform the request immediately. Instead, it
; signals to resume when _uFMOD_WaveOut is called again. _uFMOD_Resume
; is not cumulative. So, calling it many times in a row has the same
; effect as calling it once.
 
; ====================================================================
; unsigned int _uFMOD_GetStats(void)
; ---
; Description:
; ---
; Returns the current RMS volume coefficients in (L)eft and (R)ight
; channels.
; low-order word: RMS volume in R channel
; hi-order word: RMS volume in L channel
; Range from 0 (silence) to $7FFF (maximum) on each channel.
; ---
; Remarks:
; ---
; This function is useful for updating a VU meter. It's recommended
; to rescale the output to log10 (decibels or dB for short), because
; human ears track volume changes in a dB scale. You may call
; _uFMOD_GetStats() as often as you like, but take in mind that uFMOD
; updates both channel RMS volumes at the same rate _uFMOD_WaveOut
; function is called. In other words, you should call _uFMOD_WaveOut
; more often to increase the accuracy of _uFMOD_GetStats.
 
; ====================================================================
; unsigned int _uFMOD_GetRowOrder(void)
; ---
; Description:
; ---
; Returns the currently playing row and order.
; low-order word: row
; hi-order word: order
; ---
; Remarks:
; ---
; This function is useful for synchronization. uFMOD updates both
; row and order values at the same rate _uFMOD_WaveOut function is
; called. In other words, you should call _uFMOD_WaveOut more often
; to increase the accuracy of _uFMOD_GetRowOrder.
 
; ====================================================================
; unsigned int _uFMOD_GetTime(void)
; ---
; Description:
; ---
; Returns the time in milliseconds since the song was started.
; ---
; Remarks:
; ---
; This function is useful for synchronizing purposes. Multimedia
; applications can use _uFMOD_GetTime to synchronize GFX to sound,
; for example. An XM player can use this function to update a progress
; meter.
 
; ====================================================================
; unsigned char* _uFMOD_GetTitle(void)
; ---
; Description:
; ---
; Returns the current song's title.
; ---
; Remarks:
; ---
; Not every song has a title, so be prepared to get an empty string.
 
; ====================================================================
; void _uFMOD_SetVolume(
; unsigned int vol
; )
; ---
; Description:
; ---
; Sets the global volume. The volume scale is linear.
; ---
; Parameters:
; ---
; vol
; New volume. Range: from uFMOD_MIN_VOL (muting) to uFMOD_MAX_VOL
; (maximum volume). Any value above uFMOD_MAX_VOL maps to maximum
; volume.
; ---
; Remarks:
; ---
; uFMOD internally converts the given values to a logarithmic scale (dB).
; Maximum volume is set by default. The volume value is preserved across
; _uFMOD_LoadSong calls. You can set the desired volume level before
; actually starting to play a song.
; You can use Infinity Sound API to control the L and R channels volumes
; separately. It also has a wider range than _uFMOD_SetVolume, sometimes
; allowing to amplify the sound volume as well, as opposed to
; _uFMOD_SetVolume only being able to attenuate it.
 
XM_MEMORY equ 1
XM_FILE equ 2
XM_NOLOOP equ 8
XM_SUSPENDED equ 16
uFMOD_MIN_VOL equ 0
uFMOD_MAX_VOL equ 25
uFMOD_DEFAULT_VOL equ 25
/programs/develop/libraries/ufmod
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property