; <--- 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 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 title db '������',0 new_game: db "����� ���" new_game_len = $ - new_game exit: db "��室" exit_len = $ - exit s: db "10" else if lang eq 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