Files
kolibrios/programs/games/solitare/solitare.asm

1063 lines
20 KiB
NASM

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: