1069 lines
20 KiB
NASM
1069 lines
20 KiB
NASM
;
|
|
; Solitare
|
|
; Author: Max
|
|
; Compile with FASM
|
|
;
|
|
|
|
Format binary as 'run'
|
|
use32
|
|
org 0x0
|
|
|
|
db 'MENUET01'
|
|
dd 0x01
|
|
dd start
|
|
dd i_end
|
|
dd mem_end
|
|
dd stacktop
|
|
dd 0, 0
|
|
|
|
; --- CONSTANTS ---
|
|
CARD_W equ 50
|
|
CARD_H equ 70
|
|
STACK_OFFSET equ 22
|
|
WIN_W equ 800
|
|
WIN_H equ 600
|
|
BPP equ 3
|
|
STRIDE equ WIN_W * BPP
|
|
|
|
COL_TABLE equ 0x207020
|
|
COL_REVERSE equ 0x0000AA
|
|
COL_WHITE equ 0xFFFFFF
|
|
COL_RED equ 0xCC0000
|
|
COL_BLACK equ 0x000000
|
|
COL_SLOT equ 0x185018
|
|
|
|
STOCK_X equ 20
|
|
WASTE_X equ 80
|
|
FOUNDATION_X equ 400
|
|
FOUND_Y equ 20
|
|
|
|
EXIT_BTN_X equ 760
|
|
EXIT_BTN_Y equ 10
|
|
EXIT_BTN_SIZE equ 20
|
|
|
|
start:
|
|
mov esp, stacktop
|
|
call init_deck
|
|
call shuffle_deck
|
|
call layout_tableau
|
|
mov dword [score], 0
|
|
mov byte [game_won], 0
|
|
|
|
event_loop:
|
|
mov eax, 11
|
|
int 0x40
|
|
cmp eax, 1
|
|
je on_redraw
|
|
cmp eax, 2
|
|
je on_key
|
|
cmp eax, 3
|
|
je on_button
|
|
call handle_mouse
|
|
cmp dword [active_card_count], 0
|
|
ja on_redraw
|
|
mov eax, 5
|
|
mov ebx, 2
|
|
int 0x40
|
|
jmp event_loop
|
|
|
|
on_key:
|
|
mov eax, 2
|
|
int 0x40
|
|
jmp event_loop
|
|
|
|
on_button:
|
|
mov eax, 17
|
|
int 0x40
|
|
shr eax, 8
|
|
cmp eax, 1
|
|
jne event_loop
|
|
mov eax, -1
|
|
int 0x40
|
|
|
|
on_redraw:
|
|
mov eax, 12
|
|
mov ebx, 1
|
|
int 0x40
|
|
xor eax, eax
|
|
mov ebx, 100 shl 16 + WIN_W
|
|
mov ecx, 100 shl 16 + WIN_H
|
|
mov edx, 0x01000000 or COL_TABLE
|
|
mov edi, title
|
|
int 0x40
|
|
mov edi, screen_buffer
|
|
mov ecx, WIN_W * WIN_H
|
|
.clear_loop:
|
|
mov eax, COL_TABLE
|
|
mov [edi], al
|
|
mov [edi+1], ah
|
|
shr eax, 16
|
|
mov [edi+2], al
|
|
add edi, 3
|
|
loop .clear_loop
|
|
|
|
mov ebx, EXIT_BTN_X
|
|
mov ecx, EXIT_BTN_Y
|
|
mov edx, COL_RED
|
|
mov edi, EXIT_BTN_SIZE
|
|
mov ebp, EXIT_BTN_SIZE
|
|
call fill_rect_buf
|
|
|
|
call draw_slots
|
|
xor ecx, ecx
|
|
.draw_loop:
|
|
call is_card_active
|
|
jc .skip
|
|
push ecx
|
|
imul esi, ecx, 12
|
|
add esi, deck_data
|
|
call draw_card_to_buffer
|
|
pop ecx
|
|
.skip:
|
|
inc ecx
|
|
cmp ecx, 52
|
|
jl .draw_loop
|
|
xor ecx, ecx
|
|
.draw_active:
|
|
cmp ecx, [active_card_count]
|
|
jae .draw_score
|
|
push ecx
|
|
mov eax, [active_stack + ecx*4]
|
|
imul esi, eax, 12
|
|
add esi, deck_data
|
|
call draw_card_to_buffer
|
|
pop ecx
|
|
inc ecx
|
|
jmp .draw_active
|
|
|
|
.draw_score:
|
|
mov edx, COL_BLACK
|
|
mov ebx, 620
|
|
mov ecx, 570
|
|
mov esi, 17
|
|
call draw_char_to_buf
|
|
add ebx, 7
|
|
mov esi, 18
|
|
call draw_char_to_buf
|
|
add ebx, 7
|
|
mov esi, 19
|
|
call draw_char_to_buf
|
|
add ebx, 7
|
|
mov esi, 20
|
|
call draw_char_to_buf
|
|
add ebx, 7
|
|
mov esi, 21
|
|
call draw_char_to_buf
|
|
add ebx, 15
|
|
mov eax, [score]
|
|
test eax, eax
|
|
jns .pos
|
|
neg eax
|
|
push eax
|
|
mov ecx, 570
|
|
mov esi, 22
|
|
call draw_char_to_buf
|
|
add ebx, 7
|
|
pop eax
|
|
.pos:
|
|
mov edi, 10
|
|
xor ecx, ecx
|
|
.dec_loop:
|
|
xor edx, edx
|
|
div edi
|
|
push edx
|
|
inc ecx
|
|
test eax, eax
|
|
jnz .dec_loop
|
|
.print_dec:
|
|
pop edx
|
|
add edx, 23
|
|
push ecx
|
|
mov ecx, 570
|
|
mov esi, edx
|
|
mov edx, COL_BLACK
|
|
call draw_char_to_buf
|
|
add ebx, 7
|
|
pop ecx
|
|
loop .print_dec
|
|
|
|
.blit:
|
|
mov eax, 7
|
|
mov ebx, screen_buffer
|
|
mov ecx, WIN_W shl 16 + WIN_H
|
|
xor edx, edx
|
|
int 0x40
|
|
mov eax, 12
|
|
mov ebx, 2
|
|
int 0x40
|
|
jmp event_loop
|
|
|
|
; --- DRAWING PROCEDURES ---
|
|
|
|
draw_char_to_buf:
|
|
pushad
|
|
imul esi, 7
|
|
add esi, font_5x7
|
|
mov ebp, 7
|
|
.y_loop:
|
|
push ebx
|
|
push ecx
|
|
mov al, [esi]
|
|
mov ah, 10000000b
|
|
mov dword [temp_counter], 5
|
|
.x_loop:
|
|
test al, ah
|
|
jz .skip_pixel
|
|
push eax
|
|
imul eax, ecx, STRIDE
|
|
mov edi, ebx
|
|
imul edi, 3
|
|
add eax, edi
|
|
add eax, screen_buffer
|
|
mov [eax], dl
|
|
mov [eax+1], dh
|
|
push edx
|
|
shr edx, 16
|
|
mov [eax+2], dl
|
|
pop edx
|
|
pop eax
|
|
.skip_pixel:
|
|
shr ah, 1
|
|
inc ebx
|
|
dec dword [temp_counter]
|
|
jnz .x_loop
|
|
pop ecx
|
|
pop ebx
|
|
inc esi
|
|
inc ecx
|
|
dec ebp
|
|
jnz .y_loop
|
|
popad
|
|
ret
|
|
|
|
draw_card_to_buffer:
|
|
pushad
|
|
movzx ebx, word [esi+4]
|
|
movzx ecx, word [esi+6]
|
|
mov edx, COL_BLACK
|
|
mov edi, CARD_W
|
|
mov ebp, CARD_H
|
|
call fill_rect_buf
|
|
inc ebx
|
|
inc ecx
|
|
mov edx, COL_WHITE
|
|
mov edi, CARD_W-2
|
|
mov ebp, CARD_H-2
|
|
call fill_rect_buf
|
|
cmp byte [esi+2], 1
|
|
je .face_up
|
|
add ebx, 4
|
|
add ecx, 4
|
|
mov edx, COL_REVERSE
|
|
mov edi, CARD_W-10
|
|
mov ebp, CARD_H-10
|
|
call fill_rect_buf
|
|
popad
|
|
ret
|
|
.face_up:
|
|
mov edx, COL_RED
|
|
cmp byte [esi+1], 2
|
|
jb .is_red
|
|
mov edx, COL_BLACK
|
|
.is_red:
|
|
push edx
|
|
push esi
|
|
; --- TOP-LEFT CORNER (3px margin) ---
|
|
movzx eax, byte [esi]
|
|
dec eax
|
|
mov esi, eax
|
|
add ebx, 3
|
|
add ecx, 3
|
|
call draw_char_to_buf
|
|
pop esi
|
|
push esi
|
|
movzx eax, byte [esi+1]
|
|
add eax, 13
|
|
add ebx, 6 ; Suit icon next to rank
|
|
mov esi, eax
|
|
call draw_char_to_buf
|
|
|
|
; --- BOTTOM-RIGHT CORNER (symmetric 3px margin) ---
|
|
pop esi
|
|
pop edx
|
|
push edx
|
|
push esi
|
|
movzx ebx, word [esi+4]
|
|
add ebx, CARD_W - 8 ; (50 - 3 margin - 5 font width = 42, so add 42)
|
|
movzx ecx, word [esi+6]
|
|
add ecx, CARD_H - 10 ; (70 - 3 margin - 7 font height = 60, so add 60)
|
|
|
|
; Rank at the bottom (furthest to the right)
|
|
movzx eax, byte [esi]
|
|
dec eax
|
|
mov esi, eax
|
|
call draw_char_to_buf
|
|
|
|
; Suit icon next to the bottom rank
|
|
pop esi
|
|
push esi
|
|
movzx eax, byte [esi+1]
|
|
add eax, 13
|
|
sub ebx, 6 ; Icon 6px to the left of rank
|
|
mov esi, eax
|
|
call draw_char_to_buf
|
|
|
|
pop esi
|
|
pop edx
|
|
popad
|
|
ret
|
|
|
|
fill_rect_buf:
|
|
pushad
|
|
imul eax, ecx, STRIDE
|
|
imul ecx, ebx, BPP
|
|
add eax, ecx
|
|
add eax, screen_buffer
|
|
mov ecx, edx
|
|
.yl:
|
|
push eax
|
|
mov edx, edi
|
|
.xl:
|
|
mov [eax], cl
|
|
mov [eax+1], ch
|
|
push ecx
|
|
shr ecx, 16
|
|
mov [eax+2], cl
|
|
pop ecx
|
|
add eax, 3
|
|
dec edx
|
|
jnz .xl
|
|
pop eax
|
|
add eax, STRIDE
|
|
dec ebp
|
|
jnz .yl
|
|
popad
|
|
ret
|
|
|
|
draw_slots:
|
|
pushad
|
|
mov ebx, FOUNDATION_X
|
|
mov ecx, FOUND_Y
|
|
mov dword [temp_counter2], 4
|
|
.f_loop:
|
|
mov edx, COL_SLOT
|
|
mov edi, CARD_W
|
|
mov ebp, CARD_H
|
|
call fill_rect_buf
|
|
add ebx, 60
|
|
dec dword [temp_counter2]
|
|
jnz .f_loop
|
|
mov ebx, 50
|
|
mov ecx, 120
|
|
mov dword [temp_counter2], 7
|
|
.t_loop:
|
|
mov edx, COL_SLOT
|
|
mov edi, CARD_W
|
|
mov ebp, CARD_H
|
|
call fill_rect_buf
|
|
add ebx, 100
|
|
dec dword [temp_counter2]
|
|
jnz .t_loop
|
|
popad
|
|
ret
|
|
|
|
; --- GAME LOGIC ---
|
|
|
|
is_card_active:
|
|
push eax
|
|
push ebx
|
|
xor ebx, ebx
|
|
.l:
|
|
cmp ebx, [active_card_count]
|
|
jae .no
|
|
mov eax, [active_stack + ebx*4]
|
|
cmp eax, ecx
|
|
je .yes
|
|
inc ebx
|
|
jmp .l
|
|
.yes:
|
|
pop ebx
|
|
pop eax
|
|
stc
|
|
ret
|
|
.no:
|
|
pop ebx
|
|
pop eax
|
|
clc
|
|
ret
|
|
|
|
handle_mouse:
|
|
pushad
|
|
mov eax, 37
|
|
mov ebx, 0
|
|
int 0x40
|
|
mov ebp, eax
|
|
shr ebp, 16
|
|
and eax, 0xFFFF
|
|
mov edi, eax
|
|
mov eax, 37
|
|
mov ebx, 2
|
|
int 0x40
|
|
test eax, 1
|
|
jnz .dragging_state
|
|
mov dword [mouse_lock], 0
|
|
cmp dword [active_card_count], 0
|
|
je .exit
|
|
call check_stack_move
|
|
mov dword [active_card_count], 0
|
|
popad
|
|
jmp on_redraw
|
|
.exit:
|
|
popad
|
|
ret
|
|
|
|
.dragging_state:
|
|
cmp dword [mouse_lock], 1
|
|
je .no_deal_click
|
|
cmp ebp, EXIT_BTN_X
|
|
jb .no_exit
|
|
cmp ebp, EXIT_BTN_X + EXIT_BTN_SIZE
|
|
jae .no_exit
|
|
cmp edi, EXIT_BTN_Y
|
|
jb .no_exit
|
|
cmp edi, EXIT_BTN_Y + EXIT_BTN_SIZE
|
|
jae .no_exit
|
|
mov eax, -1
|
|
int 0x40
|
|
.no_exit:
|
|
cmp ebp, STOCK_X
|
|
jb .find_card
|
|
cmp ebp, STOCK_X+CARD_W
|
|
ja .find_card
|
|
cmp edi, FOUND_Y
|
|
jb .find_card
|
|
cmp edi, FOUND_Y+CARD_H
|
|
jae .find_card
|
|
mov dword [mouse_lock], 1
|
|
call deal_from_stock
|
|
popad
|
|
jmp on_redraw
|
|
.find_card:
|
|
mov ebx, 51
|
|
.f_loop:
|
|
imul edx, ebx, 12
|
|
add edx, deck_data
|
|
movzx esi, word [edx+4]
|
|
movzx ecx, word [edx+6]
|
|
cmp ebp, esi
|
|
jb .next_s
|
|
add esi, CARD_W
|
|
cmp ebp, esi
|
|
jae .next_s
|
|
cmp edi, ecx
|
|
jb .next_s
|
|
add ecx, CARD_H
|
|
cmp edi, ecx
|
|
jae .next_s
|
|
cmp byte [edx+2], 1
|
|
jne .next_s
|
|
mov dword [mouse_lock], 1
|
|
mov [active_stack], ebx
|
|
mov dword [active_card_count], 1
|
|
mov ax, [edx+4]
|
|
sub ax, bp
|
|
mov [mouse_off_x], ax
|
|
mov ax, [edx+6]
|
|
sub ax, di
|
|
mov [mouse_off_y], ax
|
|
mov eax, ebx
|
|
call build_active_stack
|
|
popad
|
|
ret
|
|
.next_s:
|
|
dec ebx
|
|
jns .f_loop
|
|
.no_deal_click:
|
|
cmp dword [active_card_count], 0
|
|
je .exit_drag
|
|
.drag_active:
|
|
xor ecx, ecx
|
|
.d_lp:
|
|
cmp ecx, [active_card_count]
|
|
jae .exit_drag
|
|
mov eax, [active_stack + ecx*4]
|
|
imul eax, 12
|
|
add eax, deck_data
|
|
mov dx, [mouse_off_x]
|
|
add dx, bp
|
|
mov [eax+4], dx
|
|
mov dx, [mouse_off_y]
|
|
add dx, di
|
|
push eax
|
|
mov eax, ecx
|
|
imul eax, STACK_OFFSET
|
|
add dx, ax
|
|
pop eax
|
|
mov [eax+6], dx
|
|
inc ecx
|
|
jmp .d_lp
|
|
.exit_drag:
|
|
popad
|
|
ret
|
|
|
|
build_active_stack:
|
|
pushad
|
|
imul esi, eax, 12
|
|
add esi, deck_data
|
|
mov bx, [esi+4]
|
|
mov dx, [esi+6]
|
|
movzx ebp, dx
|
|
add ebp, STACK_OFFSET
|
|
.y_search:
|
|
xor ecx, ecx
|
|
.l:
|
|
imul edi, ecx, 12
|
|
add edi, deck_data
|
|
cmp word [edi+4], bx
|
|
jne .nx
|
|
cmp word [edi+6], bp
|
|
jne .nx
|
|
mov edx, [active_card_count]
|
|
mov [active_stack + edx*4], ecx
|
|
inc dword [active_card_count]
|
|
add ebp, STACK_OFFSET
|
|
jmp .y_search
|
|
.nx:
|
|
inc ecx
|
|
cmp ecx, 52
|
|
jl .l
|
|
.done:
|
|
xor ecx, ecx
|
|
.save:
|
|
cmp ecx, [active_card_count]
|
|
jae .fin
|
|
mov eax, [active_stack + ecx*4]
|
|
imul eax, 12
|
|
add eax, deck_data
|
|
mov dx, [eax+4]
|
|
mov [eax+8], dx
|
|
mov dx, [eax+6]
|
|
mov [eax+10], dx
|
|
inc ecx
|
|
jmp .save
|
|
.fin:
|
|
popad
|
|
ret
|
|
|
|
check_stack_move:
|
|
pushad
|
|
mov esi, [active_stack]
|
|
imul esi, 12
|
|
add esi, deck_data
|
|
cmp dword [active_card_count], 1
|
|
jne .tableau_check
|
|
mov ebx, FOUNDATION_X
|
|
xor ecx, ecx
|
|
.f_lp:
|
|
mov ax, [esi+4]
|
|
sub ax, bx
|
|
add ax, 25
|
|
cmp ax, 50
|
|
ja .next_f
|
|
mov ax, [esi+6]
|
|
sub ax, FOUND_Y
|
|
add ax, 30
|
|
cmp ax, 60
|
|
ja .next_f
|
|
call check_foundation_logic
|
|
jc .found_match
|
|
.next_f:
|
|
add ebx, 60
|
|
inc ecx
|
|
cmp ecx, 4
|
|
jl .f_lp
|
|
.tableau_check:
|
|
mov ebx, 50
|
|
.col_lp:
|
|
xor ecx, ecx
|
|
mov dword [temp_val], -1
|
|
mov dword [temp_counter], 0
|
|
.find_l:
|
|
imul edi, ecx, 12
|
|
add edi, deck_data
|
|
push ecx
|
|
call is_card_active
|
|
pop ecx
|
|
jc .sk_l
|
|
cmp word [edi+4], bx
|
|
jne .sk_l
|
|
movzx eax, word [edi+6]
|
|
cmp eax, [temp_counter]
|
|
jl .sk_l
|
|
mov [temp_counter], eax
|
|
mov [temp_val], ecx
|
|
.sk_l:
|
|
inc ecx
|
|
cmp ecx, 52
|
|
jl .find_l
|
|
cmp dword [temp_val], -1
|
|
je .empty_col
|
|
mov ecx, [temp_val]
|
|
imul edi, ecx, 12
|
|
add edi, deck_data
|
|
mov ax, [esi+4]
|
|
mov dx, [edi+4]
|
|
sub ax, dx
|
|
add ax, 25
|
|
cmp ax, 50
|
|
ja .nx_col
|
|
mov ax, [esi+6]
|
|
mov dx, [edi+6]
|
|
sub ax, dx
|
|
add ax, 30
|
|
cmp ax, 60
|
|
ja .nx_col
|
|
mov al, [esi+1]
|
|
mov dl, [edi+1]
|
|
shr al, 1
|
|
shr dl, 1
|
|
cmp al, dl
|
|
je .nx_col
|
|
mov al, [esi]
|
|
mov dl, [edi]
|
|
inc al
|
|
cmp al, dl
|
|
jne .nx_col
|
|
mov dx, [edi+6]
|
|
add dx, STACK_OFFSET
|
|
jmp .apply_move
|
|
.empty_col:
|
|
mov ax, [esi+4]
|
|
sub ax, bx
|
|
add ax, 25
|
|
cmp ax, 50
|
|
ja .nx_col
|
|
mov ax, [esi+6]
|
|
sub ax, 120
|
|
add ax, 30
|
|
cmp ax, 60
|
|
ja .nx_col
|
|
cmp byte [esi], 13
|
|
jne .nx_col
|
|
mov dx, 120
|
|
jmp .apply_move
|
|
.nx_col:
|
|
add ebx, 100
|
|
cmp ebx, 750
|
|
jl .col_lp
|
|
xor ecx, ecx
|
|
.back:
|
|
cmp ecx, [active_card_count]
|
|
jae .out
|
|
mov eax, [active_stack + ecx*4]
|
|
imul eax, 12
|
|
add eax, deck_data
|
|
mov dx, [eax+8]
|
|
mov [eax+4], dx
|
|
mov dx, [eax+10]
|
|
mov [eax+6], dx
|
|
inc ecx
|
|
jmp .back
|
|
.out:
|
|
popad
|
|
ret
|
|
.found_match:
|
|
add dword [score], 10
|
|
mov [esi+4], bx
|
|
mov word [esi+6], FOUND_Y
|
|
mov byte [esi+3], 8
|
|
pushad
|
|
mov eax, [active_stack]
|
|
mov [temp_active], eax
|
|
call move_single_to_top
|
|
popad
|
|
call auto_reveal_all
|
|
call check_win
|
|
popad
|
|
ret
|
|
.apply_move:
|
|
xor ecx, ecx
|
|
push eax
|
|
push edx
|
|
mov eax, ebx
|
|
sub eax, 50
|
|
xor edx, edx
|
|
mov edi, 100
|
|
div edi
|
|
mov [temp_val], eax
|
|
pop edx
|
|
pop eax
|
|
mov [temp_counter2], edx
|
|
.sticky_loop:
|
|
cmp ecx, [active_card_count]
|
|
jae .sticky_done
|
|
mov eax, [active_stack + ecx*4]
|
|
imul eax, 12
|
|
add eax, deck_data
|
|
mov [eax+4], bx
|
|
mov dx, word [temp_counter2]
|
|
mov [eax+6], dx
|
|
mov dl, byte [temp_val]
|
|
mov [eax+3], dl
|
|
add word [temp_counter2], STACK_OFFSET
|
|
inc ecx
|
|
jmp .sticky_loop
|
|
.sticky_done:
|
|
xor ecx, ecx
|
|
.top_loop:
|
|
cmp ecx, [active_card_count]
|
|
jae .ok
|
|
push ecx
|
|
mov eax, [active_stack + ecx*4]
|
|
mov [temp_active], eax
|
|
call move_single_to_top
|
|
call update_active_stack_after_move
|
|
pop ecx
|
|
inc ecx
|
|
jmp .top_loop
|
|
.ok:
|
|
call auto_reveal_all
|
|
popad
|
|
ret
|
|
|
|
update_active_stack_after_move:
|
|
pushad
|
|
mov edx, [temp_active]
|
|
xor ecx, ecx
|
|
.up_lp:
|
|
cmp ecx, [active_card_count]
|
|
jae .up_dn
|
|
mov eax, [active_stack + ecx*4]
|
|
cmp eax, edx
|
|
jbe .no_chg
|
|
dec eax
|
|
mov [active_stack + ecx*4], eax
|
|
jmp .no_chg
|
|
.no_chg:
|
|
inc ecx
|
|
jmp .up_lp
|
|
.up_dn:
|
|
popad
|
|
ret
|
|
|
|
check_foundation_logic:
|
|
pushad
|
|
xor eax, eax
|
|
mov dword [temp_val], 0
|
|
mov dword [temp_counter], -1
|
|
xor ebp, ebp
|
|
.find_top:
|
|
imul edi, ebp, 12
|
|
add edi, deck_data
|
|
cmp [edi+4], bx
|
|
jne .nx_c
|
|
cmp word [edi+6], FOUND_Y
|
|
jne .nx_c
|
|
movzx edx, byte [edi]
|
|
cmp edx, [temp_val]
|
|
jle .nx_c
|
|
mov [temp_val], edx
|
|
mov [temp_counter], ebp
|
|
.nx_c:
|
|
inc ebp
|
|
cmp ebp, 52
|
|
jl .find_top
|
|
mov al, [esi]
|
|
mov dl, [esi+1]
|
|
cmp dword [temp_counter], -1
|
|
jne .not_empty
|
|
cmp al, 1
|
|
je .valid
|
|
jmp .invalid
|
|
.not_empty:
|
|
mov edi, [temp_counter]
|
|
imul edi, 12
|
|
add edi, deck_data
|
|
cmp dl, [edi+1]
|
|
jne .invalid
|
|
mov dl, [edi]
|
|
inc dl
|
|
cmp al, dl
|
|
je .valid
|
|
.invalid:
|
|
popad
|
|
clc
|
|
ret
|
|
.valid:
|
|
popad
|
|
stc
|
|
ret
|
|
|
|
check_win:
|
|
pushad
|
|
xor ecx, ecx
|
|
xor eax, eax
|
|
.l:
|
|
imul esi, ecx, 12
|
|
add esi, deck_data
|
|
cmp byte [esi+3], 8
|
|
jne .no
|
|
inc eax
|
|
.no:
|
|
inc ecx
|
|
cmp ecx, 52
|
|
jl .l
|
|
cmp eax, 52
|
|
jne .out
|
|
cmp byte [game_won], 0
|
|
jne .out
|
|
add dword [score], 100
|
|
mov byte [game_won], 1
|
|
.out:
|
|
popad
|
|
ret
|
|
|
|
auto_reveal_all:
|
|
pushad
|
|
mov ebx, 50
|
|
.col_loop:
|
|
xor esi, esi
|
|
mov dword [temp_val], -1
|
|
xor ecx, ecx
|
|
.find_lowest:
|
|
imul edi, ecx, 12
|
|
add edi, deck_data
|
|
cmp [edi+4], bx
|
|
jne .next_card
|
|
movzx eax, word [edi+6]
|
|
cmp eax, [temp_val]
|
|
jle .next_card
|
|
mov [temp_val], eax
|
|
mov esi, edi
|
|
.next_card:
|
|
inc ecx
|
|
cmp ecx, 52
|
|
jl .find_lowest
|
|
cmp dword [temp_val], -1
|
|
je .next_col
|
|
mov byte [esi+2], 1
|
|
.next_col:
|
|
add ebx, 100
|
|
cmp ebx, 750
|
|
jl .col_loop
|
|
popad
|
|
ret
|
|
|
|
move_single_to_top:
|
|
mov eax, [temp_active]
|
|
cmp eax, 51
|
|
je .done
|
|
imul esi, eax, 12
|
|
add esi, deck_data
|
|
mov edi, temp_card_buf
|
|
mov ecx, 3
|
|
rep movsd
|
|
mov eax, [temp_active]
|
|
inc eax
|
|
imul esi, eax, 12
|
|
add esi, deck_data
|
|
imul edi, [temp_active], 12
|
|
add edi, deck_data
|
|
mov ecx, 51
|
|
sub ecx, [temp_active]
|
|
imul ecx, 3
|
|
rep movsd
|
|
mov esi, temp_card_buf
|
|
mov edi, deck_data + (51 * 12)
|
|
mov ecx, 3
|
|
rep movsd
|
|
.done: ret
|
|
|
|
deal_from_stock:
|
|
pushad
|
|
mov ecx, 51
|
|
.f:
|
|
imul esi, ecx, 12
|
|
add esi, deck_data
|
|
cmp byte [esi+3], 7
|
|
jne .n
|
|
cmp byte [esi+2], 0
|
|
je .o
|
|
.n: dec ecx
|
|
jns .f
|
|
call reset_stock
|
|
popad
|
|
ret
|
|
.o:
|
|
mov byte [esi+2], 1
|
|
mov byte [esi+3], 9
|
|
mov word [esi+4], WASTE_X
|
|
mov word [esi+6], FOUND_Y
|
|
mov [temp_active], ecx
|
|
call move_single_to_top
|
|
popad
|
|
ret
|
|
|
|
reset_stock:
|
|
sub dword [score], 20
|
|
xor ecx, ecx
|
|
.l:
|
|
imul esi, ecx, 12
|
|
add esi, deck_data
|
|
cmp byte [esi+3], 9
|
|
jne .s
|
|
mov byte [esi+2], 0
|
|
mov byte [esi+3], 7
|
|
mov word [esi+4], STOCK_X
|
|
mov word [esi+6], FOUND_Y
|
|
.s: inc ecx
|
|
cmp ecx, 52
|
|
jl .l
|
|
ret
|
|
|
|
init_deck:
|
|
mov edi, deck_data
|
|
xor eax, eax
|
|
.s: xor ebx, ebx
|
|
.r: inc ebx
|
|
mov [edi], bl
|
|
mov [edi+1], al
|
|
mov byte [edi+2], 0
|
|
mov byte [edi+3], 7
|
|
add edi, 12
|
|
cmp ebx, 13
|
|
jne .r
|
|
inc eax
|
|
cmp eax, 4
|
|
jne .s
|
|
ret
|
|
|
|
shuffle_deck:
|
|
mov dword [temp_counter2], 51
|
|
.sh:
|
|
mov eax, 3
|
|
int 0x40
|
|
and eax, 0xFFFF
|
|
xor edx, edx
|
|
mov ebx, [temp_counter2]
|
|
inc ebx
|
|
div ebx
|
|
imul esi, [temp_counter2], 12
|
|
add esi, deck_data
|
|
imul edi, edx, 12
|
|
add edi, deck_data
|
|
mov ecx, 3
|
|
.sw:
|
|
mov eax, [esi]
|
|
mov edx, [edi]
|
|
mov [esi], edx
|
|
mov [edi], eax
|
|
add esi, 4
|
|
add edi, 4
|
|
loop .sw
|
|
dec dword [temp_counter2]
|
|
jnz .sh
|
|
ret
|
|
|
|
layout_tableau:
|
|
mov edi, deck_data
|
|
mov ebx, 50
|
|
xor edx, edx
|
|
.cols:
|
|
mov ecx, 120
|
|
mov eax, edx
|
|
inc eax
|
|
mov ebp, eax
|
|
.cards:
|
|
mov [edi+4], bx
|
|
mov [edi+6], cx
|
|
mov byte [edi+3], dl
|
|
dec ebp
|
|
jnz .h
|
|
mov byte [edi+2], 1
|
|
jmp .nx
|
|
.h:
|
|
mov byte [edi+2], 0
|
|
.nx:
|
|
add edi, 12
|
|
add ecx, STACK_OFFSET
|
|
cmp edx, 6
|
|
je .cl
|
|
cmp ebp, 0
|
|
jne .cards
|
|
add ebx, 100
|
|
inc edx
|
|
jmp .cols
|
|
.cl:
|
|
cmp ebp, 0
|
|
jne .cards
|
|
.sf:
|
|
cmp edi, deck_data + (52 * 12)
|
|
jae .fin
|
|
mov word [edi+4], STOCK_X
|
|
mov word [edi+6], FOUND_Y
|
|
mov byte [edi+3], 7
|
|
mov byte [edi+2], 0
|
|
add edi, 12
|
|
jmp .sf
|
|
.fin: ret
|
|
|
|
; --- DATA ---
|
|
title db 'Solitaire Symmetric Corner', 0
|
|
score dd 0
|
|
game_won db 0
|
|
mouse_lock dd 0
|
|
temp_counter dd 0
|
|
temp_counter2 dd 0
|
|
temp_val dd 0
|
|
mouse_off_x dw 0
|
|
mouse_off_y dw 0
|
|
temp_active dd 0
|
|
temp_card_buf rd 3
|
|
active_card_count dd 0
|
|
active_stack rd 13
|
|
|
|
font_5x7:
|
|
db 01110000b,10001000b,10001000b,11111000b,10001000b,10001000b,10001000b ; 0:A
|
|
db 11110000b,00001000b,00010000b,00100000b,01000000b,10000000b,11111000b ; 1:2
|
|
db 11110000b,00001000b,00001000b,01110000b,00001000b,00001000b,11110000b ; 2:3
|
|
db 10001000b,10001000b,10001000b,11111000b,00001000b,00001000b,00001000b ; 3:4
|
|
db 11111000b,10000000b,10000000b,11110000b,00001000b,00001000b,11110000b ; 4:5
|
|
db 01110000b,10000000b,10000000b,11110000b,10001000b,10001000b,01110000b ; 5:6
|
|
db 11111000b,00001000b,00010000b,00100000b,01000000b,01000000b,01000000b ; 6:7
|
|
db 01110000b,10001000b,10001000b,01110000b,10001000b,10001000b,01110000b ; 7:8
|
|
db 01110000b,10001000b,10001000b,01111000b,00001000b,00001000b,01110000b ; 8:9
|
|
db 10111000b,10101000b,10101000b,10101000b,10101000b,10101000b,10111000b ; 9:10
|
|
db 00011000b,00001000b,00001000b,00001000b,00001000b,10001000b,01110000b ; 10:J
|
|
db 01110000b,10001000b,10001000b,10001000b,10101000b,10010000b,01101000b ; 11:Q
|
|
db 10001000b,10010000b,10100000b,11000000b,10100000b,10010000b,10001000b ; 12:K
|
|
db 01010000b,11111000b,11111000b,01110000b,00100000b,00000000b,00000000b ; 13:Hearts
|
|
db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,00000000b ; 14:Diamonds
|
|
db 00100000b,00100000b,11111000b,11111000b,00100000b,00100000b,01110000b ; 15:Clubs
|
|
db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,01110000b ; 16:Spades
|
|
db 01111000b,10000000b,01110000b,00001000b,00001000b,11110000b,00000000b ; 17:S
|
|
db 01110000b,10001000b,10000000b,10000000b,10000000b,10001000b,01110000b ; 18:C
|
|
db 01110000b,10001000b,10001000b,10001000b,10001000b,10001000b,01110000b ; 19:O
|
|
db 11110000b,10001000b,10001000b,11110000b,10100000b,10010000b,10001000b ; 20:R
|
|
db 01111000b,10000000b,10000000b,11110000b,10000000b,10000000b,11111000b ; 21:E
|
|
db 00000000b,00000000b,00000000b,11111000b,00000000b,00000000b,00000000b ; 22:-
|
|
db 01110000b,10001000b,10001000b,10001000b,10001000b,10001000b,01110000b ; 23:0
|
|
db 00100000b,01100000b,00100000b,00100000b,00100000b,00100000b,01110000b ; 24:1
|
|
db 01110000b,10001000b,00001000b,01110000b,10000000b,10000000b,11111000b ; 25:2
|
|
db 11111000b,00001000b,00010000b,00110000b,00001000b,10001000b,01110000b ; 26:3
|
|
db 00010000b,00110000b,01010000b,10010000b,11111000b,00010000b,00010000b ; 27:4
|
|
db 11111000b,10000000b,11110000b,00001000b,00001000b,10001000b,01110000b ; 28:5
|
|
db 01110000b,10000000b,11110000b,10001000b,10001000b,10001000b,01110000b ; 29:6
|
|
db 11111000b,00001000b,00010000b,00100000b,01000000b,01000000b,01000000b ; 30:7
|
|
db 01110000b,10001000b,10001000b,01110000b,10001000b,10001000b,01110000b ; 31:8
|
|
db 01110000b,10001000b,10001000b,01111000b,00001000b,00001000b,01110000b ; 32:9
|
|
|
|
align 4
|
|
deck_data: rb 52 * 12
|
|
i_end:
|
|
|
|
align 4096
|
|
screen_buffer: rb WIN_W * WIN_H * 3 + 32768
|
|
stack_bottom: rb 8192
|
|
stacktop:
|
|
mem_end:
|