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 |