; 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