This is a simple hangman game, nasmx version. Text labels have an annoying colorless defect, sorry. I cannot upload an icon, so, you can comment it from code. Sorry for inconvenients.
Code:
; ----------------------------------------------------------------------------
; - TITULO : Ejemplo de ventana en Windows W-NASM -
; ----- -----
; - AUTOR : Alfonso Víctor Caballero Hurtado -
; ----- -----
; - VERSION : 1.0 -
; ----- -----
; - (c) 2010. Abre los Ojos al Ensamblador -
; ----------------------------------------------------------------------------
%include 'C:\Compila\NASMX\inc\nasmx.inc' ; Incluímos
%include 'C:\Compila\NASMX\inc\win32\windows.inc' ; Incluímos
%include 'C:\Compila\NASMX\inc\win32\kernel32.inc' ; Importamos
%include 'C:\Compila\NASMX\inc\win32\user32.inc' ; Importamos
%include 'C:\Compila\NASMX\inc\win32\gdi32.inc' ; Importamos
cdWords EQU 15 ; Número de palabras
cdXPos EQU 28 ; Constante double X-Posición de la
cdYPos EQU 100 ; Constante double Y-Posición de la ventana(esq sup izqda)
cdXSize EQU 310 ; Constante double X-tamaño de la ventana
cdYSize EQU 200 ; Constante double Y-tamaño de la ventana
cdColFondo EQU COLOR_BTNFACE + 1 ; Color de fondo de la ventana: gris de un botón de comando
cdVIcono EQU 100 ; Icono de la ventana, véase Resource.H
cdVCursor EQU IDC_ARROW ; Cursor para la ventana
cdVBarTipo EQU NULL ; Normal, con icono
cdVBtnTipo EQU WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU ; Normal sólo con botón cerrar
cdFXPos1 EQU 50
cdFYPos1 EQU 70
cdFXPos2 EQU 50
cdFYPos2 EQU 30
cdFSize EQU 20 ; Tamaño del texto
entry Entrada
[section .text]
proc Entrada
invoke GetModuleHandleA, dword NULL
mov [wc + WNDCLASSEX.hInstance], eax
INVOKE GetCommandLineA
mov [CommandLine], EAX
invoke WinMain, dword wc + WNDCLASSEX.hInstance, dword NULL, dword CommandLine, dword SW_SHOWNORMAL
invoke ExitProcess, dword NULL
ret
endproc
proc WinMain
; Propósito: Inicializamos la ventana principal de la aplicación y captura errores, si los hubiere
; Entrada : hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
; Salida : Ninguna
; Destruye : Ninguna
; Recogemos los parámetros
hinst argd ; Current instance handle - enganche a la instancia actual
hpinst argd ; Previous instance handle- enganche a la instancia previa
cmdln argd ; Command line arguments - argumentos de la línea de comandos
dwshow argd ; Display style - Estilo de despliegue
invoke LoadIconA, dword NULL, dword cdVIcono
mov edx, eax
mov eax, dword argv(hinst)
mov ebx, dword NombreClase
mov ecx, dword WndProc
MOV [wc + WNDCLASSEX.hbrBackground], dword cdColFondo ; Color de fondo de la ventana
mov [wc + WNDCLASSEX.hInstance], eax
mov [wc + WNDCLASSEX.lpszClassName], ebx
mov [wc + WNDCLASSEX.lpfnWndProc], ecx
mov [wc + WNDCLASSEX.hIcon], edx
mov [wc + WNDCLASSEX.hIconSm], edx
invoke LoadCursorA, NULL, cdVCursor
mov [wc + WNDCLASSEX.hCursor], eax
invoke RegisterClassExA, dword wc
test eax, eax
jz L_Error
invoke CreateWindowExA, dword cdVBarTipo, dword NombreClase, dword MsgCabecera, dword cdVBtnTipo,dword cdXPos, dword cdYPos, dword cdXSize, dword cdYSize, dword NULL, dword NULL, dword [wc + WNDCLASSEX.hInstance], dword NULL
test eax, eax
jz L_Error
mov [hWnd], eax
invoke ShowWindow, dword hWnd, dword SW_SHOWNORMAL
invoke UpdateWindow, dword hWnd
.msgloop:
invoke GetMessageA, dword message, dword NULL, dword NULL, dword NULL
cmp eax, dword 0
je end_loop
invoke TranslateMessage, dword message
invoke DispatchMessageA, dword message
jmp .msgloop
L_Error:
invoke MessageBoxA, DWORD NULL, DWORD MsgError, NULL, DWORD MB_ICONERROR+MB_OK
end_loop:
mov eax, dword [message + MSG.wParam]
ret
endproc
proc WndProc
; Propósito: Procesa los mensajes provenientes de las ventanas
; Entrada : hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
; Salida : Ninguna
; Destruye : Ninguna
; Recogemos los parámetros
hwnd argd ; Window handle
umsg argd ; Window message
wparam argd ; wParam
lparam argd ; lParam
mov eax, argv(umsg)
cmp eax, dword WM_PAINT
je .wmpaint
cmp eax, dword WM_DESTROY
je .wmdestroy
cmp eax, dword WM_CHAR
je .wmchar
cmp eax, dword WM_CREATE
je .wmcreate
.defwndproc:
invoke DefWindowProcA,dword argv(hwnd), dword argv(umsg), dword argv(wparam), dword argv(lparam)
jmp .finish
.wmpaint:
invoke BeginPaint,dword argv(hwnd), ps
mov [hdc], eax
; Aquí dibujamos la palabra a descubrir
invoke SetBkColor,[ps+PAINTSTRUCT.hdc],dword 0 ; Color de fondo
invoke SetTextColor,[ps+PAINTSTRUCT.hdc],0FFFFFFh ; Color del texto
invoke SelectObject, [hdc], [hGuessNFont]
mov [hGuessOFont], eax
invoke lstrlenA, MsgTexto2
invoke TextOutA, [hdc], cdFXPos2,cdFYPos2, MsgTexto2, eax
; Aquí ponemos lo que nos queda
invoke SetBkColor,[ps+PAINTSTRUCT.hdc],011A3FBh ; Color de fondo
invoke SetTextColor,[ps+PAINTSTRUCT.hdc],0FFh ; Color del texto
invoke SelectObject, [hdc], [hAttemNFont]
mov [hAttemOFont], eax
invoke lstrlenA, msgIntentos
invoke TextOutA, [hdc], cdFXPos1,cdFYPos1, msgIntentos, eax
invoke EndPaint,dword argv(hwnd),ps
; Aquí comprobamos qué tal ha ido la cosa
or byte [vbQueda], 0 ; ¿Quedan intentos?
jnz .Aciertos
invoke MessageBoxA,dword argv(hwnd),msgLoose,msgCabecera,MB_YESNO+MB_ICONERROR
CMP EAX, IDNO ; yes->eax=6, no->eax=7
JNE .repetir
jmp .wmdestroy
.Aciertos:
mov al, [vbAciertos] ; ¿Hemos acertado todas las letras?
cmp byte [vdLong], al
jnz .finish
invoke MessageBoxA,dword argv(hwnd),msgSuccess,msgCabecera,MB_YESNO+MB_ICONEXCLAMATION
CMP EAX, IDNO ; yes->eax=6, no->eax=7
JNE .repetir
jmp .wmdestroy
jmp .finish
.wmchar:
push dword argv(wparam)
pop eax
and al, 1011111b ; Lo convertimos a mayúsculas
mov BYTE [vbLetra], al
invoke chkLetrasUsadas ; Comprobamos que no la hayamos usado ya
JZ .YaUsada
invoke chkLetra
.YaUsada:
invoke SetWindowTextA,[vwdIntentos], msgUsedKeys ; Con esto cambiamos el texto
invoke InvalidateRect, dword argv(hwnd), dword 0, 1
jmp .finish
.wmcreate:
invoke GetTickCount
mov [seed], eax
invoke MakeFont,cdFSize,szCourierNew
mov [hGuessNFont], eax
invoke MakeFont,14,szVerdana
mov [hAttemNFont], eax
; Creamos el label de los intentos que quedan
invoke CreateWindowExA,dword 0,szStatic,msgUsedKeys,\
WS_CHILD + WS_VISIBLE + SS_CENTER,35, 90, 190, 30,\
dword argv(hwnd),500,[wc + WNDCLASSEX.hInstance],dword 0
mov [vwdIntentos], eax
invoke SendMessageA,eax,WM_SETFONT,dword 0,0
; Creamos el label del autor
invoke CreateWindowExA,dword 0,szStatic,msgAutor,\
WS_CHILD + WS_VISIBLE + SS_CENTER,15,120, 270, 70,\
dword argv(hwnd),500,[wc + WNDCLASSEX.hInstance],dword 0
mov [vwdAutor], eax
invoke SendMessageA,eax,WM_SETFONT,dword 0,0
invoke Inicializa, dword argv(hwnd)
jmp .finish
.repetir:
invoke Inicializa, dword argv(hwnd)
jmp .finish
.wmdestroy:
invoke DeleteObject, [hGuessNFont]
invoke DeleteObject, [hGuessOFont]
invoke DeleteObject, [hAttemNFont]
invoke DeleteObject, [hAttemOFont]
invoke PostQuitMessage,dword NULL
xor eax,eax
.finish:
ret
endproc
proc MakeFont ;pSize, pFontName
pSize argd
pFontName argd
invoke CreateFontA, dword argv(pSize),0,0,0, FW_BOLD, FALSE,FALSE,FALSE, \
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, \
DEFAULT_QUALITY, 18, dword argv(pFontName)
ret
endproc
chkLetrasUsadas:
; Propósito: Comprobamos si ya se ha usado una letra, se guarda en matriz de usadas
; Entrada : vbLetra
; Salida : ZF:1 -> ya fue usada, ZF:0 -> no fue usada
mov al, byte [vbLetra]
cmp byte [vbContLetras], 0
jnz .Siguiente
; Si aún no hemos pulsado una tecla, es que no la hemos usado
mov byte [vsmLetras], al ; Lo guardamos en la matriz de las letras
inc byte [vbContLetras]
; Devolvemos ZF=0
jmp @Exit
.Siguiente:
; Si ya hemos usado algunas letras, vamos a ver si son de las ya usadas
xor ecx, ecx
mov cl, byte [vbContLetras]
mov ebx, ecx
mov edi, vsmLetras
repne scasb
jz @Exit ; Si lo hubiéramos encontrado, saltaríamos
; Si estamos aquí es porque no lo hemos encontrado, lo incorporamos
mov byte [vsmLetras+ebx], al ; Lo guardamos en la matriz de las letras
inc byte [vbContLetras]
; Devolvemos ZF=0
@Exit:
ret
chkLetra:
; Propósito: Busca la letra pulsada en toda la palabra
; Entrada : vbLetra, vpPalabra: puntero a la palabra, vdLong: longitud palabra
; Salida : Ninguna
mov ecx, dword [vdLong]
mov edi, dword [vpPalabra]
mov al, byte [vbLetra]
mov ah, 0 ; Suponemos que no hemos encontrado ninguna ocurrencia
@RepetirBusqueda:
repne scasb
jne @NoEncontrado
; Si estamos aquí es porque hemos encontrado la letra en la palabra
mov ebx, dword [vdLong]
sub ebx, ecx
dec ebx
shl ebx, 1
mov byte [MsgTexto2+ebx], al
inc byte [vbAciertos]
mov ah, 1 ; Hemos encontrado al menos una ocurrencia
jnz @RepetirBusqueda
@NoEncontrado:
cmp ah, 1
jz @fin
dec byte [vbQueda]
invoke ActualizaIntentos
@fin:
ret
setWord:
; Propósito: Escoge una palabra de la lista que deberemos adivinar
; Entrada : Ninguna
; Salida : esi -> apunta a la palabra a adivinar
mov eax, cdWords
invoke Random ; eax
inc eax
mov edx, eax
mov ecx, cdLonMatriz
mov edi, Palabras
mov al, 0
@Bucle:
mov esi, edi
dec edx
jz @FinBucle
repne scasb
jmp @Bucle
@FinBucle:
mov dword [vpPalabra], esi
invoke lstrlenA, esi
mov dword [vdLong], eax
.Fin:
ret
ActualizaIntentos:
; Propósito: Actualizamos los intentos en msgIntentos
; Entrada : vbQueda
; Salida : Ninguna
mov al, [vbQueda]
or al, 30h
mov byte [msgIntentos+9], al
ret
proc Inicializa ;pWnd
; Propósito: Inicializa el juego
; Entrada : Ninguna
; Salida : Ninguna
pWnd argd
mov byte [vbContLetras], 0
mov byte [vbAciertos], 0
mov edi, vsmLetras ; Inicializa matriz de teclas usadas
mov eax, 20202020h
mov ecx, 4
rep stosd
invoke setWord
invoke setMsgTexto
mov eax, [vdLong]
shr eax, 1
mov [vbQueda], al
invoke ActualizaIntentos
invoke SetWindowTextA,[vwdIntentos], msgUsedKeys ; Con esto cambiamos el texto
invoke InvalidateRect, dword argv(pWnd), dword 0, 1
ret
endproc
setMsgTexto:
; Propósito: Establecemos MsgTexto
; Entrada : vdLong -> longitud de la palabra a adivinar
; Salida : ninguna
push ecx
push esi
push edi
mov esi, vsGuion
mov ecx, dword [vdLong]
mov edi, MsgTexto2
rep movsw
dec edi
mov al, 0
stosb
pop edi
pop esi
pop ecx
ret
proc Random
; Propósito: Calculamos un número aleatorio en [0..eax-1] by Park Miller
; Entrada : eax
; Salida : eax
; Destruye : Ninguna
mov ebx, eax
mov eax, dword [seed] ; from M32lib/nrand.asm
xor edx, edx
mov ecx, 127773
div ecx
mov ecx, eax
mov eax, 16807
mul edx
mov edx, ecx
mov ecx, eax
mov eax, 2836
mul edx
sub ecx, eax
xor edx, edx
mov eax, ecx
mov dword [seed], ecx
div ebx;[base]
mov eax, edx
ret
endproc
[section .bss]
CommandLine resd 1
seed resd 1 ;2037280626
vbContLetras resb 1 ; Contador de letras pulsadas
vbAciertos resb 1 ; Contador de letras acertadas
vbLetra resb 1 ; Letra pulsada
vpPalabra resd 1 ; Puntero a la palabra a buscar
vbQueda resb 1 ; Intentos que quedan
hdc resd 1
hGuessNFont resd 1
hGuessOFont resd 1
hAttemNFont resd 1
hAttemOFont resd 1
vdLong resd 1
vwdIntentos resd 1
vwdAutor resd 1
hWnd resd 1
[section .data]
szStatic db 'STATIC', 0
MsgCabecera db 'Hangman. 100% NASM(X) code',0
NombreClase db 'EXP01',0
msgCabecera db 'Information', 0
msgSuccess db 'You win. Play again?', 0
msgLoose db 'You loose. Play again?', 0
MsgError db 'Initial load failed.',0
msgIntentos db 'You have 0 attempts yet', 0
msgAutor db '(c) Abre los Ojos al Ensamblador', 13, 10
db 'http://www.abreojosensamblador.net', 0
vsGuion db '_ '
MsgTexto2 db ' ',0
msgUsedKeys db 'Used keys: '
vsmLetras: times 17 db 0 ; Matriz que recoge las letras pulsadas
szCourierNew DB "Courier New",0
szVerdana DB "Verdana",0
Palabras DB "HELLO", 0, "FANTASTIC", 0, "ENCOURAGE", 0
DB "RECTANGLE", 0, "SMALL", 0, "SQUALL", 0
DB "PAUNCH", 0, "FLAUNT", 0, "ESCAPE", 0
DB "AWARE", 0, "GALORE", 0, "SPREAD", 0
DB "STRAIGHT", 0, "FRIGHT", 0, "ACUSE", 0
cdLonMatriz equ $-Palabras
ps:
istruc PAINTSTRUCT
iend
wc:
istruc WNDCLASSEX
at WNDCLASSEX.cbSize, dd WNDCLASSEX_size
at WNDCLASSEX.style, dd CS_VREDRAW + CS_HREDRAW
at WNDCLASSEX.lpfnWndProc, dd NULL
at WNDCLASSEX.cbClsExtra, dd NULL
at WNDCLASSEX.cbWndExtra, dd NULL
at WNDCLASSEX.hInstance, dd NULL
at WNDCLASSEX.hIcon, dd NULL
at WNDCLASSEX.hCursor, dd NULL
at WNDCLASSEX.hbrBackground, dd cdColFondo
at WNDCLASSEX.lpszMenuName, dd NULL
at WNDCLASSEX.lpszClassName, dd NULL
at WNDCLASSEX.hIconSm, dd NULL
iend
message:
istruc MSG
at MSG.hwnd, dd NULL
at MSG.message, dd NULL
at MSG.wParam, dd NULL
at MSG.lParam, dd NULL
at MSG.time, dd NULL
at MSG.pt, dd NULL
iend
Resources:
#define IDR_VERSION1 1
#define MAIN_ICON 100
#define BUTTON_ICON 101
#define WINDOW_ICON 102
LANGUAGE 10,1
IDR_VERSION1 VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEOS 0x00000004
FILETYPE 0x00000000
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "FFFF0000"
BEGIN
VALUE "FileVersion", "1.0.0.0\0"
VALUE "ProductVersion", "1.0.0.0\0"
VALUE "CompanyName", "Abre los Ojos al Ensamblador\0"
VALUE "FileDescription", "Simple Hangman Game\0"
VALUE "InternalName", "HangWN01\0"
VALUE "LegalCopyright", "All rights reserved\0"
VALUE "OriginalFilename", "HangWN01.exe\0"
VALUE "ProductName", "HangWN01\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xFFFF, 0x0000
END
END
MAIN_ICON ICON DISCARDABLE "../Ico/Lazo.ico"
Batch process to compile:
del HangWN01.exe
C:\Compila\NASMX\bin\nasm -f win32 HangWN01.ASM -o HangWN01.obj
C:\Compila\NASMX\bin\GoRC.exe /r=HangWN01.res HangWN01.rc
C:\Compila\NASMX\bin\GoLink.exe /entry _main HangWN01.obj HangWN01.res kernel32.dll user32.dll gdi32.dll
del *.obj
del *.bak
Greetings from Madrid.