kolibrios/programs/games/mblocks/trunk/mblocks.asm

591 lines
9.6 KiB
NASM
Raw Normal View History

use32
db 'MENUET01'
dd 1
dd start
dd i_end
dd mem
dd mem
dd 0
dd 0
; field size in items
FieldWidth = 10
FieldHeight = 6
; size of one picture in pixels
ImageWidth = 32
ImageHeight = 32
; size of one button in pixels
ButtonWidth = ImageWidth + 6
ButtonHeight = ImageHeight + 6
SpaceWidth = ButtonWidth + 4
SpaceHeight = ButtonHeight + 4
; size of window in pixels
WindowWidth = 434
WindowHeight = 291 ; excluding skin height
if FieldWidth*FieldHeight mod 2
error field size must be an even number!
end if
draw_frame:
; in: ebx=[xstart]*65536+[xsize],ecx=[ystart]*65536+[ysize],edx=color
; ystart is relative to SkinHeight
; out: nothing
; destroys: eax,ecx
push 13
pop eax
ror ecx, 16
add ecx, [SkinHeight]
push ecx
shl ecx, 16
inc ecx
int 0x40 ; ebx=[xstart]*65536+[xsize], ecx=[ystart]*65536+1
ror ecx, 16
add cx, [esp+2]
ror ecx, 16
int 0x40 ; ebx=[xstart]*65536+[xsize], ecx=([ystart]+[ysize])*65536+1
pop ecx
ror ecx, 16
push ebx
mov bx, 1
int 0x40 ; ebx=[xstart]*65536+1, ecx=[ystart]*65536+[ysize]
ror ebx, 16
add bx, [esp]
ror ebx, 16
inc ecx
int 0x40 ; ebx=([xstart]+[xsize])*65536+1, ecx=[ystart]*65536+([ysize]+1)
dec ecx
pop ebx
ret
draw_button:
; in: ebx=[xstart]*65536+[xsize],ecx=[ystart]*65536+[ysize],edx=button color,esi=id
; ystart is relative to SkinHeight
; out: nothing
; destroys: eax
push edx
mov edx, 0x94AECE
call draw_frame
mov edx, 0xFFFFFF
push ebx
add ebx, 0xFFFF
push ecx
add ecx, 0x10000
mov cx, 1
int 0x40 ; ebx=([xstart]+1)*65536+([xsize]-1), ecx=([ystart]+1)*65536+1
pop ecx
mov edx, 0xC0C0C0
dec ebx
push ecx
shr ecx, 16
add ecx, [esp]
dec ecx
shl ecx, 16
inc ecx
int 0x40 ; ebx=([xstart]+1)*65536+([xsize]-2), ecx=([ystart]+[ysize]-1)*65536+1
pop ecx
mov edx, 0xFFFFFF
push ecx
add ecx, 0xFFFF
push ebx
mov bx, 1
int 0x40 ; ebx=([xstart]+1)*65536+1, ecx=([ystart]+1)*65536+([ysize]-1)
pop ebx
push ebx
shr ebx, 16
add ebx, [esp]
shl ebx, 16
inc ebx
mov edx, 0xC0C0C0
add ecx, 0xFFFF
int 0x40 ; ebx=([xstart]+[xsize]-1)*65536+1, ecx=([ystart]+2)*65536+([ysize]-2)
pop ebx
pop ecx
pop ebx
pop edx
push ebx ecx
add ebx, 20000h - 3
add ecx, 20000h - 3
int 0x40
pop ecx ebx
push edx
mov edx, esi
or edx, 0x80000000
mov al, 8
int 0x40
mov edx, esi
or edx, 0x40000000
int 0x40
pop edx
ret
;digits_ptr dd 0
;digits_str rb 11
;images:
; file 'mblocks.raw'
images:
file 'mblocksi.raw'
palette:
file 'mblocksp.raw'
aNewGame_ru db '<27><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>(F2)',0
aCount_ru db ' <20><><EFBFBD><EFBFBD>:',0
aRu db 'RU',0
aNewGame_en db 'New game (F2)',0
aCount_en db 'Count:',0
aEn db 'EN',0
CurLanguage db 0 ; 0=russian, 1=english
field_status rb 60 ; status of field elements: 0=closed, 1=temporarily opened, 2=permanently opened
field_items rb 60 ; items in field
count dd 0
start:
push 26
pop eax
push 5
pop ebx
int 0x40
cmp eax, 4
setnz [CurLanguage]
call generate
; get skin height
push 48
pop eax
push 4
pop ebx
int 0x40
mov [SkinHeight], eax
; no previous click
mov eax, 0xBAD
mov [FirstClick], eax
mov [SecondClick], eax
; draw window
redraw:
call draw_window
; events loop
evloop:
push 10
pop eax
int 0x40
dec eax
jz redraw
dec eax
jz key
mov al, 17
int 0x40
shr eax, 8
; cmp eax, 6
; jz set_lang
cmp eax, 5
jz new_game
cmp eax, 1
jnz field_pressed
push -1
pop eax
int 0x40
key:
mov al, 2
int 0x40
cmp ah, '3' ; F2?
jnz evloop
new_game:
mov edi, field_status
mov ecx, FieldWidth*FieldHeight/2
xor eax, eax
rep stosd
mov [count], eax
mov eax, 0xBAD
mov [FirstClick], eax
mov [SecondClick], eax
call generate
call draw_field
@@:
call draw_aux
jmp evloop
;set_lang:
; xor [CurLanguage], 1
; jmp @b
field_pressed:
sub eax, 100
cmp [field_status+eax], 0
jnz cont
mov ebx, [FirstClick]
mov ecx, [SecondClick]
cmp ebx, 0xBAD
jz first_click
cmp ecx, 0xBAD
jz second_click
mov dl, [field_items+ecx]
cmp [field_items+ebx], dl
jnz dont_match
mov [field_status+ebx], 2
mov [field_status+ecx], 2
jmp @f
dont_match:
mov [field_status+ebx], 0
mov [field_status+ecx], 0
@@:
push eax ecx
mov eax, ebx
call draw_field_item
pop eax
call draw_field_item
mov [SecondClick], 0xBAD
pop eax
mov [FirstClick], eax
jmp @f
second_click:
cmp [FirstClick], eax
jz cont
mov [SecondClick], eax
@@:
mov [field_status+eax], 1
call draw_field_item
inc [count]
cont:
call draw_count
jmp evloop
first_click:
mov [FirstClick], eax
jmp @b
draw_window:
push 48
pop eax
push 3
pop ebx
mov ecx, color_table
push 4*10
pop edx
int 0x40 ; get color table
push 12
pop eax
push 1
pop ebx
int 0x40 ; start redraw
push ebx
xor eax, eax
mov ebx, 100*65536 + WindowWidth
mov ecx, 100*65536 + WindowHeight
add ecx, [SkinHeight]
mov edx, 4C0C0C0h
int 0x40 ; define window
mov al, 71
pop ebx
mov ecx, caption
int 0x40 ; set caption
call draw_aux
call draw_field
push 12
pop eax
push 2
pop ebx
int 0x40
ret
caption db 'Memory Blocks L&V Edition',0
generate:
; generate random field
xor edi, edi
.loop:
call random
cmp [field_items+edx], 0
jnz .loop
mov eax, edi
shr eax, 1
inc eax
mov [field_items+edx], al
inc edi
cmp edi, FieldWidth*FieldHeight
jb .loop
ret
draw_field_item:
; in: eax=field item
; out: nothing
; destroys: eax,ebx,ecx,edx,esi
mov esi, eax
lea edx, [eax+0x80000000+100]
push 8
pop eax
int 0x40 ; delete old button
mov ebx, [xstart+esi*4]
shl ebx, 16
mov bl, ButtonWidth
mov ecx, [ystart+esi*4]
add ecx, [SkinHeight]
shl ecx, 16
mov cl, ButtonHeight
lea edx, [esi+0x40000000+100]
int 0x40 ; define new button
ror ecx, 16
sub ecx, [SkinHeight]
ror ecx, 16
mov al, [field_status+esi]
dec eax
js draw_closed_item
jz draw_current_item
draw_opened_item:
mov edx, 0x94AECE
call draw_frame
mov edx, 0xEFEBEF
add ebx, 0xFFFF
add ecx, 0xFFFF
mov al, 13
int 0x40
jmp draw_item_image
draw_current_item:
push ebx ecx
mov edx, 0x94AECE
call draw_frame
pop ecx ebx
add ebx, 10000h
add ecx, 10000h
push ebx ecx
mov bl, ButtonWidth-2
mov cl, ButtonHeight-2
mov edx, 0x94DB00
call draw_frame
pop ecx ebx
add ebx, 10000h
add ecx, 10000h
mov bl, ButtonWidth-4
mov cl, ButtonHeight-4
mov edx, 0x94DB00
call draw_frame
add ebx, 10000h
add ecx, 10000h
mov bl, ButtonWidth-5
mov cl, ButtonHeight-5
mov edx, 0xEFEBEF
int 0x40
draw_item_image:
; push 7
; pop eax
; movzx ebx, [field_items+esi]
; dec ebx
; imul ebx, ImageWidth*ImageHeight*3
; add ebx, images
; mov ecx, ImageWidth*10000h+ImageHeight
; mov edx, [xstart+esi*4]
; shl edx, 16
; add edx, [ystart+esi*4]
; add edx, 3*10001h
; add edx, [SkinHeight]
; int 0x40
push 65
pop eax
movzx ebx, [field_items+esi]
dec ebx
imul ebx, ImageWidth*ImageHeight
add ebx, images
mov ecx, ImageWidth*10000h+ImageHeight
mov edx, [xstart+esi*4]
shl edx, 16
add edx, [ystart+esi*4]
add edx, 3*10001h
add edx, [SkinHeight]
push 8
pop esi
mov edi, palette
xor ebp, ebp
int 0x40
ret
draw_closed_item:
mov edx, 0x94AECE
call draw_frame
push 38
pop eax
shr ebx, 16
inc ebx
imul ebx, 0x10001
push ebx
add ebx, ButtonWidth-2
shr ecx, 16
inc ecx
imul ecx, 0x10001
mov edx, 0xFFFFFF
int 0x40
pop ebx
push ecx
add ecx, ButtonHeight-3
int 0x40
pop ecx
push ebx ecx
add ebx, ButtonWidth-2
shr ecx, 16
add ecx, ButtonHeight-2
imul ecx, 0x10001
mov edx, 0xDEDEDE
int 0x40
pop ecx
push ecx
movzx ebx, bx
imul ebx, 0x10001
add ecx, 10000h+ButtonHeight-3
int 0x40
pop ecx ebx
add ebx, 10000h
mov bx, ButtonWidth-3
add ecx, 10000h
mov cx, ButtonHeight-3
mov al, 13
mov edx, 0xBDC7D6
int 0x40
ret
draw_field:
xor ebx, ebx
xor ecx, ecx
mov edi, xstart
.loop:
mov eax, ebx
imul eax, SpaceWidth
add eax, 9
stosd
mov eax, ecx
imul eax, SpaceHeight
add eax, 4
mov [edi+ystart-xstart-4], eax
lea eax, [edi-xstart-4]
shr eax, 2
push ebx ecx edi
call draw_field_item
pop edi ecx ebx
inc ecx
cmp ecx, FieldHeight
jb .loop
xor ecx, ecx
inc ebx
cmp ebx, FieldWidth
jb .loop
ret
draw_aux:
push 13
pop eax
mov ebx, 5*65536 + 425
mov ecx, [SkinHeight]
shl ecx, 16
add ecx, 256*65536 + 1
mov edx, 0xFFFFFF
int 0x40
add ecx, 1*65536 + 29
mov edx, [color_table+5*4]
int 0x40
push 8
pop eax
mov ebx, 14*65536 + 107
add ecx, 3*65536 - 7
push 5
pop edx
mov esi, [color_table+6*4]
int 0x40
push 4
pop eax
mov ebx, 27*65536 + 268
add ebx, [SkinHeight]
mov ecx, [color_table+7*4]
or ecx, 0x80000000
mov edx, aNewGame_ru
cmp [CurLanguage], 0
jz @f
mov edx, aNewGame_en
@@:
int 0x40
mov ebx, 155*65536 + 268
add ebx, [SkinHeight]
mov ecx, [color_table+8*4]
or ecx, 0x80000000
mov edx, aCount_ru
cmp [CurLanguage], 0
jz @f
mov edx, aCount_en
@@:
int 0x40
call draw_count
mov al, 13
mov ecx, [SkinHeight]
shl ecx, 16
mov ebx, 405*65536 + 2
add ecx, 265*65536 + 2
mov edx, 0xBDCBDE
int 0x40
mov ebx, 403*65536 + 6
add ecx, (270*65536 + 6) - (265*65536 + 2)
int 0x40
mov ebx, 411*65536 + 6
add ecx, (275*65536 + 6) - (270*65536 + 6)
int 0x40
mov ebx, 412*65536 + 9
add ecx, (262*65536 + 8) - (275*65536 + 6)
mov edx, 0xD6D7CE
int 0x40
ret
draw_count:
mov edi, string_for_number+15
mov eax, [count]
push 10
pop ecx
@@:
xor edx, edx
div ecx
dec edi
add dl, '0'
mov [edi], dl
test eax, eax
jnz @b
mov al, 4
mov ebx, [SkinHeight]
add ebx, 195*65536 + 268
mov ecx, [color_table+8*4]
or ecx, 0xC0000000
mov edx, edi
mov edi, [color_table+5*4]
int 0x40
ret
random:
; in: nothing
; out: edx = random value in [0..FieldWidth*FieldHeight-1]
; destroys: eax,ecx,edx
rdtsc
xor edx, eax
not edx
mov eax, [RandSeed]
ror eax, 3
xor eax, 0DEADBEEFh
add eax, edx
mov [RandSeed], eax
add eax, edx
xor edx, edx
push FieldWidth*FieldHeight
pop ecx
div ecx
ret
i_end:
SkinHeight dd ?
color_table rd 10
RandSeed dd ?
FirstClick dd ?
SecondClick dd ?
string_for_number rb 16
xstart rd 60
ystart rd 60
align 1000h
stk rb 1000h
mem: