kolibrios/programs/games/freecell/freecell.asm

2126 lines
48 KiB
NASM
Raw Blame History

; <--- description --->
; compiler: FASM 1.50
; name: FreeCell for MeOS
; version: 1.00
; last update: 21/07/2004
; written by: Alexandr Gorbovets
; e-mail: gorsash@mail.ru
include "../../macros.inc"
include "lang.inc"
meos_app_start
code
call randomize
call draw_window
wait_event:
mov eax, 10
mcall
cmp eax, 1 ; if event == 1
je redraw ; jump to redraw handler
cmp eax, 2 ; else if event == 2
je key ; jump to key handler
cmp eax, 3 ; else if event == 3
je button ; jump to button handler
jmp wait_event ;else return to the start of main cycle
redraw: ; redraw event handler
call draw_window
jmp wait_event
key: ; key event handler
mov eax, 2 ; get key code
mcall
jmp wait_event
button: ; button event handler
mov eax, 17 ; get button identifier
mcall
cmp ah, 1
je exit_app ; return if button id != 1
cmp ah, 1 + 8
jbe common_card ; if 1 < ah <= 9
cmp ah, 1 + 8 + 4 ; if 9 < ah <= 13
jbe temp_cell
cmp ah, 1 + 8 + 8
jbe home_cell
cmp ah, 1 + 8 + 4 + 4 + 1
je new_game_button
cmp ah, 1 + 8 + 4 + 4 + 2
je exit_app
jmp wait_event
exit_app:
mov eax, -1 ; exit application
mcall
common_card:
sub ah, 2 ;going from number of card to number of column
mov [columnclicked], 0
mov byte [columnclicked], ah
call common_card_click
jmp wait_event
temp_cell:
sub ah, 2 + 8
mov [columnclicked], 0
mov byte [columnclicked], ah
call temp_cell_click
jmp wait_event
home_cell:
sub ah, 2 + 8 + 4
mov [columnclicked], 0
mov byte [columnclicked], ah
call home_cell_click
jmp wait_event
new_game_button:
call new_game_click
jmp wait_event
;******************************************************************************
; common_card_click(columnclicked)
common_card_click:
; counting code of card, that has been clicked
mov eax, [columnclicked]
mov [ncolumn], eax
call get_row_of_top_card_in_column
mov eax, [topcardrow] ; eax = topcardrow * 8 + columnofselcard
mov bl, 8
mul bl
add eax, [columnclicked]
add eax, cards
mov ebx, 0
mov bl, byte [eax]
mov [cardclicked], ebx
call get_sel_card_code_and_addr
cmp [selcardcode], 52
jb .something_selected
cmp [cardclicked], 52
je .end
mov [whereisselcard], scCommonCells
mov eax, [columnclicked]
mov [columnofselcard], eax
call draw_window
jmp .end
.something_selected:
; checking if selected and clicked cards are equivalent
mov eax, [selcardcode]
cmp [cardclicked], eax
jne .not_same_card
mov [whereisselcard], scNotSelected
call draw_window
jmp .end
.not_same_card:
cmp [cardclicked], 52
jae .put_in_blank_cell
mov eax, [selcardcode]
mov bl, 4
div bl
mov ebx, 0
mov bl, ah
mov [cardfamily], ebx
mov ecx, 0
mov cl, al
mov [cardrange], ecx
mov eax, [cardclicked]
mov bl, 4
div bl ; reminder in ah, quotient in al
mov ebx, 0
mov bl, ah
mov [clickedcardfamily], ebx
mov ecx, 0
mov cl, al
mov [clickedcardrange], ecx
; clickedcardrange must be = cardrange + 1
mov eax, [cardrange]
inc eax
cmp [clickedcardrange], eax ; eax is such as needed
jne .end
cmp [cardfamily], 1
ja .black_card
; if selected red card
cmp [clickedcardfamily], 1
jbe .end ; if clicked red card (range <= 1) then exit
jmp .valid_cards
.black_card:
; if selected black card
cmp [clickedcardfamily], 1
ja .end ; if clicked black card then exit
jmp .valid_cards
.valid_cards:
; moving card from its place on clicked card
mov eax, [columnclicked]
mov [ncolumn], eax
call get_row_of_top_card_in_column
mov eax, [topcardrow]
inc eax
mov bl, 8
mul bl
and eax, $0000FFFF
add eax, [columnclicked]
add eax, cards
mov bl, byte [selcardcode]
mov byte [eax], bl
mov eax, [selcardaddr]
mov byte [eax], 52
mov [whereisselcard], scNotSelected
call draw_window
jmp .end
.put_in_blank_cell:
mov eax, cards
add eax, [columnclicked]
mov bl, byte [selcardcode]
mov byte [eax], bl
mov eax, [selcardaddr]
mov byte [eax], 52
mov [whereisselcard], scNotSelected
call draw_window
.end:
ret
;******************************************************************************
; temp_cell_click(columnclicked)
temp_cell_click:
call get_sel_card_code_and_addr
cmp [selcardcode], 52
jb .something_selected
mov [whereisselcard], scTempCells
mov eax, [columnclicked]
mov [columnofselcard], eax
call draw_window
jmp .end
.something_selected:
; checking if selected and clicked cards equivalent
mov eax, [columnclicked]
add eax, tempcells
mov ebx, 0
mov bl, byte [eax]
mov [cardclicked], ebx
mov eax, [selcardcode]
cmp [cardclicked], eax
jne .not_same_card
mov [whereisselcard], scNotSelected
call draw_window
.not_same_card:
;putting cards in temp cells
mov eax, [columnclicked]
add eax, tempcells
mov ebx, 0
mov bl, byte [eax]
mov [cardclicked], ebx
cmp [cardclicked], 52
jb .end
; if nothing lay in this cell
; move selected card to temp cell
mov eax, [columnclicked]
add eax, tempcells
mov bl, byte [selcardcode]
mov byte [eax], bl
mov eax, [selcardaddr]
mov byte [eax], 52
mov [whereisselcard], scNotSelected
call draw_window
jmp .end
.end:
ret
;******************************************************************************
; home_cell_click(column_clicked)
home_cell_click:
call get_sel_card_code_and_addr
mov eax, [columnclicked]
add eax, homecells
mov ebx, 0
mov bl, byte [eax]
mov [cardclicked], ebx
mov eax, [selcardcode]
mov bl, 4
div bl ; reminder in ah, quotient in al
mov ebx, 0
mov bl, ah
mov [cardfamily], ebx
mov ecx, 0
mov cl, al
mov [cardrange], ecx
cmp [cardclicked], 52
jb .not_blank
; if nothing lay in this cell
cmp [cardrange], 0
jne .end
; move ace to home
mov eax, [columnclicked]
add eax, homecells
mov bl, byte [selcardcode]
mov byte [eax], bl
mov eax, [selcardaddr]
mov byte [eax], 52
mov [whereisselcard], scNotSelected
call draw_window
jmp .end
.not_blank:
mov eax, [cardclicked]
mov bl, 4
div bl ; reminder in ah, quotient in al
mov ebx, 0
mov bl, ah
mov [clickedcardfamily], ebx
mov ecx, 0
mov cl, al
mov [clickedcardrange], ecx
cmp [cardfamily], ebx
jne .end
inc ecx
cmp [cardrange], ecx
jne .end
; moving card from its place to home with replacing
; of old card in home
mov eax, [columnclicked]
add eax, homecells
mov bl, byte [selcardcode]
mov byte [eax], bl
mov eax, [selcardaddr]
mov byte [eax], 52
mov [whereisselcard], scNotSelected
call draw_window
.end:
ret
;******************************************************************************
new_game_click:
mov [i], 0
.deleting_cards_from_common_cells:
mov eax, cards
add eax, [i]
mov byte [eax], 52
inc [i]
cmp [i], 19*8
jb .deleting_cards_from_common_cells
mov [i], 0
.filling_pack:
mov eax, pack
add eax, [i]
mov bl, byte [i]
mov byte [eax], bl
inc [i]
cmp [i], 52
jb .filling_pack
mov [i], 0
.putting_cards:
mov [range], 52
call random
mov eax, [random_value]
add eax, pack
mov ebx, 0
mov bl, byte [eax]
mov [randomcard], ebx
mov eax, [random_value]
mov [j], eax
cmp [randomcard], 52
jb .found_card
mov [range], 52
call random
cmp [random_value], 26
jae .decreasing_j
.increasing_j:
inc [j]
; j mod 52
mov eax, [j]
mov edx, 0
mov ebx, 52
div ebx
mov [j], edx
mov eax, [j]
add eax, pack
mov ebx, 0
mov bl, byte [eax]
mov [randomcard], ebx
cmp [randomcard], 52
jb .found_card
jmp .increasing_j
.decreasing_j:
dec [j]
; i mod 32
mov eax, [j]
mov edx, 0
mov ebx, 52
div ebx
mov [j], edx
mov eax, [j]
add eax, pack
mov ebx, 0
mov bl, byte [eax]
mov [randomcard], ebx
cmp [randomcard], 52
jb .found_card
jmp .decreasing_j
.found_card:
; putting card from pack
mov eax, cards
add eax, [i]
mov bl, byte [randomcard]
mov byte [eax], bl
; deleting card from pack
mov eax, pack
add eax, [j]
mov byte [eax], 52
inc [i]
cmp [i], 52
jb .putting_cards
mov [i], 0
.deleting_cards_from_temp_cells:
mov eax, tempcells
add eax, [i]
mov byte [eax], 52
inc [i]
cmp [i], 4
jb .deleting_cards_from_temp_cells
mov [i], 0
.deleting_cards_from_home_cells:
mov eax, homecells
add eax, [i]
mov byte [eax], 52
inc [i]
cmp [i], 4
jb .deleting_cards_from_home_cells
mov [whereisselcard], scNotSelected
call draw_window
ret
;******************************************************************************
; get_sel_card_code_and_addr(): selcardcode, selcardaddr
; if nothing selected, then selcardcode is 52
get_sel_card_code_and_addr:
cmp [whereisselcard], scNotSelected
jne .something_selected
mov [selcardcode], 52
jmp .end
.something_selected:
cmp [whereisselcard], scTempCells
je .temp_cells_selected
; common cells selected
mov eax, [columnofselcard]
mov [ncolumn], eax
call get_row_of_top_card_in_column
mov eax, [topcardrow]; eax = topcardrow * 8 + columnofselcard
mov bl, 8
mul bl ; result of multiplication in ax
add eax, [columnofselcard]
add eax, cards
mov [selcardaddr], eax
xor ebx, ebx
mov bl, byte [eax]
mov [selcardcode], ebx
jmp .end
.temp_cells_selected:
mov eax, tempcells
add eax, [columnofselcard]
mov [selcardaddr], eax
mov ebx, 0
mov bl, byte [eax]
mov [selcardcode], ebx
.end:
ret
;******************************************************************************
; draw_window()
draw_window:
mov eax,48 ; get system colors
mov ebx,3
mov ecx,syscolors
mov edx,sizeof.system_colors
mcall
mov eax, 12 ; start drawing
mov ebx, 1
mcall
mov eax, 0 ; create and draw the window
mov ebx, 100 * 65536 + 8 * cardwidth + 10 + 7 * columnspace
mov ecx, 100 * 65536 + 500
mov edx, 0x13008000
mov edi, title
mcall
mov eax, 9 ; getting window info
mov ebx, process_info
mov ecx, -1 ; we want to know info of our window
mcall
test [process_info.wnd_state], 0x04
jnz draw_window.end_draw
mov eax, [process_info.box.height]
mov [WindowHeight], ax
mov eax, [process_info.box.width]
mov [WindowWidth], ax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; draw top panel
mov eax, 13
mov ebx, 5
shl ebx, 16
add bx, word [process_info.box.width]
sub bx, 9
mov ecx, 22 shl 16 + topbuttonsbarheight - 1
mov edx, [syscolors.work_graph]
mcall
; draw button "new game"
mov eax, 8
mov ebx, 5 shl 16 + 80
mov ecx, 22 shl 16 + topbuttonsbarheight - 2
mov edx, 1 + 8 + 4 + 4 + 1 ;button id
mov esi, [syscolors.work_button]
mcall
mov eax, 4
if lang eq it_IT
mov ebx, 7 shl 16 + 22 + topbuttonsbarheight/2 - 4
else
mov ebx, 20 shl 16 + 22 + topbuttonsbarheight/2 - 4
end if
mov ecx, [syscolors.work_button_text]
mov edx, new_game
mov esi, new_game_len
mcall
; draw button "exit"
mov eax, 8
mov ebx, (5 + 85) shl 16 + 80 + 5
mov ecx, 22 shl 16 + topbuttonsbarheight - 2
mov edx, 1 + 8 + 4 + 4 + 2 ;button id
mov esi, [syscolors.work_button]
mcall
mov eax, 4
mov ebx, (40 + 80) shl 16 + 22 + topbuttonsbarheight/2 - 4
mov ecx, [syscolors.work_button_text]
mov edx, exit
mov esi, exit_len
mcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; draw separators between home, temp and common cells
mov eax, 13
; horizontal line
mov ebx, 5
shl ebx, 16
add bx, word [process_info.box.width]
sub bx, 9
mov ecx, (21 + topbuttonsbarheight + cardheight + columnspace) shl 16+1
mov edx, [syscolors.work_graph]
mcall
; verical line
mov eax, [process_info.box.width]
mov edx, 0
mov ecx, 2
div ecx
mov ebx, eax
;
shl ebx, 16
add bx, 1
mov ecx, (21 + topbuttonsbarheight) shl 16 + cardheight + columnspace
mov edx, [syscolors.work_graph]
mov eax, 13
mcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; draw temp buttons
mov [j], 0 ;counter that loops from 0 to 51
draw_a_temp_card:
; code of card must be in ecx
mov eax, tempcells
add eax, [j]
xor ecx, ecx
mov cl, byte [eax] ; placing in cl value from memory
; with address [tempcells + j] or
; j-th element of array "tempcells"
mov [cardcode], ecx
mov eax, [j]
xor edx, edx
mov ebx, 8
div ebx ; divsion by 8 (8 columns),
; so in eax quotient - number of row
; and in edx remainder -
; number of column where lay card
mov [row], eax
mov [column], edx
mov eax, [process_info.box.width] ; width of window
sub eax, 10
sub eax, cardwidth
mov ebx, 7
mov edx, 0
div ebx
mov ebx, [column]
mul ebx
add eax, 5
mov [xpos], eax
mov eax, [row]
mov bl, rowsize
mul bl
add eax, 24 + topbuttonsbarheight
mov [ypos], eax
; checking, if this card selected
mov [negativedraw], 0
cmp [whereisselcard], scTempCells
jne .this_temp_cell_isnt_selected
mov eax, [column]
cmp [columnofselcard], eax
jne .this_temp_cell_isnt_selected
mov [negativedraw], 1
.this_temp_cell_isnt_selected:
call draw_card
; define button on place of card
mov eax, 8
mov ebx, [xpos]
shl ebx, 16
add bx, cardwidth - 1
mov ecx, [ypos]
shl ecx, 16
add cx, cardheight - 1
mov edx, [column]
add edx, 01000000000000000000000000000000b + 2 + 8; button id = column
; id = 1 reserved as close button
mcall
inc [j]
cmp [j], 4
jb draw_a_temp_card
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; draw home buttons
mov [j], 0 ;counter that loops from 0 to 51
draw_a_home_card:
; code of card must be in ecx
mov eax, homecells
add eax, [j]
xor ecx, ecx
mov cl, byte [eax] ; placing in cl value from memory
; with address [tempcells + j] or
; j-th element of array "tempcells"
mov [cardcode], ecx
mov eax, [j]
xor edx, edx
mov ebx, 8
div ebx ; divsion by 8 (8 columns),
; so in eax quotient - number of row
; and in edx remainder -
; number of column where lay card
mov [row], eax
mov [column], edx
mov eax, [process_info.box.width] ; width of window
sub eax, 10
sub eax, cardwidth
mov ebx, 7
mov edx, 0
div ebx
mov ebx, [column]
add ebx, 4
mul ebx
add eax, 5
mov [xpos], eax
mov eax, [row]
mov bl, rowsize
mul bl
add eax, 24 + topbuttonsbarheight
mov [ypos], eax
mov [negativedraw], 0
call draw_card
; define button on place of card
mov eax, 8
mov ebx, [xpos]
shl ebx, 16
add bx, cardwidth - 1
mov ecx, [ypos]
shl ecx, 16
add cx, cardheight - 1
mov edx, [column]
add edx, 01000000000000000000000000000000b + 2 + 8 + 4 ; button id
; id = 1 reserved as close button
mcall
inc [j]
cmp [j], 4
jb draw_a_home_card
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; draw common cards
mov [j], 0 ;counter that loops from 0 to 8 * 19
draw_a_card:
; code of card must be in ecx
mov eax, cards
add eax, [j]
xor ecx, ecx
mov cl, byte [eax] ; placing in cl value from memory
; with address [cards + j] or
; j-th element of array "cards"
; cmp ecx, 52 ; if code of card >= 52 then there is no card
; jae no_draw
;
; cmp ecx, 0 ; if code of card < 0 then there is no card
; jb no_draw
mov [cardcode], ecx
mov eax, [j]
xor edx, edx
mov ebx, 8
div ebx ; divsion by 8 (8 columns),
; so in eax quotient - number of row
; and in edx remainder -
; number of column where lay card
mov [row], eax
mov [column], edx
mov eax, [process_info.box.width] ; width of window
sub eax, 10
sub eax, cardwidth
mov ebx, 7
mov edx, 0
div ebx
mov ebx, [column]
mul ebx
add eax, 5
mov [xpos], eax
mov eax, [row]
mov bl, rowsize
mul bl
add eax, cardheight + 24 + topbuttonsbarheight + columnspace
mov [ypos], eax
mov [negativedraw], 0 ;checking, if this is selected card
cmp [whereisselcard], scCommonCells
jne .this_card_isnt_selected
mov eax, [column]
cmp [columnofselcard], eax
jne .this_card_isnt_selected
mov eax, [column]
mov [ncolumn], eax
call get_row_of_top_card_in_column
mov eax, [row]
cmp [topcardrow], eax
jne .this_card_isnt_selected
mov [negativedraw], 1
.this_card_isnt_selected:
call draw_card
; now checking if it is top card in its column
; if it does, we'll define button on its place
mov eax, [column]
mov [ncolumn], eax
call get_row_of_top_card_in_column
mov eax, [row]
cmp [topcardrow], eax
je .define_button
cmp [topcardrow], 0
jne .no_define_button
cmp [row], 0
jne .no_define_button
.define_button:
mov eax, 8
mov ebx, [xpos]
shl ebx, 16
add bx, cardwidth - 1
mov ecx, [ypos]
shl ecx, 16
add cx, cardheight - 1
mov edx, [column]
add edx, 01000000000000000000000000000000b + 2; button id = column + 2,
; id = 1 reserved as close button
mcall
.no_define_button:
inc [j]
cmp [j], 8 * 19
jb draw_a_card
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
draw_window.end_draw:
mov eax, 12 ; finish drawing
mov ebx, 2
mcall
ret
;******************************************************************************
; get_row_of_top_card_in_column(ncolumn): topcardrow
get_row_of_top_card_in_column:
; number of column in ncolumn
; returns in topcardrow
mov [i], 0 ; i loops from 0 to 1, ... while card i * 8 + ncolumn
; is valid card (0 <= its code < 52)
.cycle:
xor eax, eax
mov al, 8
mov ebx, [i]
mul bl
add eax, [ncolumn]
add eax, cards
xor ecx, ecx
mov cl, byte [eax]
cmp ecx, 52
jae .endcycle
cmp [i], 18
ja .endcycle
inc [i]
jmp .cycle
.endcycle:
cmp [i], 0
je .dont_dec
dec [i]
.dont_dec:
mov eax, [i]
mov [topcardrow], eax
ret
;******************************************************************************
; invert_image_colors(imagetoinvert, sizeofimagetoinvert)
invert_image_colors:
mov [i], 0
.inverting:
mov eax, [imagetoinvert]
add eax, [i]
mov bl, byte [eax]
;xor ebx, ebx
;add ebx, 10
not ebx
mov byte [eax], bl
inc [i]
mov ecx, [sizeofimagetoinvert]
cmp [i], ecx
jb .inverting
jmp .later
.exit:
mov eax, -1
mcall
.later:
ret
;******************************************************************************
; draw_card(xpos, ypos, cardcode, negativedraw)
; if negativedraw = 1 then card drawn in inverted colors
draw_card: ; draws card with left top corner
; in point ([xpos],[ypos]),
; type of card in [cardcode]
cmp [cardcode], 52 ; if code of card >= 52 then there is no card
jae .no_draw_card
cmp [negativedraw], 1
jne .no_invert1
;doing if negativedraw
mov [bgcolor], $00000000
mov [blackcolor], $00FFFFFF
mov [redcolor], $0000FFFF
;inverting all images
call invert_all_images
jmp .colors_selection_done
.no_invert1:
;doing if not negativedraw
mov [bgcolor], $00FFFFFF
mov [blackcolor], $00000000
mov [redcolor], $00FF0000
.colors_selection_done:
mov eax, 13
mov ebx, [xpos] ; filling card with bgcolor
; (big background rectangle)
mov edx, [bgcolor]
add ebx, 2
shl ebx, 16
mov bx, cardwidth - 4
mov ecx, [ypos]
add ecx, 2
shl ecx, 16
mov cx, cardheight - 4
mcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ebx, [xpos] ; left black line
shl ebx, 16
mov bx, 1
mov ecx, [ypos]
add ecx, 5
shl ecx, 16
xor cx, cx
mov cx, cardheight - 2 * radius - 2
mov edx, [blackcolor]
mcall
mov ebx, [xpos] ; left white line
inc ebx
shl ebx, 16
mov bx, 1
mov edx, [bgcolor]
mcall
mov ebx, [xpos] ; right black line
add ebx, cardwidth - 1
shl ebx, 16
mov bx, 1
mov edx, [blackcolor]
mcall
mov ebx, [xpos] ; right white line
add ebx, cardwidth - 2
shl ebx, 16
mov bx, 1
mov edx, [bgcolor]
mcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ecx, [ypos] ; top black line
shl ecx, 16
mov cx, 1
mov ebx, [xpos]
add ebx, 5
shl ebx, 16
mov bx, cardwidth - 2 * radius - 2
mov edx, [blackcolor]
mcall
mov ecx, [ypos] ; top white line
inc ecx
shl ecx, 16
mov cx, 1
mov edx, [bgcolor]
mcall
mov ecx, [ypos] ; bottom black line
add ecx, cardheight - 1
shl ecx, 16
mov cx, 1
mov edx, [blackcolor]
mcall
mov ecx, [ypos] ; bottom white line
add ecx, cardheight - 2
shl ecx, 16
mov cx, 1
mov edx, [bgcolor]
mcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov eax, 1 ; drawing points
mov edx, [blackcolor] ; black color for all pixels
mov ebx, [xpos] ; draw top left corner
mov ecx, [ypos]
inc ebx
add ecx, 4
mcall
dec ecx
mcall
dec ecx
inc ebx
mcall
dec ecx
inc ebx
mcall
inc ebx
mcall
mov ebx, [xpos] ;drawing top right corner
mov ecx, [ypos]
add ebx, cardwidth - 2
add ecx, 4
mcall
dec ecx
mcall
dec ebx
dec ecx
mcall
dec ebx
dec ecx
mcall
dec ebx
mcall
;drawing bottom left corner
mov ebx, [xpos]
mov ecx, [ypos]
inc ebx
add ecx, cardheight - 5
mcall
inc ecx
mcall
inc ebx
inc ecx
mcall
inc ebx
inc ecx
mcall
inc ebx
mcall
;drawing bottom right corner
mov ebx, [xpos]
mov ecx, [ypos]
add ebx, cardwidth - 2
add ecx, cardheight - 5
mcall
inc ecx
mcall
dec ebx
inc ecx
mcall
dec ebx
inc ecx
mcall
dec ebx
mcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; drawing text and images
mov eax, [cardcode]
mov edx, 0
mov ebx, 4
div ebx
mov [cardfamily], edx
mov [cardrange], eax
; counting position of small card image
mov eax, 7
mov ecx, 8*65536+8
mov edx, [xpos]
add edx, radius
shl edx, 16
mov dx, word [ypos]
add dx, radius + 8
cmp [cardfamily], 0
je .heart
cmp [cardfamily], 1
je .diamond
cmp [cardfamily], 2
je .club
cmp [cardfamily], 3
je .spade
.heart:
mov esi, [redcolor]
mov [color], esi
mov [imageaddr], heart
mov [imageflipaddr], heart_updown
mov ebx, heart_small
mcall
jmp .selnumber
.diamond:
mov esi, [redcolor]
mov [color], esi
mov [imageaddr], diamond
mov [imageflipaddr], diamond_updown
mov ebx, diamond_small
mcall
jmp .selnumber
.club:
mov esi, [blackcolor]
mov [color], esi
mov [imageaddr], club
mov [imageflipaddr], club_updown
mov ebx, club_small
mcall
jmp .selnumber
.spade:
mov esi, [blackcolor]
mov [color], esi
mov [imageaddr], spade
mov [imageflipaddr], spade_updown
mov ebx, spade_small
mcall
.selnumber:
mov ebx, [xpos] ; counting position of text
; in ebx, same for all cards
add ebx, radius
shl ebx, 16
mov bx, word [ypos]
add bx, radius
mov ecx, [color]
cmp [cardrange], 0
je .ace
cmp [cardrange], 1
je .two
cmp [cardrange], 2
je .three
cmp [cardrange], 3
je .four
cmp [cardrange], 4
je .five
cmp [cardrange], 5
je .six
cmp [cardrange], 6
je .seven
cmp [cardrange], 7
je .eight
cmp [cardrange], 8
je .nine
cmp [cardrange], 9
je .ten
cmp [cardrange], 10
je .jack
cmp [cardrange], 11
je .queen
cmp [cardrange], 12
je .king
; +-------+-------+-------+
; | 3 | 2 | 3 | ace = 1
; +-------+-------+-------+ two = 2
; | | | | three = 2 + 1
; +-------+-------+-------+ four = 3
; | | 6 | | five = 3 + 1
; +-------+-------+-------+ six = 3 + 4
; | 5 | | 5 | seven = 3 + 4 + 6
; +-------+-------+-------+ eight = 3 + 5
; | 4 | 1 | 4 | nine = 3 + 5
; +-------+-------+-------+ ten = 3 + 5 + 6 + 7
; | 5 | | 5 |
; +-------+-------+-------+
; | | 7 | | 1 means draw_1
; +-------+-------+-------+
; | | | |
; +-------+-------+-------+
; | 3 | 2 | 3 |
; +-------+-------+-------+
.ace:
mov eax, 4
mov [s], byte 'A'
mov edx, s
mov esi, 1
mcall
call draw_1
jmp .end
.two:
mov eax, 4
mov [s], byte '2'
mov edx, s
mov esi, 1
mcall
call draw_2
jmp .end
.three:
mov eax, 4
mov [s], byte '3'
mov edx, s
mov esi, 1
mcall
call draw_1
call draw_2
jmp .end
.four:
mov eax, 4
mov [s], byte '4'
mov edx, s
mov esi, 1
mcall
call draw_3
jmp .end
.five:
mov eax, 4
mov [s], byte '5'
mov edx, s
mov esi, 1
mcall
call draw_1
call draw_3
jmp .end
.six:
mov eax, 4
mov [s], byte '6'
mov edx, s
mov esi, 1
mcall
call draw_3
call draw_4
jmp .end
.seven:
mov eax, 4
mov [s], byte '7'
mov edx, s
mov esi, 1
mcall
call draw_3
call draw_4
call draw_6
jmp .end
.eight:
mov eax, 4
mov [s], byte '8'
mov edx, s
mov esi, 1
mcall
call draw_3
call draw_5
jmp .end
.nine:
mov eax, 4
mov [s], byte '9'
mov edx, s
mov esi, 1
mcall
call draw_3
call draw_5
call draw_1
jmp .end
.ten:
mov eax, 4
mov [s], word '10'
mov edx, s
mov esi, 2
mcall
call draw_3
call draw_5
call draw_6
call draw_7
jmp .end
.jack:
mov eax, 4
mov [s], byte 'J'
mov edx, s
mov esi, 1
mcall
jmp .end
.queen:
mov eax, 4
mov [s], byte 'Q'
mov edx, s
mov esi, 1
mcall
jmp .end
.king:
mov eax, 4
mov [s], byte 'K'
mov edx,s
mov esi, 1
mcall
.end:
cmp [negativedraw], 1
jne .no_invert2
call invert_all_images
.no_invert2:
.no_draw_card:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; invert_all_images()
invert_all_images:
mov [sizeofimagetoinvert], 16 * 16 * 3
mov [imagetoinvert], heart
call invert_image_colors
mov [sizeofimagetoinvert], 16 * 16 * 3
mov [imagetoinvert], diamond
call invert_image_colors
mov [sizeofimagetoinvert], 16 * 16 * 3
mov [imagetoinvert], spade
call invert_image_colors
mov [sizeofimagetoinvert], 16 * 16 * 3
mov [imagetoinvert], club
call invert_image_colors
mov [sizeofimagetoinvert], 16 * 16 * 3
mov [imagetoinvert], heart_updown
call invert_image_colors
mov [sizeofimagetoinvert], 16 * 16 * 3
mov [imagetoinvert], diamond_updown
call invert_image_colors
mov [sizeofimagetoinvert], 16 * 16 * 3
mov [imagetoinvert], spade_updown
call invert_image_colors
mov [sizeofimagetoinvert], 16 * 16 * 3
mov [imagetoinvert], club_updown
call invert_image_colors
mov [sizeofimagetoinvert], 8 * 8 * 3
mov [imagetoinvert], heart_small
call invert_image_colors
mov [sizeofimagetoinvert], 8 * 8 * 3
mov [imagetoinvert], diamond_small
call invert_image_colors
mov [sizeofimagetoinvert], 8 * 8 * 3
mov [imagetoinvert], spade_small
call invert_image_colors
mov [sizeofimagetoinvert], 8 * 8 * 3
mov [imagetoinvert], club_small
call invert_image_colors
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
draw_1:
;draw center image
mov ebx, [imageaddr]
mov ecx, 16 * 65536 + 16
mov edx, [xpos]
add edx, cardwidth/2 - 8
shl edx, 16
mov dx, word [ypos]
add dx, cardheight/2 - 8
mov eax, 7
mcall
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
draw_2:
;draw top image
mov ebx, [imageaddr]
mov ecx, 16 * 65536 + 16
mov edx, [xpos]
add edx, 40 - 8
shl edx, 16
mov dx, word [ypos]
add dx, margin
mov eax, 7
mcall
;draw bottom image
mov ebx, [imageflipaddr]
mov edx, [xpos]
add edx, cardwidth/2 - 8
shl edx, 16
mov dx, word [ypos]
add dx, cardheight - 16 - margin
mov eax, 7
mcall
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
draw_3:
;draw top left image
mov ebx, [imageaddr]
mov ecx, 16 * 65536 + 16
mov edx, [xpos]
add edx, margin
shl edx, 16
mov dx, word [ypos]
add dx, margin
mov eax, 7
mcall
;draw bottom left image
mov ebx, [imageflipaddr]
mov edx, [xpos]
add edx, margin
shl edx, 16
mov dx, word [ypos]
add dx, cardheight - margin - 16
mov eax, 7
mcall
;draw top right image
mov ebx, [imageaddr]
mov edx, [xpos]
add edx, cardwidth - margin - 16
shl edx, 16
mov dx, word [ypos]
add dx, margin
mov eax, 7
mcall
;draw bottom right image
mov ebx, [imageflipaddr]
mov edx, [xpos]
add edx, cardwidth - margin - 16
shl edx, 16
mov dx, word [ypos]
add dx, cardheight - margin - 16
mov eax, 7
mcall
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
draw_4:
;draw center left image
mov ebx, [imageaddr]
mov ecx, 16 * 65536 + 16
mov edx, [xpos]
add edx, margin
shl edx, 16
mov dx, word [ypos]
add dx, cardheight/2 - 8
mov eax, 7
mcall
;draw center right image
mov edx, [xpos]
add edx, cardwidth - margin - 16
shl edx, 16
mov dx, word [ypos]
add dx, cardheight/2 - 8
mov eax, 7
mcall
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
draw_5:
;draw top left image
mov ebx, [imageaddr]
mov ecx, 16 * 65536 + 16
mov edx, [xpos]
add edx, margin
shl edx, 16
mov dx, word [ypos]
add dx, cardheight * 3 / 9
mov eax, 7
mcall
;draw bottom left image
mov ebx, [imageflipaddr]
mov edx, [xpos]
add edx, 16
shl edx, 16
mov dx, word [ypos]
add dx, cardheight * 5 / 9
mov eax, 7
mcall
;draw top right image
mov ebx, [imageaddr]
mov edx, [xpos]
add edx, cardwidth - margin - 16
shl edx, 16
mov dx, word [ypos]
add dx, cardheight * 3 / 9
mov eax, 7
mcall
;draw bottom right image
mov ebx, [imageflipaddr]
mov edx, [xpos]
add edx, cardwidth - margin - 16
shl edx, 16
mov dx, word [ypos]
add dx, cardheight * 5 / 9
mov eax, 7
mcall
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
draw_6:
mov ebx, [imageaddr]
mov ecx, 16 * 65536 + 16
mov edx, [xpos]
add edx, cardwidth/2 - 8
shl edx, 16
mov dx, word [ypos]
add dx, cardheight * 2 / 9
mov eax, 7
mcall
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
draw_7:
mov ebx, [imageflipaddr]
mov ecx, 16 * 65536 + 16
mov edx, [xpos]
add edx, cardwidth/2 - 8
shl edx, 16
mov dx, word [ypos]
add dx, cardheight * 6 / 9
mov eax, 7
mcall
ret
;******************************************************************************
randomize:
push eax
mov eax, 3
mcall
mov ebx, $A59E3F1C
mul ebx
mov dword [randseed], eax
pop eax
ret
;******************************************************************************
; function Random(Range): RandomValue
random:
push ebx
mov eax, [randseed]
mov edx, 0
mov ebx, 7
div ebx
cmp edx, 0
je _0
cmp edx, 1
je _1
cmp edx, 2
je _2
cmp edx, 3
je _3
cmp edx, 4
je _4
cmp edx, 5
je _5
cmp edx, 6
je _6
jmp _end
_0:
;base := base + 58 + a[8];
mov eax, [randseed]
add eax, 58
add eax, dword [a + 8 * 4]
mov [randseed], eax
jmp _end;
_1:
;base := base + 1 + a[9];
mov eax, [randseed]
add eax, 1
add eax, dword [a + 9 * 4]
mov [randseed], eax
jmp _end;
_2:
;base := base + 4 + a[88];
mov eax, [randseed]
add eax, 4
add eax, dword [a + 88 * 4]
mov [randseed], eax
jmp _end;
_3:
;randseed := randseed + 79 + a[43];
mov eax, [randseed]
add eax, 79
add eax, dword [a + 43 * 4]
mov [randseed], eax
jmp _end;
_4:
;randseed := randseed + 3 + a[12];
mov eax, [randseed]
add eax, 3
add eax, dword [a + 12 * 4]
mov [randseed], eax
jmp _end;
_5:
;randseed := randseed + 2 + a[63];
mov eax, [randseed]
add eax, 2
add eax, dword [a + 63 * 4]
mov [randseed], eax
jmp _end;
_6:
;randseed := randseed + 151 + a[24];
mov eax, [randseed]
add eax, 151
add eax, dword [a + 24 * 4]
mov [randseed], eax
_end:
mov eax, [randseed]
mov edx, eax
shl edx, 16
mov bx, 100
div bx ; dx = randseed mod 100
mov ax, dx ; ax = randseed mod 100
mov bx, 4
mul bx ; dx:ax = (randseed mod 100) * 4
and eax, $0000FFFF
shr edx, 16
and edx, $FFFF0000
or eax, edx
mov eax, dword [a + eax] ; eax = dword[a + (randseed mod 100) * 4]
; ~ a[randseed mod 100]
mov ebx, dword [a + 47 * 4]
mul ebx ; eax = low(a[randseed mod 100] * a[47])
add eax, [randseed]
add eax, $4AE783A
mov [randseed], eax
mov eax, dword [a + 6 * 4]
mov edx, 0
mov ebx, 100
div ebx
mov eax, edx
mov ebx, 4
mul ebx ; eax = (dword [a + 6 * 4] mod 100) * 4 ~ a[6] mod 100
mov eax, dword [a + eax] ; eax = dword [a + (dword [a + 6 * 4] mod 100) * 4
; ~ a[a[6] mod 100]
add eax, [randseed]
mov [random_value], eax
mov edx, 0
mov ebx, [range]
div ebx
mov [random_value], edx
mov al, [TimesCalled]
xor ah, ah
inc al
mov bl, 100
div bl
mov [TimesCalled], ah ; TimesCalled = (TimesCalled + 1 ) mod 100
mov al, ah
mov bl, 4
mul bl
and eax, $0000FFFF
mov ebx, [randseed]
mov dword [a + eax], ebx ; a[TimesCalled] = randseed
pop ebx
ret
;******************************************************************************
; <--- initialised data --->
if lang eq ru_RU
title db '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>',0
new_game: db "<22><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>"
new_game_len = $ - new_game
exit: db "<22><>室"
exit_len = $ - exit
s: db "10"
else if lang eq it_IT
title db 'Freecell',0
new_game: db "Nuova partita"
new_game_len = $ - new_game
exit: db "Esci"
exit_len = $ - exit
s: db "10"
else
title db 'Freecell',0
new_game: db "New game"
new_game_len = $ - new_game
exit: db "Exit"
exit_len = $ - exit
s: db "10"
end if
negativedraw db 0 ; for procedure draw_card
spade file 'Spade.bmp': 54
spade_updown file 'SpadeUD.bmp': 54
spade_small file 'SpadeSml.bmp': 54
club file 'Club.bmp': 54
club_updown file 'ClubUD.bmp': 54
club_small file 'ClubSml.bmp': 54
diamond file 'Diam.bmp': 54
diamond_updown file 'DiamUD.bmp': 54
diamond_small file 'DiamSml.bmp': 54
heart file 'Heart.bmp': 54
heart_updown file 'HeartUD.bmp': 54
heart_small file 'HeartSml.bmp': 54
scNotSelected = 0
scCommonCells = 1
scTempCells = 2
whereisselcard dd scNotSelected
columnofselcard dd 0 ; if WhereIsSelCard = scGeneralCells
; then this can be 0 .. 7,
; if scTempCells then - 0 .. 3
; if scNotSelected - no matter
tempcells: times 4 db 52;
homecells: times 4 db 52 ; maximal card code is 51
cards: times 8 * 19 db 52; - %
pack: times 52 db ?
udata
process_info process_information
syscolors system_colors
WindowHeight rw 1
WindowWidth rw 1
xpos rd 1
ypos rd 1
bgcolor rd 1
blackcolor rd 1
redcolor rd 1
lastparam rd 1 ;
randomcard rd 1 ; for new_game_click
columnclicked rd 1 ; used in common_card_click, temp_cell_click,
cardclicked rd 1 ; home_cell_click
clickedcardrange rd 1 ;
clickedcardfamily rd 1 ;
selcardcode rd 1 ; for procedure get_sel_card_code_and_addr
selcardaddr rd 1 ;
column rd 1 ; for procedure draw_window
row rd 1 ;
imagetoinvert rd 1 ; for procedure invert_image_colors
sizeofimagetoinvert rd 1 ;
ncolumn rd 1 ; for procedure get_row_of_top_card_in_column
topcardrow rd 1 ;
color rd 1 ; for procedue draw_card
imageaddr rd 1 ;
imageflipaddr rd 1 ;
cardcode rd 1 ; used in differrent procedures
cardrange rd 1 ; cardcode = cardrange * 4 + cardfamily
cardfamily rd 1 ;
a: times 100 rd 1 ; for function Random
range rd 1 ;
random_value rd 1 ;
randseed rd 1 ;
TimesCalled rb 1 ;
j rd 1 ; number of card (in array cards) drawn now
i rd 1 ; used in many procedures of 1-st level
k rd 1
cardwidth = 80
cardheight = 120
radius = 4 ; not recommended to change
rowsize = 30 ; distance between top poins
;of cards in neighboring rows
columnspace = 5 ; minimal space between cards
margin = 14 ; margin of every card
topbuttonsbarheight = 20
meos_app_end