From b464de6265884f6dbd1b75012d371d78ba189281 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 27 Feb 2026 11:10:19 +0000 Subject: [PATCH 01/19] Upload files to "programs/games" --- programs/games/solitare.asm | 1062 +++++++++++++++++++++++++++++++++++ 1 file changed, 1062 insertions(+) create mode 100644 programs/games/solitare.asm diff --git a/programs/games/solitare.asm b/programs/games/solitare.asm new file mode 100644 index 000000000..b0d670485 --- /dev/null +++ b/programs/games/solitare.asm @@ -0,0 +1,1062 @@ +Format binary as 'run' +use32 +org 0x0 + +db 'MENUET01' +dd 0x01 +dd start +dd i_end +dd mem_end +dd stacktop +dd 0, 0 + +; --- STAŁE --- +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 + +; --- PROCEDURY RYSOWANIA --- + +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 + ; --- LEWY GÓRNY RÓG (Margines 3px) --- + 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 ; Ikona obok rangi + mov esi, eax + call draw_char_to_buf + + ; --- PRAWY DOLNY RÓG (Symetryczny Margines 3px) --- + pop esi + pop edx + push edx + push esi + movzx ebx, word [esi+4] + add ebx, CARD_W - 8 ; (50 - 3 marginesu - 5 szerokości fontu = 42, czyli add 42) + movzx ecx, word [esi+6] + add ecx, CARD_H - 10 ; (70 - 3 marginesu - 7 wysokości fontu = 60, czyli add 60) + + ; Ranga na dole (najbardziej wysunięta w prawo) + movzx eax, byte [esi] + dec eax + mov esi, eax + call draw_char_to_buf + + ; Ikona koloru obok rangi na dole + pop esi + push esi + movzx eax, byte [esi+1] + add eax, 13 + sub ebx, 6 ; Ikona 6px na lewo od rangi + 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 + +; --- LOGIKA GRY --- + +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 + +; --- DANE --- +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:Kier +db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,00000000b ; 14:Karo +db 00100000b,00100000b,11111000b,11111000b,00100000b,00100000b,01110000b ; 15:Trefl +db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,01110000b ; 16:Pik +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: -- 2.49.1 From 593ae0bd7f464bb8746984d32f164638720a89da Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 27 Feb 2026 18:19:32 +0000 Subject: [PATCH 02/19] Upload files to "programs/games" Hi, this is a simple solitaire game project. --- programs/games/Tupfile.lua | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 programs/games/Tupfile.lua diff --git a/programs/games/Tupfile.lua b/programs/games/Tupfile.lua new file mode 100644 index 000000000..1d55488e1 --- /dev/null +++ b/programs/games/Tupfile.lua @@ -0,0 +1,7 @@ +if tup.getconfig("NO_FASM") ~= "" then return end +HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../.." or tup.getconfig("HELPERDIR") +tup.include(HELPERDIR .. "/use_fasm.lua") +add_include(tup.getvariantdir()) + +tup.rule("echo lang fix " .. ((tup.getconfig("LANG") == "") and "en_US" or tup.getconfig("LANG")) .. " > %o", {"lang.inc"}) +tup.rule("solitare.asm", FASM .. " %f %o " .. tup.getconfig("KPACK_CMD"), "solitare") -- 2.49.1 From 4495fd5981b163a06e22fdb7577ef53b87a20697 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 27 Feb 2026 18:39:23 +0000 Subject: [PATCH 03/19] Update programs/games/Tupfile.lua --- programs/games/Tupfile.lua | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/programs/games/Tupfile.lua b/programs/games/Tupfile.lua index 1d55488e1..027c55204 100644 --- a/programs/games/Tupfile.lua +++ b/programs/games/Tupfile.lua @@ -1,7 +1,2 @@ if tup.getconfig("NO_FASM") ~= "" then return end -HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../.." or tup.getconfig("HELPERDIR") -tup.include(HELPERDIR .. "/use_fasm.lua") -add_include(tup.getvariantdir()) - -tup.rule("echo lang fix " .. ((tup.getconfig("LANG") == "") and "en_US" or tup.getconfig("LANG")) .. " > %o", {"lang.inc"}) -tup.rule("solitare.asm", FASM .. " %f %o " .. tup.getconfig("KPACK_CMD"), "solitare") +tup.rule("solitare.asm", "fasm %f %o " .. tup.getconfig("KPACK_CMD"), "solitare") -- 2.49.1 From 756fa8dd66eaa6e7bf31d78f9a3d09fc47314260 Mon Sep 17 00:00:00 2001 From: Taldariner <71024372+Taldariner@users.noreply.github.com> Date: Fri, 27 Feb 2026 20:50:04 +0200 Subject: [PATCH 04/19] apps/solitaires: fix build, translate comments to English --- programs/games/{ => solitaires}/Tupfile.lua | 2 +- .../solitaires.asm} | 32 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) rename programs/games/{ => solitaires}/Tupfile.lua (79%) rename programs/games/{solitare.asm => solitaires/solitaires.asm} (96%) diff --git a/programs/games/Tupfile.lua b/programs/games/solitaires/Tupfile.lua similarity index 79% rename from programs/games/Tupfile.lua rename to programs/games/solitaires/Tupfile.lua index 1d55488e1..2aa8e1401 100644 --- a/programs/games/Tupfile.lua +++ b/programs/games/solitaires/Tupfile.lua @@ -4,4 +4,4 @@ tup.include(HELPERDIR .. "/use_fasm.lua") add_include(tup.getvariantdir()) tup.rule("echo lang fix " .. ((tup.getconfig("LANG") == "") and "en_US" or tup.getconfig("LANG")) .. " > %o", {"lang.inc"}) -tup.rule("solitare.asm", FASM .. " %f %o " .. tup.getconfig("KPACK_CMD"), "solitare") +tup.rule("solitares.asm", FASM .. " %f %o " .. tup.getconfig("KPACK_CMD"), "solitares") diff --git a/programs/games/solitare.asm b/programs/games/solitaires/solitaires.asm similarity index 96% rename from programs/games/solitare.asm rename to programs/games/solitaires/solitaires.asm index b0d670485..b6d1d0957 100644 --- a/programs/games/solitare.asm +++ b/programs/games/solitaires/solitaires.asm @@ -10,7 +10,7 @@ dd mem_end dd stacktop dd 0, 0 -; --- STAŁE --- +; --- CONSTANTS --- CARD_W equ 50 CARD_H equ 70 STACK_OFFSET equ 22 @@ -191,7 +191,7 @@ on_redraw: int 0x40 jmp event_loop -; --- PROCEDURY RYSOWANIA --- +; --- DRAWING PROCEDURES --- draw_char_to_buf: pushad @@ -266,7 +266,7 @@ draw_card_to_buffer: .is_red: push edx push esi - ; --- LEWY GÓRNY RÓG (Margines 3px) --- + ; --- TOP-LEFT CORNER (3px margin) --- movzx eax, byte [esi] dec eax mov esi, eax @@ -277,32 +277,32 @@ draw_card_to_buffer: push esi movzx eax, byte [esi+1] add eax, 13 - add ebx, 6 ; Ikona obok rangi + add ebx, 6 ; Suit icon next to rank mov esi, eax call draw_char_to_buf - ; --- PRAWY DOLNY RÓG (Symetryczny Margines 3px) --- + ; --- 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 marginesu - 5 szerokości fontu = 42, czyli add 42) + 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 marginesu - 7 wysokości fontu = 60, czyli add 60) + add ecx, CARD_H - 10 ; (70 - 3 margin - 7 font height = 60, so add 60) - ; Ranga na dole (najbardziej wysunięta w prawo) + ; Rank at the bottom (furthest to the right) movzx eax, byte [esi] dec eax mov esi, eax call draw_char_to_buf - ; Ikona koloru obok rangi na dole + ; Suit icon next to the bottom rank pop esi push esi movzx eax, byte [esi+1] add eax, 13 - sub ebx, 6 ; Ikona 6px na lewo od rangi + sub ebx, 6 ; Icon 6px to the left of rank mov esi, eax call draw_char_to_buf @@ -365,7 +365,7 @@ draw_slots: popad ret -; --- LOGIKA GRY --- +; --- GAME LOGIC --- is_card_active: push eax @@ -1001,7 +1001,7 @@ layout_tableau: jmp .sf .fin: ret -; --- DANE --- +; --- DATA --- title db 'Solitaire Symmetric Corner', 0 score dd 0 game_won db 0 @@ -1030,10 +1030,10 @@ 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:Kier -db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,00000000b ; 14:Karo -db 00100000b,00100000b,11111000b,11111000b,00100000b,00100000b,01110000b ; 15:Trefl -db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,01110000b ; 16:Pik +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 -- 2.49.1 From 8d55a1cfc841429fddf5e538fde5d74533ef6292 Mon Sep 17 00:00:00 2001 From: Burer Date: Fri, 27 Feb 2026 20:55:35 +0200 Subject: [PATCH 05/19] games/solitaries: fix build, part 2 --- programs/games/solitaires/Tupfile.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/games/solitaires/Tupfile.lua b/programs/games/solitaires/Tupfile.lua index 2aa8e1401..845fcab75 100644 --- a/programs/games/solitaires/Tupfile.lua +++ b/programs/games/solitaires/Tupfile.lua @@ -4,4 +4,4 @@ tup.include(HELPERDIR .. "/use_fasm.lua") add_include(tup.getvariantdir()) tup.rule("echo lang fix " .. ((tup.getconfig("LANG") == "") and "en_US" or tup.getconfig("LANG")) .. " > %o", {"lang.inc"}) -tup.rule("solitares.asm", FASM .. " %f %o " .. tup.getconfig("KPACK_CMD"), "solitares") +tup.rule("solitaires.asm", FASM .. " %f %o " .. tup.getconfig("KPACK_CMD"), "solitaires") -- 2.49.1 From 79f8b27cfe4a0e7e56fa651abba46d6aecd62194 Mon Sep 17 00:00:00 2001 From: Burer Date: Fri, 27 Feb 2026 21:08:05 +0200 Subject: [PATCH 06/19] games/solitaires: add to image build --- data/Tupfile.lua | 1 + programs/games/{solitaires => solitare}/Tupfile.lua | 2 +- .../games/{solitaires/solitaires.asm => solitare/solitare.asm} | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename programs/games/{solitaires => solitare}/Tupfile.lua (79%) rename programs/games/{solitaires/solitaires.asm => solitare/solitare.asm} (100%) diff --git a/data/Tupfile.lua b/data/Tupfile.lua index b5dce6c1c..bab1c92cd 100644 --- a/data/Tupfile.lua +++ b/data/Tupfile.lua @@ -506,6 +506,7 @@ tup.append_table(img_files, { {"GAMES/TANKS", VAR_PROGS .. "/games/tanks/tanks"}, {"GAMES/TETRIS", VAR_PROGS .. "/games/tetris/tetris"}, {"GAMES/C4", VAR_PROGS .. "/games/c4/c4"}, + {"GAMES/SOLITARE", VAR_PROGS .. "/games/solitare/solitare"}, {"LIB/ARCHIVER.OBJ", VAR_PROGS .. "/fs/kfar/trunk/kfar_arc/kfar_arc.obj"}, {"LIB/BOX_LIB.OBJ", VAR_PROGS .. "/develop/libraries/box_lib/trunk/box_lib.obj"}, {"LIB/BUF2D.OBJ", VAR_PROGS .. "/develop/libraries/buf2d/trunk/buf2d.obj"}, diff --git a/programs/games/solitaires/Tupfile.lua b/programs/games/solitare/Tupfile.lua similarity index 79% rename from programs/games/solitaires/Tupfile.lua rename to programs/games/solitare/Tupfile.lua index 845fcab75..1d55488e1 100644 --- a/programs/games/solitaires/Tupfile.lua +++ b/programs/games/solitare/Tupfile.lua @@ -4,4 +4,4 @@ tup.include(HELPERDIR .. "/use_fasm.lua") add_include(tup.getvariantdir()) tup.rule("echo lang fix " .. ((tup.getconfig("LANG") == "") and "en_US" or tup.getconfig("LANG")) .. " > %o", {"lang.inc"}) -tup.rule("solitaires.asm", FASM .. " %f %o " .. tup.getconfig("KPACK_CMD"), "solitaires") +tup.rule("solitare.asm", FASM .. " %f %o " .. tup.getconfig("KPACK_CMD"), "solitare") diff --git a/programs/games/solitaires/solitaires.asm b/programs/games/solitare/solitare.asm similarity index 100% rename from programs/games/solitaires/solitaires.asm rename to programs/games/solitare/solitare.asm -- 2.49.1 From 7cb981914d51ee5106fd21666d49db86795687e4 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 27 Feb 2026 19:23:44 +0000 Subject: [PATCH 07/19] Update programs/games/solitare/solitare.asm --- programs/games/solitare/solitare.asm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm index b6d1d0957..7408cc146 100644 --- a/programs/games/solitare/solitare.asm +++ b/programs/games/solitare/solitare.asm @@ -1,3 +1,9 @@ +; +; The Solitare +; Author: Max +; Compile with FASM +; + Format binary as 'run' use32 org 0x0 -- 2.49.1 From 932a0fed7d7dcafe8dc71b6da7fe830fa51881d2 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 27 Feb 2026 20:09:48 +0000 Subject: [PATCH 08/19] Update programs/games/solitare/solitare.asm --- programs/games/solitare/solitare.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm index 7408cc146..4be62bf9b 100644 --- a/programs/games/solitare/solitare.asm +++ b/programs/games/solitare/solitare.asm @@ -1,5 +1,5 @@ ; -; The Solitare +; Solitare ; Author: Max ; Compile with FASM ; -- 2.49.1 From e2b3ccf5413d96bfd1fa80eeaab4678a84f15af7 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Mar 2026 12:28:31 +0000 Subject: [PATCH 09/19] Delete programs/games/solitare/solitare.asm --- programs/games/solitare/solitare.asm | 1068 -------------------------- 1 file changed, 1068 deletions(-) delete mode 100644 programs/games/solitare/solitare.asm diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm deleted file mode 100644 index 4be62bf9b..000000000 --- a/programs/games/solitare/solitare.asm +++ /dev/null @@ -1,1068 +0,0 @@ -; -; 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: -- 2.49.1 From 848719b5c1bf228d5749bc58b033c98e1dfdcfdc Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Mar 2026 12:30:28 +0000 Subject: [PATCH 10/19] Upload files to "programs/games/solitare" Refactored version of CARD game --- programs/games/solitare/solitare.asm | 1140 ++++++++++++++++++++++++++ 1 file changed, 1140 insertions(+) create mode 100644 programs/games/solitare/solitare.asm diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm new file mode 100644 index 000000000..a2a6ca0bc --- /dev/null +++ b/programs/games/solitare/solitare.asm @@ -0,0 +1,1140 @@ +; Solitare - Refactored Version +; Author: Max +; Compile with FASM + +format binary as 'run' +use32 +org 0x0 + +; --- SYSTEM MACROS --- +macro mcall a,b,c,d,e,f { + if ~ a eq + mov eax, a + end if + if ~ b eq + mov ebx, b + end if + if ~ c eq + mov ecx, c + end if + if ~ d eq + mov edx, d + end if + if ~ e eq + mov esi, e + end if + if ~ f eq + mov edi, f + end if + int 0x40 +} + +; --- CONSTANTS --- +; System Functions +SYS_REDRAW equ 12 +SYS_KEY equ 2 +SYS_BUTTON equ 17 +SYS_MOUSE_POS equ 37 +SYS_DRAW_WINDOW equ 0 +SYS_EXIT equ -1 +SYS_BLIT equ 7 +SYS_RANDOM equ 3 +SYS_DELAY equ 5 + +; Card Structure Offsets +CARD_VALUE equ 0 +CARD_SUIT equ 1 +CARD_STATE equ 2 ; 0=Face Down, 1=Face Up +CARD_LOC equ 3 ; 0-6=Tableau, 7=Stock, 8=Found, 9=Waste +CARD_X equ 4 +CARD_Y equ 6 +CARD_OLD_X equ 8 +CARD_OLD_Y equ 10 +CARD_STRUCT_SIZE equ 12 + +; Game 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 + +; Colors +COL_TABLE equ 0x207020 +COL_REVERSE equ 0x0000AA +COL_WHITE equ 0xFFFFFF +COL_RED equ 0xCC0000 +COL_BLACK equ 0x000000 +COL_SLOT equ 0x185018 + +; Positions +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 + +; --- HEADER --- +db 'MENUET01' +dd 0x01 +dd start +dd i_end +dd mem_end +dd stacktop +dd 0, 0 + +start: + mov esp, stacktop + call init_deck + call shuffle_deck + call layout_tableau + mov dword [score], 0 + mov byte [game_won], 0 + +event_loop: + mcall 11 ; Check event + 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 + + mcall SYS_DELAY, 2 ; Yield CPU + jmp event_loop + +on_key: + mcall SYS_KEY + jmp event_loop + +on_button: + mcall SYS_BUTTON + shr eax, 8 + cmp eax, 1 + jne event_loop + mcall SYS_EXIT + +on_redraw: + mcall SYS_REDRAW, 1 ; Start Redraw + + ; Draw Window + mcall SYS_DRAW_WINDOW, 100 shl 16 + WIN_W, 100 shl 16 + WIN_H, 0x01000000 or COL_TABLE, , title + + ; Clear Buffer + 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 + + ; Exit Button + 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 + + ; Draw Static Cards + xor ecx, ecx +.draw_loop: + call is_card_active + jc .skip + push ecx + imul esi, ecx, CARD_STRUCT_SIZE + add esi, deck_data + call draw_card_to_buffer + pop ecx +.skip: + inc ecx + cmp ecx, 52 + jl .draw_loop + + ; Draw Active (Dragged) Cards + xor ecx, ecx +.draw_active: + cmp ecx, [active_card_count] + jae .draw_score + push ecx + mov eax, [active_stack + ecx*4] + imul esi, eax, CARD_STRUCT_SIZE + add esi, deck_data + call draw_card_to_buffer + pop ecx + inc ecx + jmp .draw_active + +.draw_score: + call render_score_ui + +.blit: + mcall SYS_BLIT, screen_buffer, WIN_W shl 16 + WIN_H, 0 + mcall SYS_REDRAW, 2 ; End Redraw + jmp event_loop + +; --- UI HELPERS --- + +render_score_ui: + mov edx, COL_BLACK + mov ebx, 620 + mov ecx, 570 + mov esi, 17 ; 'S' + call draw_char_to_buf + add ebx, 7 + mov esi, 18 ; 'C' + call draw_char_to_buf + add ebx, 7 + mov esi, 19 ; 'O' + call draw_char_to_buf + add ebx, 7 + mov esi, 20 ; 'R' + call draw_char_to_buf + add ebx, 7 + mov esi, 21 ; 'E' + 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 ; Font offset for '0' + 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 + ret + +; --- 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+CARD_X] + movzx ecx, word [esi+CARD_Y] + 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+CARD_STATE], 1 + je .face_up + + ; Draw Card Back + 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+CARD_SUIT], 2 + jb .is_red + mov edx, COL_BLACK +.is_red: + push edx + push esi + ; Rank and Suit Top-Left + movzx eax, byte [esi+CARD_VALUE] + dec eax + mov esi, eax + add ebx, 3 + add ecx, 3 + call draw_char_to_buf + + pop esi + push esi + movzx eax, byte [esi+CARD_SUIT] + add eax, 13 + add ebx, 6 + mov esi, eax + call draw_char_to_buf + + ; Rank and Suit Bottom-Right + pop esi + pop edx + push edx + push esi + movzx ebx, word [esi+CARD_X] + add ebx, CARD_W - 8 + movzx ecx, word [esi+CARD_Y] + add ecx, CARD_H - 10 + + movzx eax, byte [esi+CARD_VALUE] + dec eax + mov esi, eax + call draw_char_to_buf + + pop esi + push esi + movzx eax, byte [esi+CARD_SUIT] + add eax, 13 + sub ebx, 6 + 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 + mcall SYS_MOUSE_POS, 0 + mov ebp, eax + shr ebp, 16 + and eax, 0xFFFF + mov edi, eax + + mcall SYS_MOUSE_POS, 2 + test eax, 1 + jnz .dragging_state + + ; Mouse Released + 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 + + ; Exit Check + 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 + mcall SYS_EXIT + +.no_exit: + ; Stock Click + 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, CARD_STRUCT_SIZE + add edx, deck_data + movzx esi, word [edx+CARD_X] + movzx ecx, word [edx+CARD_Y] + 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+CARD_STATE], 1 + jne .next_s + + ; Found Card to Drag + mov dword [mouse_lock], 1 + mov [active_stack], ebx + mov dword [active_card_count], 1 + mov ax, [edx+CARD_X] + sub ax, bp + mov [mouse_off_x], ax + mov ax, [edx+CARD_Y] + 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, CARD_STRUCT_SIZE + add eax, deck_data + mov dx, [mouse_off_x] + add dx, bp + mov [eax+CARD_X], 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+CARD_Y], dx + inc ecx + jmp .d_lp +.exit_drag: + popad + ret + +build_active_stack: + pushad + imul esi, eax, CARD_STRUCT_SIZE + add esi, deck_data + mov bx, [esi+CARD_X] + mov dx, [esi+CARD_Y] + movzx ebp, dx + add ebp, STACK_OFFSET +.y_search: + xor ecx, ecx +.l: + imul edi, ecx, CARD_STRUCT_SIZE + add edi, deck_data + cmp word [edi+CARD_X], bx + jne .nx + cmp word [edi+CARD_Y], 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, CARD_STRUCT_SIZE + add eax, deck_data + mov dx, [eax+CARD_X] + mov [eax+CARD_OLD_X], dx + mov dx, [eax+CARD_Y] + mov [eax+CARD_OLD_Y], dx + inc ecx + jmp .save +.fin: + popad + ret + +check_stack_move: + pushad + mov esi, [active_stack] + imul esi, CARD_STRUCT_SIZE + add esi, deck_data + cmp dword [active_card_count], 1 + jne .tableau_check + + ; Check Foundations + mov ebx, FOUNDATION_X + xor ecx, ecx +.f_lp: + mov ax, [esi+CARD_X] + sub ax, bx + add ax, 25 + cmp ax, 50 + ja .next_f + mov ax, [esi+CARD_Y] + 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, CARD_STRUCT_SIZE + add edi, deck_data + push ecx + call is_card_active + pop ecx + jc .sk_l + cmp word [edi+CARD_X], bx + jne .sk_l + movzx eax, word [edi+CARD_Y] + 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 + + ; Logic for placing on another card + mov ecx, [temp_val] + imul edi, ecx, CARD_STRUCT_SIZE + add edi, deck_data + mov ax, [esi+CARD_X] + mov dx, [edi+CARD_X] + sub ax, dx + add ax, 25 + cmp ax, 50 + ja .nx_col + mov ax, [esi+CARD_Y] + mov dx, [edi+CARD_Y] + sub ax, dx + add ax, 30 + cmp ax, 60 + ja .nx_col + + ; Alternate colors and value-1 + mov al, [esi+CARD_SUIT] + mov dl, [edi+CARD_SUIT] + shr al, 1 + shr dl, 1 + cmp al, dl + je .nx_col + mov al, [esi+CARD_VALUE] + mov dl, [edi+CARD_VALUE] + inc al + cmp al, dl + jne .nx_col + mov dx, [edi+CARD_Y] + add dx, STACK_OFFSET + jmp .apply_move + +.empty_col: + mov ax, [esi+CARD_X] + sub ax, bx + add ax, 25 + cmp ax, 50 + ja .nx_col + mov ax, [esi+CARD_Y] + sub ax, 120 + add ax, 30 + cmp ax, 60 + ja .nx_col + cmp byte [esi+CARD_VALUE], 13 ; Must be King + jne .nx_col + mov dx, 120 + jmp .apply_move + +.nx_col: + add ebx, 100 + cmp ebx, 750 + jl .col_lp + + ; No valid move - Return to Old Pos + xor ecx, ecx +.back: + cmp ecx, [active_card_count] + jae .out + mov eax, [active_stack + ecx*4] + imul eax, CARD_STRUCT_SIZE + add eax, deck_data + mov dx, [eax+CARD_OLD_X] + mov [eax+CARD_X], dx + mov dx, [eax+CARD_OLD_Y] + mov [eax+CARD_Y], dx + inc ecx + jmp .back +.out: + popad + ret + +.found_match: + add dword [score], 10 + mov [esi+CARD_X], bx + mov word [esi+CARD_Y], FOUND_Y + mov byte [esi+CARD_LOC], 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, CARD_STRUCT_SIZE + add eax, deck_data + mov [eax+CARD_X], bx + mov dx, word [temp_counter2] + mov [eax+CARD_Y], dx + mov dl, byte [temp_val] + mov [eax+CARD_LOC], 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 +.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, CARD_STRUCT_SIZE + add edi, deck_data + cmp [edi+CARD_X], bx + jne .nx_c + cmp word [edi+CARD_Y], FOUND_Y + jne .nx_c + movzx edx, byte [edi+CARD_VALUE] + 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+CARD_VALUE] + mov dl, [esi+CARD_SUIT] + cmp dword [temp_counter], -1 + jne .not_empty + cmp al, 1 ; Must be Ace + je .valid + jmp .invalid +.not_empty: + mov edi, [temp_counter] + imul edi, 12 + add edi, deck_data + cmp dl, [edi+CARD_SUIT] + jne .invalid + mov dl, [edi+CARD_VALUE] + 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, CARD_STRUCT_SIZE + add esi, deck_data + cmp byte [esi+CARD_LOC], 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, CARD_STRUCT_SIZE + add edi, deck_data + cmp [edi+CARD_X], bx + jne .next_card + movzx eax, word [edi+CARD_Y] + 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+CARD_STATE], 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, CARD_STRUCT_SIZE + add esi, deck_data + mov edi, temp_card_buf + mov ecx, 3 + rep movsd + + mov eax, [temp_active] + inc eax + imul esi, eax, CARD_STRUCT_SIZE + add esi, deck_data + imul edi, [temp_active], CARD_STRUCT_SIZE + 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 * CARD_STRUCT_SIZE) + mov ecx, 3 + rep movsd +.done: ret + +deal_from_stock: + pushad + mov ecx, 51 +.f: + imul esi, ecx, CARD_STRUCT_SIZE + add esi, deck_data + cmp byte [esi+CARD_LOC], 7 + jne .n + cmp byte [esi+CARD_STATE], 0 + je .o +.n: dec ecx + jns .f + call reset_stock + popad + ret +.o: + mov byte [esi+CARD_STATE], 1 + mov byte [esi+CARD_LOC], 9 + mov word [esi+CARD_X], WASTE_X + mov word [esi+CARD_Y], 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, CARD_STRUCT_SIZE + add esi, deck_data + cmp byte [esi+CARD_LOC], 9 + jne .s + mov byte [esi+CARD_STATE], 0 + mov byte [esi+CARD_LOC], 7 + mov word [esi+CARD_X], STOCK_X + mov word [esi+CARD_Y], 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+CARD_VALUE], bl + mov [edi+CARD_SUIT], al + mov byte [edi+CARD_STATE], 0 + mov byte [edi+CARD_LOC], 7 + add edi, CARD_STRUCT_SIZE + cmp ebx, 13 + jne .r + inc eax + cmp eax, 4 + jne .s + ret + +shuffle_deck: + mov dword [temp_counter2], 51 +.sh: + mcall SYS_RANDOM + and eax, 0xFFFF + xor edx, edx + mov ebx, [temp_counter2] + inc ebx + div ebx + imul esi, [temp_counter2], CARD_STRUCT_SIZE + add esi, deck_data + imul edi, edx, CARD_STRUCT_SIZE + 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+CARD_X], bx + mov [edi+CARD_Y], cx + mov byte [edi+CARD_LOC], dl + dec ebp + jnz .h + mov byte [edi+CARD_STATE], 1 + jmp .nx +.h: + mov byte [edi+CARD_STATE], 0 +.nx: + add edi, CARD_STRUCT_SIZE + 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 * CARD_STRUCT_SIZE) + jae .fin + mov word [edi+CARD_X], STOCK_X + mov word [edi+CARD_Y], FOUND_Y + mov byte [edi+CARD_LOC], 7 + mov byte [edi+CARD_STATE], 0 + add edi, CARD_STRUCT_SIZE + jmp .sf +.fin: ret + +; --- DATA --- +title db 'Solitare V1.1', 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: +; Font bitmap data remains unchanged... +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,11111000b ; 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 * CARD_STRUCT_SIZE +i_end: + +align 4096 +screen_buffer: rb WIN_W * WIN_H * 3 + 32768 +stack_bottom: rb 8192 +stacktop: +mem_end: -- 2.49.1 From c9484c2f9b1e30f8785e8cbf0921927181e5119f Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Mar 2026 13:55:03 +0000 Subject: [PATCH 11/19] Delete programs/games/solitare/solitare.asm --- programs/games/solitare/solitare.asm | 1140 -------------------------- 1 file changed, 1140 deletions(-) delete mode 100644 programs/games/solitare/solitare.asm diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm deleted file mode 100644 index a2a6ca0bc..000000000 --- a/programs/games/solitare/solitare.asm +++ /dev/null @@ -1,1140 +0,0 @@ -; Solitare - Refactored Version -; Author: Max -; Compile with FASM - -format binary as 'run' -use32 -org 0x0 - -; --- SYSTEM MACROS --- -macro mcall a,b,c,d,e,f { - if ~ a eq - mov eax, a - end if - if ~ b eq - mov ebx, b - end if - if ~ c eq - mov ecx, c - end if - if ~ d eq - mov edx, d - end if - if ~ e eq - mov esi, e - end if - if ~ f eq - mov edi, f - end if - int 0x40 -} - -; --- CONSTANTS --- -; System Functions -SYS_REDRAW equ 12 -SYS_KEY equ 2 -SYS_BUTTON equ 17 -SYS_MOUSE_POS equ 37 -SYS_DRAW_WINDOW equ 0 -SYS_EXIT equ -1 -SYS_BLIT equ 7 -SYS_RANDOM equ 3 -SYS_DELAY equ 5 - -; Card Structure Offsets -CARD_VALUE equ 0 -CARD_SUIT equ 1 -CARD_STATE equ 2 ; 0=Face Down, 1=Face Up -CARD_LOC equ 3 ; 0-6=Tableau, 7=Stock, 8=Found, 9=Waste -CARD_X equ 4 -CARD_Y equ 6 -CARD_OLD_X equ 8 -CARD_OLD_Y equ 10 -CARD_STRUCT_SIZE equ 12 - -; Game 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 - -; Colors -COL_TABLE equ 0x207020 -COL_REVERSE equ 0x0000AA -COL_WHITE equ 0xFFFFFF -COL_RED equ 0xCC0000 -COL_BLACK equ 0x000000 -COL_SLOT equ 0x185018 - -; Positions -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 - -; --- HEADER --- -db 'MENUET01' -dd 0x01 -dd start -dd i_end -dd mem_end -dd stacktop -dd 0, 0 - -start: - mov esp, stacktop - call init_deck - call shuffle_deck - call layout_tableau - mov dword [score], 0 - mov byte [game_won], 0 - -event_loop: - mcall 11 ; Check event - 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 - - mcall SYS_DELAY, 2 ; Yield CPU - jmp event_loop - -on_key: - mcall SYS_KEY - jmp event_loop - -on_button: - mcall SYS_BUTTON - shr eax, 8 - cmp eax, 1 - jne event_loop - mcall SYS_EXIT - -on_redraw: - mcall SYS_REDRAW, 1 ; Start Redraw - - ; Draw Window - mcall SYS_DRAW_WINDOW, 100 shl 16 + WIN_W, 100 shl 16 + WIN_H, 0x01000000 or COL_TABLE, , title - - ; Clear Buffer - 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 - - ; Exit Button - 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 - - ; Draw Static Cards - xor ecx, ecx -.draw_loop: - call is_card_active - jc .skip - push ecx - imul esi, ecx, CARD_STRUCT_SIZE - add esi, deck_data - call draw_card_to_buffer - pop ecx -.skip: - inc ecx - cmp ecx, 52 - jl .draw_loop - - ; Draw Active (Dragged) Cards - xor ecx, ecx -.draw_active: - cmp ecx, [active_card_count] - jae .draw_score - push ecx - mov eax, [active_stack + ecx*4] - imul esi, eax, CARD_STRUCT_SIZE - add esi, deck_data - call draw_card_to_buffer - pop ecx - inc ecx - jmp .draw_active - -.draw_score: - call render_score_ui - -.blit: - mcall SYS_BLIT, screen_buffer, WIN_W shl 16 + WIN_H, 0 - mcall SYS_REDRAW, 2 ; End Redraw - jmp event_loop - -; --- UI HELPERS --- - -render_score_ui: - mov edx, COL_BLACK - mov ebx, 620 - mov ecx, 570 - mov esi, 17 ; 'S' - call draw_char_to_buf - add ebx, 7 - mov esi, 18 ; 'C' - call draw_char_to_buf - add ebx, 7 - mov esi, 19 ; 'O' - call draw_char_to_buf - add ebx, 7 - mov esi, 20 ; 'R' - call draw_char_to_buf - add ebx, 7 - mov esi, 21 ; 'E' - 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 ; Font offset for '0' - 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 - ret - -; --- 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+CARD_X] - movzx ecx, word [esi+CARD_Y] - 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+CARD_STATE], 1 - je .face_up - - ; Draw Card Back - 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+CARD_SUIT], 2 - jb .is_red - mov edx, COL_BLACK -.is_red: - push edx - push esi - ; Rank and Suit Top-Left - movzx eax, byte [esi+CARD_VALUE] - dec eax - mov esi, eax - add ebx, 3 - add ecx, 3 - call draw_char_to_buf - - pop esi - push esi - movzx eax, byte [esi+CARD_SUIT] - add eax, 13 - add ebx, 6 - mov esi, eax - call draw_char_to_buf - - ; Rank and Suit Bottom-Right - pop esi - pop edx - push edx - push esi - movzx ebx, word [esi+CARD_X] - add ebx, CARD_W - 8 - movzx ecx, word [esi+CARD_Y] - add ecx, CARD_H - 10 - - movzx eax, byte [esi+CARD_VALUE] - dec eax - mov esi, eax - call draw_char_to_buf - - pop esi - push esi - movzx eax, byte [esi+CARD_SUIT] - add eax, 13 - sub ebx, 6 - 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 - mcall SYS_MOUSE_POS, 0 - mov ebp, eax - shr ebp, 16 - and eax, 0xFFFF - mov edi, eax - - mcall SYS_MOUSE_POS, 2 - test eax, 1 - jnz .dragging_state - - ; Mouse Released - 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 - - ; Exit Check - 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 - mcall SYS_EXIT - -.no_exit: - ; Stock Click - 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, CARD_STRUCT_SIZE - add edx, deck_data - movzx esi, word [edx+CARD_X] - movzx ecx, word [edx+CARD_Y] - 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+CARD_STATE], 1 - jne .next_s - - ; Found Card to Drag - mov dword [mouse_lock], 1 - mov [active_stack], ebx - mov dword [active_card_count], 1 - mov ax, [edx+CARD_X] - sub ax, bp - mov [mouse_off_x], ax - mov ax, [edx+CARD_Y] - 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, CARD_STRUCT_SIZE - add eax, deck_data - mov dx, [mouse_off_x] - add dx, bp - mov [eax+CARD_X], 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+CARD_Y], dx - inc ecx - jmp .d_lp -.exit_drag: - popad - ret - -build_active_stack: - pushad - imul esi, eax, CARD_STRUCT_SIZE - add esi, deck_data - mov bx, [esi+CARD_X] - mov dx, [esi+CARD_Y] - movzx ebp, dx - add ebp, STACK_OFFSET -.y_search: - xor ecx, ecx -.l: - imul edi, ecx, CARD_STRUCT_SIZE - add edi, deck_data - cmp word [edi+CARD_X], bx - jne .nx - cmp word [edi+CARD_Y], 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, CARD_STRUCT_SIZE - add eax, deck_data - mov dx, [eax+CARD_X] - mov [eax+CARD_OLD_X], dx - mov dx, [eax+CARD_Y] - mov [eax+CARD_OLD_Y], dx - inc ecx - jmp .save -.fin: - popad - ret - -check_stack_move: - pushad - mov esi, [active_stack] - imul esi, CARD_STRUCT_SIZE - add esi, deck_data - cmp dword [active_card_count], 1 - jne .tableau_check - - ; Check Foundations - mov ebx, FOUNDATION_X - xor ecx, ecx -.f_lp: - mov ax, [esi+CARD_X] - sub ax, bx - add ax, 25 - cmp ax, 50 - ja .next_f - mov ax, [esi+CARD_Y] - 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, CARD_STRUCT_SIZE - add edi, deck_data - push ecx - call is_card_active - pop ecx - jc .sk_l - cmp word [edi+CARD_X], bx - jne .sk_l - movzx eax, word [edi+CARD_Y] - 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 - - ; Logic for placing on another card - mov ecx, [temp_val] - imul edi, ecx, CARD_STRUCT_SIZE - add edi, deck_data - mov ax, [esi+CARD_X] - mov dx, [edi+CARD_X] - sub ax, dx - add ax, 25 - cmp ax, 50 - ja .nx_col - mov ax, [esi+CARD_Y] - mov dx, [edi+CARD_Y] - sub ax, dx - add ax, 30 - cmp ax, 60 - ja .nx_col - - ; Alternate colors and value-1 - mov al, [esi+CARD_SUIT] - mov dl, [edi+CARD_SUIT] - shr al, 1 - shr dl, 1 - cmp al, dl - je .nx_col - mov al, [esi+CARD_VALUE] - mov dl, [edi+CARD_VALUE] - inc al - cmp al, dl - jne .nx_col - mov dx, [edi+CARD_Y] - add dx, STACK_OFFSET - jmp .apply_move - -.empty_col: - mov ax, [esi+CARD_X] - sub ax, bx - add ax, 25 - cmp ax, 50 - ja .nx_col - mov ax, [esi+CARD_Y] - sub ax, 120 - add ax, 30 - cmp ax, 60 - ja .nx_col - cmp byte [esi+CARD_VALUE], 13 ; Must be King - jne .nx_col - mov dx, 120 - jmp .apply_move - -.nx_col: - add ebx, 100 - cmp ebx, 750 - jl .col_lp - - ; No valid move - Return to Old Pos - xor ecx, ecx -.back: - cmp ecx, [active_card_count] - jae .out - mov eax, [active_stack + ecx*4] - imul eax, CARD_STRUCT_SIZE - add eax, deck_data - mov dx, [eax+CARD_OLD_X] - mov [eax+CARD_X], dx - mov dx, [eax+CARD_OLD_Y] - mov [eax+CARD_Y], dx - inc ecx - jmp .back -.out: - popad - ret - -.found_match: - add dword [score], 10 - mov [esi+CARD_X], bx - mov word [esi+CARD_Y], FOUND_Y - mov byte [esi+CARD_LOC], 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, CARD_STRUCT_SIZE - add eax, deck_data - mov [eax+CARD_X], bx - mov dx, word [temp_counter2] - mov [eax+CARD_Y], dx - mov dl, byte [temp_val] - mov [eax+CARD_LOC], 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 -.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, CARD_STRUCT_SIZE - add edi, deck_data - cmp [edi+CARD_X], bx - jne .nx_c - cmp word [edi+CARD_Y], FOUND_Y - jne .nx_c - movzx edx, byte [edi+CARD_VALUE] - 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+CARD_VALUE] - mov dl, [esi+CARD_SUIT] - cmp dword [temp_counter], -1 - jne .not_empty - cmp al, 1 ; Must be Ace - je .valid - jmp .invalid -.not_empty: - mov edi, [temp_counter] - imul edi, 12 - add edi, deck_data - cmp dl, [edi+CARD_SUIT] - jne .invalid - mov dl, [edi+CARD_VALUE] - 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, CARD_STRUCT_SIZE - add esi, deck_data - cmp byte [esi+CARD_LOC], 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, CARD_STRUCT_SIZE - add edi, deck_data - cmp [edi+CARD_X], bx - jne .next_card - movzx eax, word [edi+CARD_Y] - 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+CARD_STATE], 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, CARD_STRUCT_SIZE - add esi, deck_data - mov edi, temp_card_buf - mov ecx, 3 - rep movsd - - mov eax, [temp_active] - inc eax - imul esi, eax, CARD_STRUCT_SIZE - add esi, deck_data - imul edi, [temp_active], CARD_STRUCT_SIZE - 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 * CARD_STRUCT_SIZE) - mov ecx, 3 - rep movsd -.done: ret - -deal_from_stock: - pushad - mov ecx, 51 -.f: - imul esi, ecx, CARD_STRUCT_SIZE - add esi, deck_data - cmp byte [esi+CARD_LOC], 7 - jne .n - cmp byte [esi+CARD_STATE], 0 - je .o -.n: dec ecx - jns .f - call reset_stock - popad - ret -.o: - mov byte [esi+CARD_STATE], 1 - mov byte [esi+CARD_LOC], 9 - mov word [esi+CARD_X], WASTE_X - mov word [esi+CARD_Y], 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, CARD_STRUCT_SIZE - add esi, deck_data - cmp byte [esi+CARD_LOC], 9 - jne .s - mov byte [esi+CARD_STATE], 0 - mov byte [esi+CARD_LOC], 7 - mov word [esi+CARD_X], STOCK_X - mov word [esi+CARD_Y], 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+CARD_VALUE], bl - mov [edi+CARD_SUIT], al - mov byte [edi+CARD_STATE], 0 - mov byte [edi+CARD_LOC], 7 - add edi, CARD_STRUCT_SIZE - cmp ebx, 13 - jne .r - inc eax - cmp eax, 4 - jne .s - ret - -shuffle_deck: - mov dword [temp_counter2], 51 -.sh: - mcall SYS_RANDOM - and eax, 0xFFFF - xor edx, edx - mov ebx, [temp_counter2] - inc ebx - div ebx - imul esi, [temp_counter2], CARD_STRUCT_SIZE - add esi, deck_data - imul edi, edx, CARD_STRUCT_SIZE - 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+CARD_X], bx - mov [edi+CARD_Y], cx - mov byte [edi+CARD_LOC], dl - dec ebp - jnz .h - mov byte [edi+CARD_STATE], 1 - jmp .nx -.h: - mov byte [edi+CARD_STATE], 0 -.nx: - add edi, CARD_STRUCT_SIZE - 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 * CARD_STRUCT_SIZE) - jae .fin - mov word [edi+CARD_X], STOCK_X - mov word [edi+CARD_Y], FOUND_Y - mov byte [edi+CARD_LOC], 7 - mov byte [edi+CARD_STATE], 0 - add edi, CARD_STRUCT_SIZE - jmp .sf -.fin: ret - -; --- DATA --- -title db 'Solitare V1.1', 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: -; Font bitmap data remains unchanged... -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,11111000b ; 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 * CARD_STRUCT_SIZE -i_end: - -align 4096 -screen_buffer: rb WIN_W * WIN_H * 3 + 32768 -stack_bottom: rb 8192 -stacktop: -mem_end: -- 2.49.1 From e1320d573f6bbe0e9c4588089d6a234ab5fb12fc Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Mar 2026 13:56:52 +0000 Subject: [PATCH 12/19] Upload files to "programs/games/solitare" New version, Pixel clipping on edge od screen --- programs/games/solitare/solitare.asm | 1154 ++++++++++++++++++++++++++ 1 file changed, 1154 insertions(+) create mode 100644 programs/games/solitare/solitare.asm diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm new file mode 100644 index 000000000..da43222ab --- /dev/null +++ b/programs/games/solitare/solitare.asm @@ -0,0 +1,1154 @@ +; Solitare V1.2 - Fixed Register Size +; Author: Max +; Compile with FASM + +format binary as 'run' +use32 +org 0x0 + +; --- SYSTEM MACROS --- +macro mcall a,b,c,d,e,f { + if ~ a eq + mov eax, a + end if + if ~ b eq + mov ebx, b + end if + if ~ c eq + mov ecx, c + end if + if ~ d eq + mov edx, d + end if + if ~ e eq + mov esi, e + end if + if ~ f eq + mov edi, f + end if + int 0x40 +} + +; --- CONSTANTS --- +SYS_REDRAW equ 12 +SYS_KEY equ 2 +SYS_BUTTON equ 17 +SYS_MOUSE_POS equ 37 +SYS_DRAW_WINDOW equ 0 +SYS_EXIT equ -1 +SYS_BLIT equ 7 +SYS_RANDOM equ 3 +SYS_DELAY equ 5 + +CARD_VALUE equ 0 +CARD_SUIT equ 1 +CARD_STATE equ 2 +CARD_LOC equ 3 +CARD_X equ 4 +CARD_Y equ 6 +CARD_OLD_X equ 8 +CARD_OLD_Y equ 10 +CARD_STRUCT_SIZE equ 12 + +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 + +; --- HEADER --- +db 'MENUET01' +dd 0x01 +dd start +dd i_end +dd mem_end +dd stacktop +dd 0, 0 + +start: + mov esp, stacktop + call init_deck + call shuffle_deck + call layout_tableau + mov dword [score], 0 + mov byte [game_won], 0 + +event_loop: + mcall 11 + 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 + + mcall SYS_DELAY, 2 + jmp event_loop + +on_key: + mcall SYS_KEY + jmp event_loop + +on_button: + mcall SYS_BUTTON + shr eax, 8 + cmp eax, 1 + jne event_loop + mcall SYS_EXIT + +on_redraw: + mcall SYS_REDRAW, 1 + mcall SYS_DRAW_WINDOW, 100 shl 16 + WIN_W, 100 shl 16 + WIN_H, 0x01000000 or COL_TABLE, , title + + ; Clear Buffer + 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 + + ; Exit Button + 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, CARD_STRUCT_SIZE + 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, CARD_STRUCT_SIZE + add esi, deck_data + call draw_card_to_buffer + pop ecx + inc ecx + jmp .draw_active + +.draw_score: + call render_score_ui + +.blit: + mcall SYS_BLIT, screen_buffer, WIN_W shl 16 + WIN_H, 0 + mcall SYS_REDRAW, 2 + jmp event_loop + +; --- DRAWING PROCEDURES --- + +fill_rect_buf: + pushad + mov esi, ebp +.yl: + cmp ecx, 0 + jl .skip_line + cmp ecx, WIN_H + jae .skip_line + + push ecx + push ebx + mov eax, ecx + imul eax, STRIDE + add eax, screen_buffer + + mov dword [temp_counter], edi +.xl: + cmp ebx, 0 + jl .skip_pixel + cmp ebx, WIN_W + jae .skip_pixel + + push eax + mov ecx, ebx + imul ecx, 3 + add eax, ecx + + mov [eax], dl + mov [eax+1], dh + push edx + shr edx, 16 + mov [eax+2], dl + pop edx + pop eax + +.skip_pixel: + inc ebx + dec dword [temp_counter] + jnz .xl + + pop ebx + pop ecx +.skip_line: + inc ecx + dec esi + jnz .yl + popad + ret + +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 + + cmp ebx, 0 + jl .skip_pixel + cmp ebx, WIN_W + jae .skip_pixel + cmp ecx, 0 + jl .skip_pixel + cmp ecx, WIN_H + jae .skip_pixel + + push eax + mov eax, ecx + imul eax, STRIDE + push ebx + imul ebx, 3 + add eax, ebx + pop ebx + 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 + +render_score_ui: + 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 + ret + +draw_card_to_buffer: + pushad + movsx ebx, word [esi+CARD_X] + movsx ecx, word [esi+CARD_Y] + + 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+CARD_STATE], 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+CARD_SUIT], 2 + jb .is_red + mov edx, COL_BLACK +.is_red: + push edx + push esi + movzx eax, byte [esi+CARD_VALUE] + dec eax + mov esi, eax + add ebx, 3 + add ecx, 3 + call draw_char_to_buf + + pop esi + push esi + movzx eax, byte [esi+CARD_SUIT] + add eax, 13 + add ebx, 6 + mov esi, eax + call draw_char_to_buf + + pop esi + pop edx + push edx + push esi + movsx ebx, word [esi+CARD_X] + add ebx, CARD_W - 8 + movsx ecx, word [esi+CARD_Y] + add ecx, CARD_H - 10 + + movzx eax, byte [esi+CARD_VALUE] + dec eax + mov esi, eax + call draw_char_to_buf + + pop esi + push esi + movzx eax, byte [esi+CARD_SUIT] + add eax, 13 + sub ebx, 6 + mov esi, eax + call draw_char_to_buf + + pop esi + pop edx + 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 + +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 + mcall SYS_MOUSE_POS, 0 + mov ebp, eax + shr ebp, 16 + and eax, 0xFFFF + mov edi, eax + + mcall SYS_MOUSE_POS, 2 + 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 + mcall SYS_EXIT + +.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, CARD_STRUCT_SIZE + add edx, deck_data + movsx esi, word [edx+CARD_X] + movsx ecx, word [edx+CARD_Y] + 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+CARD_STATE], 1 + jne .next_s + + mov dword [mouse_lock], 1 + mov [active_stack], ebx + mov dword [active_card_count], 1 + mov ax, word [edx+CARD_X] + sub ax, bp + mov [mouse_off_x], ax + mov ax, word [edx+CARD_Y] + 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, CARD_STRUCT_SIZE + add eax, deck_data + + mov dx, [mouse_off_x] + add dx, bp + mov [eax+CARD_X], 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+CARD_Y], dx + inc ecx + jmp .d_lp +.exit_drag: + popad + ret + +build_active_stack: + pushad + imul esi, eax, CARD_STRUCT_SIZE + add esi, deck_data + mov bx, [esi+CARD_X] + mov dx, [esi+CARD_Y] + movzx ebp, dx + add ebp, STACK_OFFSET +.y_search: + xor ecx, ecx +.l: + imul edi, ecx, CARD_STRUCT_SIZE + add edi, deck_data + cmp word [edi+CARD_X], bx + jne .nx + cmp word [edi+CARD_Y], 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, CARD_STRUCT_SIZE + add eax, deck_data + mov dx, [eax+CARD_X] + mov [eax+CARD_OLD_X], dx + mov dx, [eax+CARD_Y] + mov [eax+CARD_OLD_Y], dx + inc ecx + jmp .save +.fin: + popad + ret + +check_stack_move: + pushad + mov esi, [active_stack] + imul esi, CARD_STRUCT_SIZE + add esi, deck_data + cmp dword [active_card_count], 1 + jne .tableau_check + + mov ebx, FOUNDATION_X + xor ecx, ecx +.f_lp: + movsx eax, word [esi+CARD_X] + sub eax, ebx + add eax, 25 + cmp eax, 50 + ja .next_f + movsx eax, word [esi+CARD_Y] + sub eax, FOUND_Y + add eax, 30 + cmp eax, 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, CARD_STRUCT_SIZE + add edi, deck_data + push ecx + call is_card_active + pop ecx + jc .sk_l + cmp word [edi+CARD_X], bx + jne .sk_l + movzx eax, word [edi+CARD_Y] + 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, CARD_STRUCT_SIZE + add edi, deck_data + movsx eax, word [esi+CARD_X] + movsx edx, word [edi+CARD_X] + sub eax, edx + add eax, 25 + cmp eax, 50 + ja .nx_col + movsx eax, word [esi+CARD_Y] + movsx edx, word [edi+CARD_Y] + sub eax, edx + add eax, 30 + cmp eax, 60 + ja .nx_col + + mov al, [esi+CARD_SUIT] + mov dl, [edi+CARD_SUIT] + shr al, 1 + shr dl, 1 + cmp al, dl + je .nx_col + mov al, [esi+CARD_VALUE] + mov dl, [edi+CARD_VALUE] + inc al + cmp al, dl + jne .nx_col + mov dx, word [edi+CARD_Y] + add dx, STACK_OFFSET + jmp .apply_move + +.empty_col: + movsx eax, word [esi+CARD_X] + sub eax, ebx + add eax, 25 + cmp eax, 50 + ja .nx_col + movsx eax, word [esi+CARD_Y] + sub eax, 120 + add eax, 30 + cmp eax, 60 + ja .nx_col + cmp byte [esi+CARD_VALUE], 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, CARD_STRUCT_SIZE + add eax, deck_data + mov dx, [eax+CARD_OLD_X] + mov [eax+CARD_X], dx + mov dx, [eax+CARD_OLD_Y] + mov [eax+CARD_Y], dx + inc ecx + jmp .back +.out: + popad + ret + +.found_match: + add dword [score], 10 + mov word [esi+CARD_X], bx + mov word [esi+CARD_Y], FOUND_Y + mov byte [esi+CARD_LOC], 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, CARD_STRUCT_SIZE + add eax, deck_data + mov word [eax+CARD_X], bx + mov dx, word [temp_counter2] + mov word [eax+CARD_Y], dx + mov dl, byte [temp_val] + mov byte [eax+CARD_LOC], 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 +.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, CARD_STRUCT_SIZE + add edi, deck_data + cmp word [edi+CARD_X], bx + jne .nx_c + cmp word [edi+CARD_Y], FOUND_Y + jne .nx_c + movzx edx, byte [edi+CARD_VALUE] + 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+CARD_VALUE] + mov dl, [esi+CARD_SUIT] + 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+CARD_SUIT] + jne .invalid + mov dl, [edi+CARD_VALUE] + 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, CARD_STRUCT_SIZE + add esi, deck_data + cmp byte [esi+CARD_LOC], 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, CARD_STRUCT_SIZE + add edi, deck_data + cmp word [edi+CARD_X], bx + jne .next_card + movzx eax, word [edi+CARD_Y] + 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+CARD_STATE], 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, CARD_STRUCT_SIZE + add esi, deck_data + mov edi, temp_card_buf + mov ecx, 3 + rep movsd + + mov eax, [temp_active] + inc eax + imul esi, eax, CARD_STRUCT_SIZE + add esi, deck_data + imul edi, [temp_active], CARD_STRUCT_SIZE + 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 * CARD_STRUCT_SIZE) + mov ecx, 3 + rep movsd +.done: ret + +deal_from_stock: + pushad + mov ecx, 51 +.f: + imul esi, ecx, CARD_STRUCT_SIZE + add esi, deck_data + cmp byte [esi+CARD_LOC], 7 + jne .n + cmp byte [esi+CARD_STATE], 0 + je .o +.n: dec ecx + jns .f + call reset_stock + popad + ret +.o: + mov byte [esi+CARD_STATE], 1 + mov byte [esi+CARD_LOC], 9 + mov word [esi+CARD_X], WASTE_X + mov word [esi+CARD_Y], 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, CARD_STRUCT_SIZE + add esi, deck_data + cmp byte [esi+CARD_LOC], 9 + jne .s + mov byte [esi+CARD_STATE], 0 + mov byte [esi+CARD_LOC], 7 + mov word [esi+CARD_X], STOCK_X + mov word [esi+CARD_Y], 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 byte [edi+CARD_VALUE], bl + mov byte [edi+CARD_SUIT], al + mov byte [edi+CARD_STATE], 0 + mov byte [edi+CARD_LOC], 7 + add edi, CARD_STRUCT_SIZE + cmp ebx, 13 + jne .r + inc eax + cmp eax, 4 + jne .s + ret + +shuffle_deck: + mov dword [temp_counter2], 51 +.sh: + mcall SYS_RANDOM + and eax, 0xFFFF + xor edx, edx + mov ebx, [temp_counter2] + inc ebx + div ebx + imul esi, [temp_counter2], CARD_STRUCT_SIZE + add esi, deck_data + imul edi, edx, CARD_STRUCT_SIZE + 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 word [edi+CARD_X], bx + mov word [edi+CARD_Y], cx + mov byte [edi+CARD_LOC], dl + dec ebp + jnz .h + mov byte [edi+CARD_STATE], 1 + jmp .nx +.h: + mov byte [edi+CARD_STATE], 0 +.nx: + add edi, CARD_STRUCT_SIZE + 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 * CARD_STRUCT_SIZE) + jae .fin + mov word [edi+CARD_X], STOCK_X + mov word [edi+CARD_Y], FOUND_Y + mov byte [edi+CARD_LOC], 7 + mov byte [edi+CARD_STATE], 0 + add edi, CARD_STRUCT_SIZE + jmp .sf +.fin: ret + +; --- DATA --- +title db 'Solitare V1.2 Final', 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 +db 11110000b,00001000b,00010000b,00100000b,01000000b,10000000b,11111000b +db 11110000b,00001000b,00001000b,01110000b,00001000b,00001000b,11110000b +db 10001000b,10001000b,10001000b,11111000b,00001000b,00001000b,00001000b +db 11111000b,10000000b,10000000b,11110000b,00001000b,00001000b,11111000b +db 01110000b,10000000b,10000000b,11110000b,10001000b,10001000b,01110000b +db 11111000b,00001000b,00010000b,00100000b,01000000b,01000000b,01000000b +db 01110000b,10001000b,10001000b,01110000b,10001000b,10001000b,01110000b +db 01110000b,10001000b,10001000b,01111000b,00001000b,00001000b,01110000b +db 10111000b,10101000b,10101000b,10101000b,10101000b,10101000b,10111000b +db 00011000b,00001000b,00001000b,00001000b,00001000b,10001000b,01110000b +db 01110000b,10001000b,10001000b,10001000b,10101000b,10010000b,01101000b +db 10001000b,10010000b,10100000b,11000000b,10100000b,10010000b,10001000b +db 01010000b,11111000b,11111000b,01110000b,00100000b,00000000b,00000000b +db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,00000000b +db 00100000b,00100000b,11111000b,11111000b,00100000b,00100000b,01110000b +db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,01110000b +db 01111000b,10000000b,01110000b,00001000b,00001000b,11110000b,00000000b +db 01110000b,10001000b,10000000b,10000000b,10000000b,10001000b,01110000b +db 01110000b,10001000b,10001000b,10001000b,10001000b,10001000b,01110000b +db 11111000b,10001000b,10001000b,11111000b,10100000b,10010000b,10001000b +db 01111000b,10000000b,10000000b,11110000b,10000000b,10000000b,11111000b +db 00000000b,00000000b,00000000b,11111000b,00000000b,00000000b,00000000b +db 01110000b,10001000b,10001000b,10001000b,10001000b,10001000b,01110000b +db 00100000b,01100000b,00100000b,00100000b,00100000b,00100000b,01110000b +db 01110000b,10001000b,00001000b,01110000b,10000000b,10000000b,11111000b +db 11111000b,00001000b,00010000b,00110000b,00001000b,10001000b,01110000b +db 00010000b,00110000b,01010000b,10010000b,11111000b,00010000b,00010000b +db 11111000b,10000000b,11110000b,00001000b,00001000b,10001000b,01110000b +db 01110000b,10000000b,11110000b,10001000b,10001000b,10001000b,01110000b +db 11111000b,00001000b,00010000b,00100000b,01000000b,01000000b,01000000b +db 01110000b,10001000b,10001000b,01110000b,10001000b,10001000b,01110000b +db 01110000b,10001000b,10001000b,01111000b,00001000b,00001000b,01110000b + +align 4 +deck_data: rb 52 * CARD_STRUCT_SIZE +i_end: + +align 4096 +screen_buffer: rb WIN_W * WIN_H * 3 + 32768 +stack_bottom: rb 8192 +stacktop: +mem_end: -- 2.49.1 From 5a47b26aebf3bfba7cb3c70a5e5509b7f787bb36 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 2 Mar 2026 19:05:36 +0000 Subject: [PATCH 13/19] Delete programs/games/solitare/solitare.asm --- programs/games/solitare/solitare.asm | 1154 -------------------------- 1 file changed, 1154 deletions(-) delete mode 100644 programs/games/solitare/solitare.asm diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm deleted file mode 100644 index da43222ab..000000000 --- a/programs/games/solitare/solitare.asm +++ /dev/null @@ -1,1154 +0,0 @@ -; Solitare V1.2 - Fixed Register Size -; Author: Max -; Compile with FASM - -format binary as 'run' -use32 -org 0x0 - -; --- SYSTEM MACROS --- -macro mcall a,b,c,d,e,f { - if ~ a eq - mov eax, a - end if - if ~ b eq - mov ebx, b - end if - if ~ c eq - mov ecx, c - end if - if ~ d eq - mov edx, d - end if - if ~ e eq - mov esi, e - end if - if ~ f eq - mov edi, f - end if - int 0x40 -} - -; --- CONSTANTS --- -SYS_REDRAW equ 12 -SYS_KEY equ 2 -SYS_BUTTON equ 17 -SYS_MOUSE_POS equ 37 -SYS_DRAW_WINDOW equ 0 -SYS_EXIT equ -1 -SYS_BLIT equ 7 -SYS_RANDOM equ 3 -SYS_DELAY equ 5 - -CARD_VALUE equ 0 -CARD_SUIT equ 1 -CARD_STATE equ 2 -CARD_LOC equ 3 -CARD_X equ 4 -CARD_Y equ 6 -CARD_OLD_X equ 8 -CARD_OLD_Y equ 10 -CARD_STRUCT_SIZE equ 12 - -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 - -; --- HEADER --- -db 'MENUET01' -dd 0x01 -dd start -dd i_end -dd mem_end -dd stacktop -dd 0, 0 - -start: - mov esp, stacktop - call init_deck - call shuffle_deck - call layout_tableau - mov dword [score], 0 - mov byte [game_won], 0 - -event_loop: - mcall 11 - 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 - - mcall SYS_DELAY, 2 - jmp event_loop - -on_key: - mcall SYS_KEY - jmp event_loop - -on_button: - mcall SYS_BUTTON - shr eax, 8 - cmp eax, 1 - jne event_loop - mcall SYS_EXIT - -on_redraw: - mcall SYS_REDRAW, 1 - mcall SYS_DRAW_WINDOW, 100 shl 16 + WIN_W, 100 shl 16 + WIN_H, 0x01000000 or COL_TABLE, , title - - ; Clear Buffer - 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 - - ; Exit Button - 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, CARD_STRUCT_SIZE - 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, CARD_STRUCT_SIZE - add esi, deck_data - call draw_card_to_buffer - pop ecx - inc ecx - jmp .draw_active - -.draw_score: - call render_score_ui - -.blit: - mcall SYS_BLIT, screen_buffer, WIN_W shl 16 + WIN_H, 0 - mcall SYS_REDRAW, 2 - jmp event_loop - -; --- DRAWING PROCEDURES --- - -fill_rect_buf: - pushad - mov esi, ebp -.yl: - cmp ecx, 0 - jl .skip_line - cmp ecx, WIN_H - jae .skip_line - - push ecx - push ebx - mov eax, ecx - imul eax, STRIDE - add eax, screen_buffer - - mov dword [temp_counter], edi -.xl: - cmp ebx, 0 - jl .skip_pixel - cmp ebx, WIN_W - jae .skip_pixel - - push eax - mov ecx, ebx - imul ecx, 3 - add eax, ecx - - mov [eax], dl - mov [eax+1], dh - push edx - shr edx, 16 - mov [eax+2], dl - pop edx - pop eax - -.skip_pixel: - inc ebx - dec dword [temp_counter] - jnz .xl - - pop ebx - pop ecx -.skip_line: - inc ecx - dec esi - jnz .yl - popad - ret - -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 - - cmp ebx, 0 - jl .skip_pixel - cmp ebx, WIN_W - jae .skip_pixel - cmp ecx, 0 - jl .skip_pixel - cmp ecx, WIN_H - jae .skip_pixel - - push eax - mov eax, ecx - imul eax, STRIDE - push ebx - imul ebx, 3 - add eax, ebx - pop ebx - 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 - -render_score_ui: - 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 - ret - -draw_card_to_buffer: - pushad - movsx ebx, word [esi+CARD_X] - movsx ecx, word [esi+CARD_Y] - - 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+CARD_STATE], 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+CARD_SUIT], 2 - jb .is_red - mov edx, COL_BLACK -.is_red: - push edx - push esi - movzx eax, byte [esi+CARD_VALUE] - dec eax - mov esi, eax - add ebx, 3 - add ecx, 3 - call draw_char_to_buf - - pop esi - push esi - movzx eax, byte [esi+CARD_SUIT] - add eax, 13 - add ebx, 6 - mov esi, eax - call draw_char_to_buf - - pop esi - pop edx - push edx - push esi - movsx ebx, word [esi+CARD_X] - add ebx, CARD_W - 8 - movsx ecx, word [esi+CARD_Y] - add ecx, CARD_H - 10 - - movzx eax, byte [esi+CARD_VALUE] - dec eax - mov esi, eax - call draw_char_to_buf - - pop esi - push esi - movzx eax, byte [esi+CARD_SUIT] - add eax, 13 - sub ebx, 6 - mov esi, eax - call draw_char_to_buf - - pop esi - pop edx - 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 - -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 - mcall SYS_MOUSE_POS, 0 - mov ebp, eax - shr ebp, 16 - and eax, 0xFFFF - mov edi, eax - - mcall SYS_MOUSE_POS, 2 - 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 - mcall SYS_EXIT - -.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, CARD_STRUCT_SIZE - add edx, deck_data - movsx esi, word [edx+CARD_X] - movsx ecx, word [edx+CARD_Y] - 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+CARD_STATE], 1 - jne .next_s - - mov dword [mouse_lock], 1 - mov [active_stack], ebx - mov dword [active_card_count], 1 - mov ax, word [edx+CARD_X] - sub ax, bp - mov [mouse_off_x], ax - mov ax, word [edx+CARD_Y] - 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, CARD_STRUCT_SIZE - add eax, deck_data - - mov dx, [mouse_off_x] - add dx, bp - mov [eax+CARD_X], 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+CARD_Y], dx - inc ecx - jmp .d_lp -.exit_drag: - popad - ret - -build_active_stack: - pushad - imul esi, eax, CARD_STRUCT_SIZE - add esi, deck_data - mov bx, [esi+CARD_X] - mov dx, [esi+CARD_Y] - movzx ebp, dx - add ebp, STACK_OFFSET -.y_search: - xor ecx, ecx -.l: - imul edi, ecx, CARD_STRUCT_SIZE - add edi, deck_data - cmp word [edi+CARD_X], bx - jne .nx - cmp word [edi+CARD_Y], 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, CARD_STRUCT_SIZE - add eax, deck_data - mov dx, [eax+CARD_X] - mov [eax+CARD_OLD_X], dx - mov dx, [eax+CARD_Y] - mov [eax+CARD_OLD_Y], dx - inc ecx - jmp .save -.fin: - popad - ret - -check_stack_move: - pushad - mov esi, [active_stack] - imul esi, CARD_STRUCT_SIZE - add esi, deck_data - cmp dword [active_card_count], 1 - jne .tableau_check - - mov ebx, FOUNDATION_X - xor ecx, ecx -.f_lp: - movsx eax, word [esi+CARD_X] - sub eax, ebx - add eax, 25 - cmp eax, 50 - ja .next_f - movsx eax, word [esi+CARD_Y] - sub eax, FOUND_Y - add eax, 30 - cmp eax, 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, CARD_STRUCT_SIZE - add edi, deck_data - push ecx - call is_card_active - pop ecx - jc .sk_l - cmp word [edi+CARD_X], bx - jne .sk_l - movzx eax, word [edi+CARD_Y] - 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, CARD_STRUCT_SIZE - add edi, deck_data - movsx eax, word [esi+CARD_X] - movsx edx, word [edi+CARD_X] - sub eax, edx - add eax, 25 - cmp eax, 50 - ja .nx_col - movsx eax, word [esi+CARD_Y] - movsx edx, word [edi+CARD_Y] - sub eax, edx - add eax, 30 - cmp eax, 60 - ja .nx_col - - mov al, [esi+CARD_SUIT] - mov dl, [edi+CARD_SUIT] - shr al, 1 - shr dl, 1 - cmp al, dl - je .nx_col - mov al, [esi+CARD_VALUE] - mov dl, [edi+CARD_VALUE] - inc al - cmp al, dl - jne .nx_col - mov dx, word [edi+CARD_Y] - add dx, STACK_OFFSET - jmp .apply_move - -.empty_col: - movsx eax, word [esi+CARD_X] - sub eax, ebx - add eax, 25 - cmp eax, 50 - ja .nx_col - movsx eax, word [esi+CARD_Y] - sub eax, 120 - add eax, 30 - cmp eax, 60 - ja .nx_col - cmp byte [esi+CARD_VALUE], 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, CARD_STRUCT_SIZE - add eax, deck_data - mov dx, [eax+CARD_OLD_X] - mov [eax+CARD_X], dx - mov dx, [eax+CARD_OLD_Y] - mov [eax+CARD_Y], dx - inc ecx - jmp .back -.out: - popad - ret - -.found_match: - add dword [score], 10 - mov word [esi+CARD_X], bx - mov word [esi+CARD_Y], FOUND_Y - mov byte [esi+CARD_LOC], 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, CARD_STRUCT_SIZE - add eax, deck_data - mov word [eax+CARD_X], bx - mov dx, word [temp_counter2] - mov word [eax+CARD_Y], dx - mov dl, byte [temp_val] - mov byte [eax+CARD_LOC], 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 -.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, CARD_STRUCT_SIZE - add edi, deck_data - cmp word [edi+CARD_X], bx - jne .nx_c - cmp word [edi+CARD_Y], FOUND_Y - jne .nx_c - movzx edx, byte [edi+CARD_VALUE] - 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+CARD_VALUE] - mov dl, [esi+CARD_SUIT] - 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+CARD_SUIT] - jne .invalid - mov dl, [edi+CARD_VALUE] - 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, CARD_STRUCT_SIZE - add esi, deck_data - cmp byte [esi+CARD_LOC], 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, CARD_STRUCT_SIZE - add edi, deck_data - cmp word [edi+CARD_X], bx - jne .next_card - movzx eax, word [edi+CARD_Y] - 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+CARD_STATE], 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, CARD_STRUCT_SIZE - add esi, deck_data - mov edi, temp_card_buf - mov ecx, 3 - rep movsd - - mov eax, [temp_active] - inc eax - imul esi, eax, CARD_STRUCT_SIZE - add esi, deck_data - imul edi, [temp_active], CARD_STRUCT_SIZE - 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 * CARD_STRUCT_SIZE) - mov ecx, 3 - rep movsd -.done: ret - -deal_from_stock: - pushad - mov ecx, 51 -.f: - imul esi, ecx, CARD_STRUCT_SIZE - add esi, deck_data - cmp byte [esi+CARD_LOC], 7 - jne .n - cmp byte [esi+CARD_STATE], 0 - je .o -.n: dec ecx - jns .f - call reset_stock - popad - ret -.o: - mov byte [esi+CARD_STATE], 1 - mov byte [esi+CARD_LOC], 9 - mov word [esi+CARD_X], WASTE_X - mov word [esi+CARD_Y], 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, CARD_STRUCT_SIZE - add esi, deck_data - cmp byte [esi+CARD_LOC], 9 - jne .s - mov byte [esi+CARD_STATE], 0 - mov byte [esi+CARD_LOC], 7 - mov word [esi+CARD_X], STOCK_X - mov word [esi+CARD_Y], 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 byte [edi+CARD_VALUE], bl - mov byte [edi+CARD_SUIT], al - mov byte [edi+CARD_STATE], 0 - mov byte [edi+CARD_LOC], 7 - add edi, CARD_STRUCT_SIZE - cmp ebx, 13 - jne .r - inc eax - cmp eax, 4 - jne .s - ret - -shuffle_deck: - mov dword [temp_counter2], 51 -.sh: - mcall SYS_RANDOM - and eax, 0xFFFF - xor edx, edx - mov ebx, [temp_counter2] - inc ebx - div ebx - imul esi, [temp_counter2], CARD_STRUCT_SIZE - add esi, deck_data - imul edi, edx, CARD_STRUCT_SIZE - 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 word [edi+CARD_X], bx - mov word [edi+CARD_Y], cx - mov byte [edi+CARD_LOC], dl - dec ebp - jnz .h - mov byte [edi+CARD_STATE], 1 - jmp .nx -.h: - mov byte [edi+CARD_STATE], 0 -.nx: - add edi, CARD_STRUCT_SIZE - 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 * CARD_STRUCT_SIZE) - jae .fin - mov word [edi+CARD_X], STOCK_X - mov word [edi+CARD_Y], FOUND_Y - mov byte [edi+CARD_LOC], 7 - mov byte [edi+CARD_STATE], 0 - add edi, CARD_STRUCT_SIZE - jmp .sf -.fin: ret - -; --- DATA --- -title db 'Solitare V1.2 Final', 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 -db 11110000b,00001000b,00010000b,00100000b,01000000b,10000000b,11111000b -db 11110000b,00001000b,00001000b,01110000b,00001000b,00001000b,11110000b -db 10001000b,10001000b,10001000b,11111000b,00001000b,00001000b,00001000b -db 11111000b,10000000b,10000000b,11110000b,00001000b,00001000b,11111000b -db 01110000b,10000000b,10000000b,11110000b,10001000b,10001000b,01110000b -db 11111000b,00001000b,00010000b,00100000b,01000000b,01000000b,01000000b -db 01110000b,10001000b,10001000b,01110000b,10001000b,10001000b,01110000b -db 01110000b,10001000b,10001000b,01111000b,00001000b,00001000b,01110000b -db 10111000b,10101000b,10101000b,10101000b,10101000b,10101000b,10111000b -db 00011000b,00001000b,00001000b,00001000b,00001000b,10001000b,01110000b -db 01110000b,10001000b,10001000b,10001000b,10101000b,10010000b,01101000b -db 10001000b,10010000b,10100000b,11000000b,10100000b,10010000b,10001000b -db 01010000b,11111000b,11111000b,01110000b,00100000b,00000000b,00000000b -db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,00000000b -db 00100000b,00100000b,11111000b,11111000b,00100000b,00100000b,01110000b -db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,01110000b -db 01111000b,10000000b,01110000b,00001000b,00001000b,11110000b,00000000b -db 01110000b,10001000b,10000000b,10000000b,10000000b,10001000b,01110000b -db 01110000b,10001000b,10001000b,10001000b,10001000b,10001000b,01110000b -db 11111000b,10001000b,10001000b,11111000b,10100000b,10010000b,10001000b -db 01111000b,10000000b,10000000b,11110000b,10000000b,10000000b,11111000b -db 00000000b,00000000b,00000000b,11111000b,00000000b,00000000b,00000000b -db 01110000b,10001000b,10001000b,10001000b,10001000b,10001000b,01110000b -db 00100000b,01100000b,00100000b,00100000b,00100000b,00100000b,01110000b -db 01110000b,10001000b,00001000b,01110000b,10000000b,10000000b,11111000b -db 11111000b,00001000b,00010000b,00110000b,00001000b,10001000b,01110000b -db 00010000b,00110000b,01010000b,10010000b,11111000b,00010000b,00010000b -db 11111000b,10000000b,11110000b,00001000b,00001000b,10001000b,01110000b -db 01110000b,10000000b,11110000b,10001000b,10001000b,10001000b,01110000b -db 11111000b,00001000b,00010000b,00100000b,01000000b,01000000b,01000000b -db 01110000b,10001000b,10001000b,01110000b,10001000b,10001000b,01110000b -db 01110000b,10001000b,10001000b,01111000b,00001000b,00001000b,01110000b - -align 4 -deck_data: rb 52 * CARD_STRUCT_SIZE -i_end: - -align 4096 -screen_buffer: rb WIN_W * WIN_H * 3 + 32768 -stack_bottom: rb 8192 -stacktop: -mem_end: -- 2.49.1 From dd15125384d87cd8f224a95b11e8fc928e314985 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 2 Mar 2026 19:06:54 +0000 Subject: [PATCH 14/19] Upload files to "programs/games/solitare" V1.5 windows mode --- programs/games/solitare/solitare.asm | 1233 ++++++++++++++++++++++++++ 1 file changed, 1233 insertions(+) create mode 100644 programs/games/solitare/solitare.asm diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm new file mode 100644 index 000000000..4f6d3e8c1 --- /dev/null +++ b/programs/games/solitare/solitare.asm @@ -0,0 +1,1233 @@ +; Solitaire V1.5 - Window Alignment Edition +; Platform: MenuetOS / KolibriOS +; Author: Max + +format binary as 'run' +use32 +org 0x0 + +; --- SYSTEM INCLUDES --- +include 'macros.inc' + +; --- CONSTANTS --- +SYS_REDRAW equ 12 +SYS_KEY equ 2 +SYS_BUTTON equ 17 +SYS_MOUSE_POS equ 37 +SYS_DRAW_WINDOW equ 0 +SYS_EXIT equ -1 +SYS_BLIT equ 7 +SYS_RANDOM equ 3 +SYS_DELAY equ 5 +SYS_GET_SKIN_H equ 48 + +CARD_W equ 50 +CARD_H equ 70 +STACK_OFFSET equ 20 +WIN_W equ 750 +WIN_H equ 560 +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 + +; Card structure offsets +CARD_STRUCT_SIZE equ 12 +CARD_VALUE equ 0 +CARD_SUIT equ 1 +CARD_STATE equ 2 +CARD_LOC equ 3 +CARD_X equ 4 +CARD_Y equ 6 +CARD_OLD_X equ 8 +CARD_OLD_Y equ 10 + +STOCK_X equ 20 +WASTE_X equ 80 +FOUNDATION_X equ 350 +FOUND_Y equ 20 +SCORE_Y equ 535 + +; --- HEADER --- +db 'MENUET01' +dd 0x01 +dd start +dd i_end +dd mem_end +dd stacktop +dd 0, 0 + +start: + mov esp, stacktop + mcall SYS_GET_SKIN_H, 4 + mov [skin_h], eax + + call init_deck + call shuffle_deck + call layout_tableau + mov dword [score], 0 + mov byte [game_won], 0 + +event_loop: + mcall 11 + cmp eax, 1 + je on_redraw + cmp eax, 2 + je on_key + cmp eax, 3 + je on_button + + call handle_mouse + + ; Redraw only if there's an active card movement or forced update + cmp dword [active_card_count], 0 + ja update_screen_only + cmp byte [force_redraw], 1 + je update_screen_only + + mcall SYS_DELAY, 1 + jmp event_loop + +on_key: + mcall SYS_KEY + jmp event_loop + +on_button: + mcall SYS_BUTTON + shr eax, 8 + cmp eax, 1 ; Close button (ID 1) + jne event_loop + mcall SYS_EXIT + +on_redraw: + mcall SYS_REDRAW, 1 + + ; EBX: [X start : Window Width] + mov ebx, 100 shl 16 + (WIN_W + 9) + + ; ECX: [Y start : Window Height + skin + border] + mov eax, [skin_h] + add eax, WIN_H + 5 + mov ecx, 100 shl 16 + mov cx, ax + + ; Draw window with skin flag (0x14) + mcall SYS_DRAW_WINDOW, , , 0x14000000 or COL_TABLE, , title + + mcall SYS_REDRAW, 2 + mov byte [force_redraw], 1 + jmp update_screen_only + +update_screen_only: + mov byte [force_redraw], 0 + call prepare_buffer + + ; EDX: [x_dest:16|y_dest:16] - Offset by border and skin height + mov edx, 4 shl 16 + add dx, word [skin_h] + + mcall SYS_BLIT, screen_buffer, WIN_W shl 16 + WIN_H, edx + jmp event_loop + +; --- MOUSE HANDLING --- + +handle_mouse: + pushad + mcall SYS_MOUSE_POS, 1 + mov ebp, eax + shr ebp, 16 + sub ebp, 5 ; Mouse X correction relative to frame + + and eax, 0xFFFF + sub eax, [skin_h] + mov edi, eax ; EDI = Mouse Y inside workspace + + mcall SYS_MOUSE_POS, 2 + test eax, 1 ; Check left button + jnz .dragging_state + + cmp dword [mouse_lock], 1 + jne .exit + + mov dword [mouse_lock], 0 + cmp dword [active_card_count], 0 + je .exit + + call check_stack_move + mov dword [active_card_count], 0 + mov byte [force_redraw], 1 + popad + ret + +.dragging_state: + cmp dword [mouse_lock], 1 + je .no_deal_click + + ; Check if clicking on the stock pile + cmp ebp, STOCK_X + jb .find_card + cmp ebp, STOCK_X+CARD_W + jae .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 + mov byte [force_redraw], 1 + popad + ret + +.find_card: + mov ebx, 51 ; Check cards from top to bottom +.f_loop: + imul edx, ebx, CARD_STRUCT_SIZE + add edx, deck_data + movsx esi, word [edx+CARD_X] + movsx ecx, word [edx+CARD_Y] + + ; Bounds checking for the card + 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 + + ; Only pick up face-up cards + cmp byte [edx+CARD_STATE], 1 + jne .next_s + + mov dword [mouse_lock], 1 + mov [active_stack], ebx + mov dword [active_card_count], 1 + + ; Calculate mouse offset within card + mov ax, word [edx+CARD_X] + sub ax, bp + mov [mouse_off_x], ax + mov ax, word [edx+CARD_Y] + sub ax, di + mov [mouse_off_y], ax + + mov eax, ebx + call build_active_stack + popad + ret +.next_s: + dec ebx + jns .f_loop + popad + ret + +.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, CARD_STRUCT_SIZE + add eax, deck_data + + ; Move active card stack with the mouse + mov dx, [mouse_off_x] + add dx, bp + mov [eax+CARD_X], 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+CARD_Y], dx + + inc ecx + jmp .d_lp +.exit_drag: + popad + ret +.exit: + popad + ret + +; --- RENDERING --- + +prepare_buffer: + ; Clear buffer with table color + mov edi, screen_buffer + mov ecx, WIN_W * WIN_H + mov eax, COL_TABLE +.clear_loop: + mov [edi], al + mov [edi+1], ah + push eax + shr eax, 16 + mov byte [edi+2], al + pop eax + add edi, 3 + dec ecx + jnz .clear_loop + + call draw_slots + call render_score_ui + + ; Draw static cards + xor ecx, ecx +.draw_loop: + call is_card_active + jc .skip + push ecx + imul esi, ecx, CARD_STRUCT_SIZE + add esi, deck_data + call draw_card_to_buffer + pop ecx +.skip: + inc ecx + cmp ecx, 52 + jl .draw_loop + + ; Draw active (dragged) cards on top + xor ecx, ecx +.draw_active: + cmp ecx, [active_card_count] + jae .done_rendering + push ecx + mov eax, [active_stack + ecx*4] + imul esi, eax, CARD_STRUCT_SIZE + add esi, deck_data + call draw_card_to_buffer + pop ecx + inc ecx + jmp .draw_active + +.done_rendering: + ret + +draw_card_to_buffer: + pushad + movsx ebx, word [esi+CARD_X] + movsx ecx, word [esi+CARD_Y] + + ; Shadow/Outline + mov edx, COL_BLACK + mov edi, CARD_W + mov ebp, CARD_H + call fill_rect_buf + + ; Face + 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+CARD_STATE], 1 + je .face_up + + ; Back of the card + 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: + ; Suit color determination + mov edx, COL_RED + cmp byte [esi+CARD_SUIT], 2 + jb .is_red + mov edx, COL_BLACK +.is_red: + ; Top left symbol + push edx + push esi + movzx eax, byte [esi+CARD_VALUE] + dec eax + mov esi, eax + add ebx, 3 + add ecx, 3 + call draw_char_to_buf + pop esi + push esi + movzx eax, byte [esi+CARD_SUIT] + add eax, 13 + add ebx, 6 + mov esi, eax + call draw_char_to_buf + pop esi + pop edx + + ; Bottom right symbol (inverted position) + push edx + push esi + movsx ebx, word [esi+CARD_X] + add ebx, CARD_W - 8 + movsx ecx, word [esi+CARD_Y] + add ecx, CARD_H - 10 + movzx eax, byte [esi+CARD_VALUE] + dec eax + mov esi, eax + call draw_char_to_buf + pop esi + push esi + movzx eax, byte [esi+CARD_SUIT] + add eax, 13 + sub ebx, 6 + mov esi, eax + call draw_char_to_buf + pop esi + pop edx + popad + ret + +fill_rect_buf: + pushad + mov esi, ebp +.yl: + cmp ecx, 0 + jl .skip_line + cmp ecx, WIN_H + jge .skip_line + push ecx + push ebx + mov eax, ecx + imul eax, STRIDE + add eax, screen_buffer + mov dword [temp_counter], edi +.xl: + cmp ebx, 0 + jl .skip_pixel + cmp ebx, WIN_W + jge .skip_pixel + push eax + mov ecx, ebx + imul ecx, 3 + add eax, ecx + mov [eax], dl + mov [eax+1], dh + push edx + shr edx, 16 + mov [eax+2], dl + pop edx + pop eax +.skip_pixel: + inc ebx + dec dword [temp_counter] + jnz .xl + pop ebx + pop ecx +.skip_line: + inc ecx + dec esi + jnz .yl + popad + ret + +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 + cmp ebx, 0 + jl .skip_pixel + cmp ebx, WIN_W + jge .skip_pixel + cmp ecx, 0 + jl .skip_pixel + cmp ecx, WIN_H + jge .skip_pixel + push eax + mov eax, ecx + imul eax, STRIDE + push ebx + imul ebx, 3 + add eax, ebx + pop ebx + 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_large_char_to_buf: + pushad + imul esi, 12 + add esi, font_8x12 + mov ebp, 12 +.y_loop: + push ebx + push ecx + mov al, [esi] + mov ah, 10000000b + mov dword [temp_counter], 8 +.x_loop: + test al, ah + jz .skip_pixel + cmp ebx, 0 + jl .skip_pixel + cmp ebx, WIN_W + jge .skip_pixel + cmp ecx, 0 + jl .skip_pixel + cmp ecx, WIN_H + jge .skip_pixel + push eax + mov eax, ecx + imul eax, STRIDE + push ebx + imul ebx, 3 + add eax, ebx + pop ebx + 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 + +render_score_ui: + mov edx, COL_BLACK + mov ebx, 530 + mov ecx, SCORE_Y + xor esi, esi ; Print "SCORE" + call draw_large_char_to_buf + add ebx, 10 + mov esi, 1 + call draw_large_char_to_buf + add ebx, 10 + mov esi, 2 + call draw_large_char_to_buf + add ebx, 10 + mov esi, 3 + call draw_large_char_to_buf + add ebx, 10 + mov esi, 4 + call draw_large_char_to_buf + add ebx, 20 + + ; Handle score value display + mov eax, [score] + test eax, eax + jns .pos + neg eax + push eax + mov ecx, SCORE_Y + mov esi, 5 ; Minus sign + call draw_large_char_to_buf + add ebx, 10 + 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, 6 ; Map digit to font index + push ecx + mov ecx, SCORE_Y + mov esi, edx + mov edx, COL_BLACK + call draw_large_char_to_buf + add ebx, 10 + pop ecx + loop .print_dec + ret + +draw_slots: + pushad + ; Draw foundation slots + 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 + + ; Draw tableau slots + mov ebx, 40 + mov ecx, 110 + 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 + +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 + +build_active_stack: + pushad + imul esi, eax, CARD_STRUCT_SIZE + add esi, deck_data + mov bx, [esi+CARD_X] + mov dx, [esi+CARD_Y] + movzx ebp, dx + add ebp, STACK_OFFSET +.y_search: + xor ecx, ecx +.l: + imul edi, ecx, CARD_STRUCT_SIZE + add edi, deck_data + cmp word [edi+CARD_X], bx + jne .nx + cmp word [edi+CARD_Y], 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, CARD_STRUCT_SIZE + add eax, deck_data + mov dx, [eax+CARD_X] + mov [eax+CARD_OLD_X], dx + mov dx, [eax+CARD_Y] + mov [eax+CARD_OLD_Y], dx + inc ecx + jmp .save +.fin: + popad + ret + +check_stack_move: + pushad + mov esi, [active_stack] + imul esi, CARD_STRUCT_SIZE + add esi, deck_data + + ; Logic for single card foundation drop + cmp dword [active_card_count], 1 + jne .tableau_check + mov ebx, FOUNDATION_X + xor ecx, ecx +.f_lp: + movsx eax, word [esi+CARD_X] + sub eax, ebx + add eax, 25 + cmp eax, 50 + ja .next_f + movsx eax, word [esi+CARD_Y] + sub eax, FOUND_Y + add eax, 30 + cmp eax, 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, 40 +.col_lp: + xor ecx, ecx + mov dword [temp_val], -1 + mov dword [temp_counter], 0 +.find_l: + imul edi, ecx, CARD_STRUCT_SIZE + add edi, deck_data + push ecx + call is_card_active + pop ecx + jc .sk_l + cmp word [edi+CARD_X], bx + jne .sk_l + movzx eax, word [edi+CARD_Y] + 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 + + ; Check drop on another card + mov ecx, [temp_val] + imul edi, ecx, CARD_STRUCT_SIZE + add edi, deck_data + movsx eax, word [esi+CARD_X] + movsx edx, word [edi+CARD_X] + sub eax, edx + add eax, 25 + cmp eax, 50 + ja .nx_col + movsx eax, word [esi+CARD_Y] + movsx edx, word [edi+CARD_Y] + sub eax, edx + add eax, 30 + cmp eax, 60 + ja .nx_col + + ; Rules check: Opposite color and sequence (Value + 1) + mov al, [esi+CARD_SUIT] + mov dl, [edi+CARD_SUIT] + shr al, 1 + shr dl, 1 + cmp al, dl + je .nx_col + mov al, [esi+CARD_VALUE] + mov dl, [edi+CARD_VALUE] + inc al + cmp al, dl + jne .nx_col + mov dx, word [edi+CARD_Y] + add dx, STACK_OFFSET + jmp .apply_move + +.empty_col: + ; Check drop on empty column (only Kings) + movsx eax, word [esi+CARD_X] + sub eax, ebx + add eax, 25 + cmp eax, 50 + ja .nx_col + movsx eax, word [esi+CARD_Y] + sub eax, 110 + add eax, 30 + cmp eax, 60 + ja .nx_col + cmp byte [esi+CARD_VALUE], 13 + jne .nx_col + mov dx, 110 + jmp .apply_move + +.nx_col: + add ebx, 100 + cmp ebx, 740 + jl .col_lp + + ; No valid move found, snap back to original position + xor ecx, ecx +.back: + cmp ecx, [active_card_count] + jae .out + mov eax, [active_stack + ecx*4] + imul eax, CARD_STRUCT_SIZE + add eax, deck_data + mov dx, [eax+CARD_OLD_X] + mov [eax+CARD_X], dx + mov dx, [eax+CARD_OLD_Y] + mov [eax+CARD_Y], dx + inc ecx + jmp .back +.out: + popad + ret + +.found_match: + add dword [score], 10 + mov word [esi+CARD_X], bx + mov word [esi+CARD_Y], FOUND_Y + mov byte [esi+CARD_LOC], 8 ; Set location to foundation + 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, 40 + 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, CARD_STRUCT_SIZE + add eax, deck_data + mov word [eax+CARD_X], bx + mov dx, word [temp_counter2] + mov word [eax+CARD_Y], dx + mov dl, byte [temp_val] + mov byte [eax+CARD_LOC], 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 +.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, CARD_STRUCT_SIZE + add edi, deck_data + cmp word [edi+CARD_X], bx + jne .nx_c + cmp word [edi+CARD_Y], FOUND_Y + jne .nx_c + movzx edx, byte [edi+CARD_VALUE] + 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+CARD_VALUE] + mov dl, [esi+CARD_SUIT] + cmp dword [temp_counter], -1 + jne .not_empty + + ; Empty foundation slot only accepts Aces (Value 1) + cmp al, 1 + je .valid + jmp .invalid +.not_empty: + mov edi, [temp_counter] + imul edi, 12 + add edi, deck_data + cmp dl, [edi+CARD_SUIT] + jne .invalid + mov dl, [edi+CARD_VALUE] + 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, CARD_STRUCT_SIZE + add esi, deck_data + cmp byte [esi+CARD_LOC], 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, 40 +.col_loop: + xor esi, esi + mov dword [temp_val], -1 + xor ecx, ecx +.find_lowest: + imul edi, ecx, CARD_STRUCT_SIZE + add edi, deck_data + cmp word [edi+CARD_X], bx + jne .next_card + movzx eax, word [edi+CARD_Y] + 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+CARD_STATE], 1 ; Flip the bottom card of the stack face up +.next_col: + add ebx, 100 + cmp ebx, 740 + jl .col_loop + popad + ret + +move_single_to_top: + ; Moves a card to the end of the deck_data array so it's drawn last (on top) + mov eax, [temp_active] + cmp eax, 51 + je .done + imul esi, eax, CARD_STRUCT_SIZE + add esi, deck_data + mov edi, temp_card_buf + mov ecx, 3 + cld + rep movsd + mov eax, [temp_active] + inc eax + imul esi, eax, CARD_STRUCT_SIZE + add esi, deck_data + imul edi, [temp_active], CARD_STRUCT_SIZE + 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 * CARD_STRUCT_SIZE) + mov ecx, 3 + rep movsd +.done: ret + +deal_from_stock: + pushad + mov ecx, 51 +.f: + imul esi, ecx, CARD_STRUCT_SIZE + add esi, deck_data + cmp byte [esi+CARD_LOC], 7 + jne .n + cmp byte [esi+CARD_STATE], 0 + je .o +.n: dec ecx + jns .f + call reset_stock + popad + ret +.o: + mov byte [esi+CARD_STATE], 1 + mov byte [esi+CARD_LOC], 9 ; Move to waste + mov word [esi+CARD_X], WASTE_X + mov word [esi+CARD_Y], 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, CARD_STRUCT_SIZE + add esi, deck_data + cmp byte [esi+CARD_LOC], 9 + jne .s + mov byte [esi+CARD_STATE], 0 + mov byte [esi+CARD_LOC], 7 + mov word [esi+CARD_X], STOCK_X + mov word [esi+CARD_Y], 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 byte [edi+CARD_VALUE], bl + mov byte [edi+CARD_SUIT], al + mov byte [edi+CARD_STATE], 0 + mov byte [edi+CARD_LOC], 7 + add edi, CARD_STRUCT_SIZE + cmp ebx, 13 + jne .r + inc eax + cmp eax, 4 + jne .s + ret + +shuffle_deck: + mov dword [temp_counter2], 51 +.sh: + mcall SYS_RANDOM + and eax, 0xFFFF + xor edx, edx + mov ebx, [temp_counter2] + inc ebx + div ebx + imul esi, [temp_counter2], CARD_STRUCT_SIZE + add esi, deck_data + imul edi, edx, CARD_STRUCT_SIZE + 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, 40 + xor edx, edx +.cols: + mov ecx, 110 + mov eax, edx + inc eax + mov ebp, eax +.cards: + mov word [edi+CARD_X], bx + mov word [edi+CARD_Y], cx + mov byte [edi+CARD_LOC], dl + dec ebp + jnz .h + mov byte [edi+CARD_STATE], 1 + jmp .nx +.h: + mov byte [edi+CARD_STATE], 0 +.nx: + add edi, CARD_STRUCT_SIZE + 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 * CARD_STRUCT_SIZE) + jae .fin + mov word [edi+CARD_X], STOCK_X + mov word [edi+CARD_Y], FOUND_Y + mov byte [edi+CARD_LOC], 7 + mov byte [edi+CARD_STATE], 0 + add edi, CARD_STRUCT_SIZE + jmp .sf +.fin: ret + +; --- DATA & FONTS --- +title db 'Solitaire V1.5', 0 +score dd 0 +game_won db 0 +mouse_lock dd 0 +force_redraw db 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 +skin_h dd 0 + +font_8x12: +; Definitions for S, C, O, R, E, -, and digits 0-9 +db 01111100b,10000010b,10000000b,10000000b,01111100b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; S +db 01111100b,10000010b,10000000b,10000000b,10000000b,10000000b,10000000b,10000010b,01111100b,00000000b,00000000b,00000000b ; C +db 01111100b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; O +db 11111100b,10000010b,10000010b,10000010b,11111100b,10010000b,10001000b,10000100b,10000010b,00000000b,00000000b,00000000b ; R +db 11111110b,10000000b,10000000b,10000000b,11111100b,10000000b,10000000b,10000000b,11111110b,00000000b,00000000b,00000000b ; E +db 00000000b,00000000b,00000000b,00000000b,11111111b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b ; - +db 00111100b,01000010b,10000001b,10000001b,10000001b,10000001b,10000001b,01000010b,00111100b,00000000b,00000000b,00000000b ; 0 +db 00011000b,00111000b,00001000b,00001000b,00001000b,00001000b,00001000b,00001000b,00111100b,00000000b,00000000b,00000000b ; 1 +db 01111100b,10000010b,00000010b,00000010b,01111100b,10000000b,10000000b,10000000b,11111110b,00000000b,00000000b,00000000b ; 2 +db 01111100b,10000010b,00000010b,00000010b,00111100b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 3 +db 00001000b,00011000b,00101000b,01001000b,10001000b,11111111b,00001000b,00001000b,00001000b,00000000b,00000000b,00000000b ; 4 +db 11111110b,10000000b,10000000b,11111100b,00000010b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 5 +db 01111100b,10000010b,10000000b,11111100b,10000010b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 6 +db 11111110b,00000010b,00000100b,00001000b,00010000b,00100000b,00100000b,00100000b,00100000b,00000000b,00000000b,00000000b ; 7 +db 01111100b,10000010b,10000010b,10000010b,01111100b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 8 +db 01111100b,10000010b,10000010b,10000010b,10000010b,01111110b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 9 + +font_5x7: +; Definitions for A, 2-10, J, Q, K, and Suits +db 01110000b,10001000b,10001000b,11111000b,10001000b,10001000b,10001000b ; A +db 11110000b,00001000b,00010000b,00100000b,01000000b,10000000b,11111000b ; 2 +db 11110000b,00001000b,00001000b,01110000b,00001000b,00001000b,11110000b ; 3 +db 10001000b,10001000b,10001000b,11111000b,00001000b,00001000b,00001000b ; 4 +db 11111000b,10000000b,10000000b,11110000b,00001000b,00001000b,11111000b ; 5 +db 01110000b,10000000b,10000000b,11110000b,10001000b,10001000b,01110000b ; 6 +db 11111000b,00001000b,00010000b,00100000b,01000000b,01000000b,01000000b ; 7 +db 01110000b,10001000b,10001000b,01110000b,10001000b,10001000b,01110000b ; 8 +db 01110000b,10001000b,10001000b,01111000b,00001000b,00001000b,01110000b ; 9 +db 10111000b,10101000b,10101000b,10101000b,10101000b,10101000b,10111000b ; 10 +db 00011000b,00001000b,00001000b,00001000b,00001000b,10001000b,01110000b ; J +db 01110000b,10001000b,10001000b,10001000b,10101000b,10010000b,01101000b ; Q +db 10001000b,10010000b,10100000b,11000000b,10100000b,10010000b,10001000b ; K +db 01010000b,11111000b,11111000b,01110000b,00100000b,00000000b,00000000b ; Hearts +db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,00000000b ; Diamonds +db 00100000b,00100000b,11111000b,11111000b,00100000b,00100000b,01110000b ; Clubs +db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,01110000b ; Spades + +align 4 +deck_data: rb 52 * CARD_STRUCT_SIZE +i_end: + +align 4096 +screen_buffer: rb WIN_W * WIN_H * 3 + 32768 +stack_bottom: rb 8192 +stacktop: +mem_end: -- 2.49.1 From 836735d28c8f6f82f3306d0b7e0428220eb36283 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 2 Mar 2026 19:11:11 +0000 Subject: [PATCH 15/19] Update programs/games/solitare/solitare.asm --- programs/games/solitare/solitare.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm index 4f6d3e8c1..305cd3711 100644 --- a/programs/games/solitare/solitare.asm +++ b/programs/games/solitare/solitare.asm @@ -1,4 +1,4 @@ -; Solitaire V1.5 - Window Alignment Edition +; Solitaire V1.5 - Window Edition ; Platform: MenuetOS / KolibriOS ; Author: Max -- 2.49.1 From 0efc35f8b275dde5ea03eb355fc1db0faa6edd26 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 2 Mar 2026 22:02:21 +0000 Subject: [PATCH 16/19] Upload files to "programs/games/solitare" Add KOSfuncs.inc --- programs/games/solitare/solitare.asm | 207 ++++++++++----------------- 1 file changed, 77 insertions(+), 130 deletions(-) diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm index 305cd3711..f6b898858 100644 --- a/programs/games/solitare/solitare.asm +++ b/programs/games/solitare/solitare.asm @@ -1,5 +1,5 @@ -; Solitaire V1.5 - Window Edition -; Platform: MenuetOS / KolibriOS +; Solitare V1.5.1 - KOSfuncs Edition +; Platform: KolibriOS / MenuetOS ; Author: Max format binary as 'run' @@ -8,19 +8,9 @@ org 0x0 ; --- SYSTEM INCLUDES --- include 'macros.inc' +include 'KOSfuncs.inc' -; --- CONSTANTS --- -SYS_REDRAW equ 12 -SYS_KEY equ 2 -SYS_BUTTON equ 17 -SYS_MOUSE_POS equ 37 -SYS_DRAW_WINDOW equ 0 -SYS_EXIT equ -1 -SYS_BLIT equ 7 -SYS_RANDOM equ 3 -SYS_DELAY equ 5 -SYS_GET_SKIN_H equ 48 - +; --- GAME CONSTANTS --- CARD_W equ 50 CARD_H equ 70 STACK_OFFSET equ 20 @@ -51,7 +41,7 @@ STOCK_X equ 20 WASTE_X equ 80 FOUNDATION_X equ 350 FOUND_Y equ 20 -SCORE_Y equ 535 +SCORE_Y equ 535 ; --- HEADER --- db 'MENUET01' @@ -64,7 +54,9 @@ dd 0, 0 start: mov esp, stacktop - mcall SYS_GET_SKIN_H, 4 + + ; Get skin height using KOSfuncs constant + mcall SF_STYLE_SETTINGS, SSF_GET_SKIN_HEIGHT mov [skin_h], eax call init_deck @@ -74,90 +66,90 @@ start: mov byte [game_won], 0 event_loop: - mcall 11 - cmp eax, 1 + mcall SF_CHECK_EVENT + cmp eax, 1 ; Redraw je on_redraw - cmp eax, 2 + cmp eax, 2 ; Key je on_key - cmp eax, 3 + cmp eax, 3 ; Button je on_button - + call handle_mouse - - ; Redraw only if there's an active card movement or forced update + + ; Logic for active card movement or forced update cmp dword [active_card_count], 0 ja update_screen_only cmp byte [force_redraw], 1 je update_screen_only - - mcall SYS_DELAY, 1 + + mcall SF_SLEEP, 1 jmp event_loop on_key: - mcall SYS_KEY + mcall SF_GET_KEY jmp event_loop on_button: - mcall SYS_BUTTON + mcall SF_GET_BUTTON shr eax, 8 - cmp eax, 1 ; Close button (ID 1) + cmp eax, 1 ; Close button ID jne event_loop - mcall SYS_EXIT + mcall SF_TERMINATE_PROCESS on_redraw: - mcall SYS_REDRAW, 1 - - ; EBX: [X start : Window Width] + mcall SF_REDRAW, SSF_BEGIN_DRAW + + ; EBX: Window position and width mov ebx, 100 shl 16 + (WIN_W + 9) - - ; ECX: [Y start : Window Height + skin + border] + + ; ECX: Window position and height mov eax, [skin_h] add eax, WIN_H + 5 mov ecx, 100 shl 16 mov cx, ax - - ; Draw window with skin flag (0x14) - mcall SYS_DRAW_WINDOW, , , 0x14000000 or COL_TABLE, , title - - mcall SYS_REDRAW, 2 + + ; Draw window with skin flag + mcall SF_CREATE_WINDOW, , , 0x14000000 or COL_TABLE, , title + + mcall SF_REDRAW, SSF_END_DRAW mov byte [force_redraw], 1 jmp update_screen_only update_screen_only: mov byte [force_redraw], 0 call prepare_buffer - - ; EDX: [x_dest:16|y_dest:16] - Offset by border and skin height + + ; EDX: coordinates for blit mov edx, 4 shl 16 add dx, word [skin_h] - - mcall SYS_BLIT, screen_buffer, WIN_W shl 16 + WIN_H, edx + + mcall SF_PUT_IMAGE, screen_buffer, WIN_W shl 16 + WIN_H, edx jmp event_loop ; --- MOUSE HANDLING --- handle_mouse: pushad - mcall SYS_MOUSE_POS, 1 + mcall SF_MOUSE_GET, SSF_WINDOW_POSITION mov ebp, eax shr ebp, 16 - sub ebp, 5 ; Mouse X correction relative to frame - - and eax, 0xFFFF - sub eax, [skin_h] - mov edi, eax ; EDI = Mouse Y inside workspace + sub ebp, 5 ; X correction - mcall SYS_MOUSE_POS, 2 - test eax, 1 ; Check left button + and eax, 0xFFFF + sub eax, [skin_h] + mov edi, eax ; EDI = Mouse Y relative to workspace + + mcall SF_MOUSE_GET, SSF_BUTTON + test eax, 1 ; Check Left Button jnz .dragging_state - + cmp dword [mouse_lock], 1 - jne .exit - + jne .exit + mov dword [mouse_lock], 0 cmp dword [active_card_count], 0 je .exit - + call check_stack_move mov dword [active_card_count], 0 mov byte [force_redraw], 1 @@ -167,8 +159,8 @@ handle_mouse: .dragging_state: cmp dword [mouse_lock], 1 je .no_deal_click - - ; Check if clicking on the stock pile + + ; Stock pile click detection cmp ebp, STOCK_X jb .find_card cmp ebp, STOCK_X+CARD_W @@ -177,7 +169,7 @@ handle_mouse: jb .find_card cmp edi, FOUND_Y+CARD_H jae .find_card - + mov dword [mouse_lock], 1 call deal_from_stock mov byte [force_redraw], 1 @@ -185,14 +177,13 @@ handle_mouse: ret .find_card: - mov ebx, 51 ; Check cards from top to bottom + mov ebx, 51 .f_loop: imul edx, ebx, CARD_STRUCT_SIZE add edx, deck_data movsx esi, word [edx+CARD_X] movsx ecx, word [edx+CARD_Y] - - ; Bounds checking for the card + cmp ebp, esi jb .next_s add esi, CARD_W @@ -203,23 +194,21 @@ handle_mouse: add ecx, CARD_H cmp edi, ecx jae .next_s - - ; Only pick up face-up cards + cmp byte [edx+CARD_STATE], 1 jne .next_s - + mov dword [mouse_lock], 1 mov [active_stack], ebx mov dword [active_card_count], 1 - - ; Calculate mouse offset within card + mov ax, word [edx+CARD_X] sub ax, bp mov [mouse_off_x], ax mov ax, word [edx+CARD_Y] sub ax, di mov [mouse_off_y], ax - + mov eax, ebx call build_active_stack popad @@ -241,21 +230,20 @@ handle_mouse: mov eax, [active_stack + ecx*4] imul eax, CARD_STRUCT_SIZE add eax, deck_data - - ; Move active card stack with the mouse + mov dx, [mouse_off_x] add dx, bp mov [eax+CARD_X], 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+CARD_Y], dx - + inc ecx jmp .d_lp .exit_drag: @@ -268,7 +256,6 @@ handle_mouse: ; --- RENDERING --- prepare_buffer: - ; Clear buffer with table color mov edi, screen_buffer mov ecx, WIN_W * WIN_H mov eax, COL_TABLE @@ -286,7 +273,6 @@ prepare_buffer: call draw_slots call render_score_ui - ; Draw static cards xor ecx, ecx .draw_loop: call is_card_active @@ -301,7 +287,6 @@ prepare_buffer: cmp ecx, 52 jl .draw_loop - ; Draw active (dragged) cards on top xor ecx, ecx .draw_active: cmp ecx, [active_card_count] @@ -322,25 +307,18 @@ draw_card_to_buffer: pushad movsx ebx, word [esi+CARD_X] movsx ecx, word [esi+CARD_Y] - - ; Shadow/Outline mov edx, COL_BLACK mov edi, CARD_W mov ebp, CARD_H call fill_rect_buf - - ; Face 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+CARD_STATE], 1 je .face_up - - ; Back of the card add ebx, 4 add ecx, 4 mov edx, COL_REVERSE @@ -349,15 +327,12 @@ draw_card_to_buffer: call fill_rect_buf popad ret - .face_up: - ; Suit color determination mov edx, COL_RED cmp byte [esi+CARD_SUIT], 2 jb .is_red mov edx, COL_BLACK .is_red: - ; Top left symbol push edx push esi movzx eax, byte [esi+CARD_VALUE] @@ -365,18 +340,16 @@ draw_card_to_buffer: mov esi, eax add ebx, 3 add ecx, 3 - call draw_char_to_buf + call draw_char_to_buf pop esi push esi movzx eax, byte [esi+CARD_SUIT] - add eax, 13 + add eax, 13 add ebx, 6 mov esi, eax call draw_char_to_buf pop esi pop edx - - ; Bottom right symbol (inverted position) push edx push esi movsx ebx, word [esi+CARD_X] @@ -546,32 +519,30 @@ draw_large_char_to_buf: render_score_ui: mov edx, COL_BLACK - mov ebx, 530 + mov ebx, 530 mov ecx, SCORE_Y - xor esi, esi ; Print "SCORE" + xor esi, esi call draw_large_char_to_buf add ebx, 10 - mov esi, 1 + mov esi, 1 call draw_large_char_to_buf add ebx, 10 - mov esi, 2 + mov esi, 2 call draw_large_char_to_buf add ebx, 10 - mov esi, 3 + mov esi, 3 call draw_large_char_to_buf add ebx, 10 - mov esi, 4 + mov esi, 4 call draw_large_char_to_buf add ebx, 20 - - ; Handle score value display mov eax, [score] test eax, eax jns .pos neg eax push eax mov ecx, SCORE_Y - mov esi, 5 ; Minus sign + mov esi, 5 call draw_large_char_to_buf add ebx, 10 pop eax @@ -587,7 +558,7 @@ render_score_ui: jnz .dec_loop .print_dec: pop edx - add edx, 6 ; Map digit to font index + add edx, 6 push ecx mov ecx, SCORE_Y mov esi, edx @@ -600,7 +571,6 @@ render_score_ui: draw_slots: pushad - ; Draw foundation slots mov ebx, FOUNDATION_X mov ecx, FOUND_Y mov dword [temp_counter2], 4 @@ -612,8 +582,6 @@ draw_slots: add ebx, 60 dec dword [temp_counter2] jnz .f_loop - - ; Draw tableau slots mov ebx, 40 mov ecx, 110 mov dword [temp_counter2], 7 @@ -700,8 +668,6 @@ check_stack_move: mov esi, [active_stack] imul esi, CARD_STRUCT_SIZE add esi, deck_data - - ; Logic for single card foundation drop cmp dword [active_card_count], 1 jne .tableau_check mov ebx, FOUNDATION_X @@ -724,7 +690,6 @@ check_stack_move: inc ecx cmp ecx, 4 jl .f_lp - .tableau_check: mov ebx, 40 .col_lp: @@ -749,11 +714,8 @@ check_stack_move: inc ecx cmp ecx, 52 jl .find_l - cmp dword [temp_val], -1 je .empty_col - - ; Check drop on another card mov ecx, [temp_val] imul edi, ecx, CARD_STRUCT_SIZE add edi, deck_data @@ -769,8 +731,6 @@ check_stack_move: add eax, 30 cmp eax, 60 ja .nx_col - - ; Rules check: Opposite color and sequence (Value + 1) mov al, [esi+CARD_SUIT] mov dl, [edi+CARD_SUIT] shr al, 1 @@ -785,9 +745,7 @@ check_stack_move: mov dx, word [edi+CARD_Y] add dx, STACK_OFFSET jmp .apply_move - .empty_col: - ; Check drop on empty column (only Kings) movsx eax, word [esi+CARD_X] sub eax, ebx add eax, 25 @@ -802,13 +760,10 @@ check_stack_move: jne .nx_col mov dx, 110 jmp .apply_move - .nx_col: add ebx, 100 cmp ebx, 740 jl .col_lp - - ; No valid move found, snap back to original position xor ecx, ecx .back: cmp ecx, [active_card_count] @@ -825,12 +780,11 @@ check_stack_move: .out: popad ret - .found_match: add dword [score], 10 mov word [esi+CARD_X], bx mov word [esi+CARD_Y], FOUND_Y - mov byte [esi+CARD_LOC], 8 ; Set location to foundation + mov byte [esi+CARD_LOC], 8 pushad mov eax, [active_stack] mov [temp_active], eax @@ -840,7 +794,6 @@ check_stack_move: call check_win popad ret - .apply_move: xor ecx, ecx push eax @@ -927,14 +880,11 @@ check_foundation_logic: inc ebp cmp ebp, 52 jl .find_top - mov al, [esi+CARD_VALUE] mov dl, [esi+CARD_SUIT] cmp dword [temp_counter], -1 jne .not_empty - - ; Empty foundation slot only accepts Aces (Value 1) - cmp al, 1 + cmp al, 1 je .valid jmp .invalid .not_empty: @@ -1003,7 +953,7 @@ auto_reveal_all: jl .find_lowest cmp dword [temp_val], -1 je .next_col - mov byte [esi+CARD_STATE], 1 ; Flip the bottom card of the stack face up + mov byte [esi+CARD_STATE], 1 .next_col: add ebx, 100 cmp ebx, 740 @@ -1012,7 +962,6 @@ auto_reveal_all: ret move_single_to_top: - ; Moves a card to the end of the deck_data array so it's drawn last (on top) mov eax, [temp_active] cmp eax, 51 je .done @@ -1055,7 +1004,7 @@ deal_from_stock: ret .o: mov byte [esi+CARD_STATE], 1 - mov byte [esi+CARD_LOC], 9 ; Move to waste + mov byte [esi+CARD_LOC], 9 mov word [esi+CARD_X], WASTE_X mov word [esi+CARD_Y], FOUND_Y mov [temp_active], ecx @@ -1100,7 +1049,7 @@ init_deck: shuffle_deck: mov dword [temp_counter2], 51 .sh: - mcall SYS_RANDOM + mcall SF_GET_SYS_TIME and eax, 0xFFFF xor edx, edx mov ebx, [temp_counter2] @@ -1167,7 +1116,7 @@ layout_tableau: .fin: ret ; --- DATA & FONTS --- -title db 'Solitaire V1.5', 0 +title db 'Solitare V1.5.1', 0 score dd 0 game_won db 0 mouse_lock dd 0 @@ -1184,7 +1133,6 @@ active_stack rd 13 skin_h dd 0 font_8x12: -; Definitions for S, C, O, R, E, -, and digits 0-9 db 01111100b,10000010b,10000000b,10000000b,01111100b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; S db 01111100b,10000010b,10000000b,10000000b,10000000b,10000000b,10000000b,10000010b,01111100b,00000000b,00000000b,00000000b ; C db 01111100b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; O @@ -1192,10 +1140,10 @@ db 11111100b,10000010b,10000010b,10000010b,11111100b,10010000b,10001000b,1000010 db 11111110b,10000000b,10000000b,10000000b,11111100b,10000000b,10000000b,10000000b,11111110b,00000000b,00000000b,00000000b ; E db 00000000b,00000000b,00000000b,00000000b,11111111b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b ; - db 00111100b,01000010b,10000001b,10000001b,10000001b,10000001b,10000001b,01000010b,00111100b,00000000b,00000000b,00000000b ; 0 -db 00011000b,00111000b,00001000b,00001000b,00001000b,00001000b,00001000b,00001000b,00111100b,00000000b,00000000b,00000000b ; 1 +db 00011000b,00111000b,00001000b,00001000b,00001000b,00001000b,00001000b,00001000b,00111100b,00000000b,00000000b,00000000b ; 1 db 01111100b,10000010b,00000010b,00000010b,01111100b,10000000b,10000000b,10000000b,11111110b,00000000b,00000000b,00000000b ; 2 db 01111100b,10000010b,00000010b,00000010b,00111100b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 3 -db 00001000b,00011000b,00101000b,01001000b,10001000b,11111111b,00001000b,00001000b,00001000b,00000000b,00000000b,00000000b ; 4 +db 00001000b,00011000b,00101000b,01001000b,10001000b,11111111b,00001000b,00001000b,00001000b,00000000b,00000000b,00000000b ; 4 db 11111110b,10000000b,10000000b,11111100b,00000010b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 5 db 01111100b,10000010b,10000000b,11111100b,10000010b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 6 db 11111110b,00000010b,00000100b,00001000b,00010000b,00100000b,00100000b,00100000b,00100000b,00000000b,00000000b,00000000b ; 7 @@ -1203,7 +1151,6 @@ db 01111100b,10000010b,10000010b,10000010b,01111100b,10000010b,10000010b,1000001 db 01111100b,10000010b,10000010b,10000010b,10000010b,01111110b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 9 font_5x7: -; Definitions for A, 2-10, J, Q, K, and Suits db 01110000b,10001000b,10001000b,11111000b,10001000b,10001000b,10001000b ; A db 11110000b,00001000b,00010000b,00100000b,01000000b,10000000b,11111000b ; 2 db 11110000b,00001000b,00001000b,01110000b,00001000b,00001000b,11110000b ; 3 -- 2.49.1 From 5f4b2937671b08ecd62a509320aa0253a9eb9221 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 3 Mar 2026 11:28:08 +0000 Subject: [PATCH 17/19] Upload files to "programs/games/solitare" FIX adding score --- programs/games/solitare/solitare.asm | 84 ++++++++++++++-------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm index f6b898858..8da904563 100644 --- a/programs/games/solitare/solitare.asm +++ b/programs/games/solitare/solitare.asm @@ -1,6 +1,7 @@ -; Solitare V1.5.1 - KOSfuncs Edition +; Solitare V1.5.2 ; Platform: KolibriOS / MenuetOS -; Author: Max +; Author: Max (Refactored/Fixed) +; Scoring Fix: Cards only give points ONCE, even if moved back and forth. format binary as 'run' use32 @@ -30,8 +31,8 @@ COL_SLOT equ 0x185018 CARD_STRUCT_SIZE equ 12 CARD_VALUE equ 0 CARD_SUIT equ 1 -CARD_STATE equ 2 -CARD_LOC equ 3 +CARD_STATE equ 2 ; Bit 0: Face-up, Bit 7: Already Scored +CARD_LOC equ 3 ; 0-6: Tableau, 7: Stock, 8: Foundation, 9: Waste CARD_X equ 4 CARD_Y equ 6 CARD_OLD_X equ 8 @@ -55,7 +56,7 @@ dd 0, 0 start: mov esp, stacktop - ; Get skin height using KOSfuncs constant + ; Get system skin height mcall SF_STYLE_SETTINGS, SSF_GET_SKIN_HEIGHT mov [skin_h], eax @@ -67,16 +68,16 @@ start: event_loop: mcall SF_CHECK_EVENT - cmp eax, 1 ; Redraw + cmp eax, 1 ; Redraw event je on_redraw - cmp eax, 2 ; Key + cmp eax, 2 ; Key event je on_key - cmp eax, 3 ; Button + cmp eax, 3 ; Button event je on_button call handle_mouse - ; Logic for active card movement or forced update + ; Update display if dragging or forced cmp dword [active_card_count], 0 ja update_screen_only cmp byte [force_redraw], 1 @@ -92,25 +93,18 @@ on_key: on_button: mcall SF_GET_BUTTON shr eax, 8 - cmp eax, 1 ; Close button ID + cmp eax, 1 ; Window close button jne event_loop mcall SF_TERMINATE_PROCESS on_redraw: mcall SF_REDRAW, SSF_BEGIN_DRAW - - ; EBX: Window position and width mov ebx, 100 shl 16 + (WIN_W + 9) - - ; ECX: Window position and height mov eax, [skin_h] add eax, WIN_H + 5 mov ecx, 100 shl 16 mov cx, ax - - ; Draw window with skin flag mcall SF_CREATE_WINDOW, , , 0x14000000 or COL_TABLE, , title - mcall SF_REDRAW, SSF_END_DRAW mov byte [force_redraw], 1 jmp update_screen_only @@ -118,11 +112,8 @@ on_redraw: update_screen_only: mov byte [force_redraw], 0 call prepare_buffer - - ; EDX: coordinates for blit mov edx, 4 shl 16 add dx, word [skin_h] - mcall SF_PUT_IMAGE, screen_buffer, WIN_W shl 16 + WIN_H, edx jmp event_loop @@ -133,14 +124,14 @@ handle_mouse: mcall SF_MOUSE_GET, SSF_WINDOW_POSITION mov ebp, eax shr ebp, 16 - sub ebp, 5 ; X correction + sub ebp, 5 ; Mouse X correction and eax, 0xFFFF sub eax, [skin_h] - mov edi, eax ; EDI = Mouse Y relative to workspace + mov edi, eax ; Mouse Y in workspace mcall SF_MOUSE_GET, SSF_BUTTON - test eax, 1 ; Check Left Button + test eax, 1 ; Left click? jnz .dragging_state cmp dword [mouse_lock], 1 @@ -160,7 +151,7 @@ handle_mouse: cmp dword [mouse_lock], 1 je .no_deal_click - ; Stock pile click detection + ; Stock pile interaction cmp ebp, STOCK_X jb .find_card cmp ebp, STOCK_X+CARD_W @@ -195,8 +186,8 @@ handle_mouse: cmp edi, ecx jae .next_s - cmp byte [edx+CARD_STATE], 1 - jne .next_s + test byte [edx+CARD_STATE], 1 ; Is card face up? + jz .next_s mov dword [mouse_lock], 1 mov [active_stack], ebx @@ -317,8 +308,8 @@ draw_card_to_buffer: mov edi, CARD_W-2 mov ebp, CARD_H-2 call fill_rect_buf - cmp byte [esi+CARD_STATE], 1 - je .face_up + test byte [esi+CARD_STATE], 1 + jnz .face_up add ebx, 4 add ecx, 4 mov edx, COL_REVERSE @@ -781,7 +772,12 @@ check_stack_move: popad ret .found_match: + ; FIXED SCORING: Check Bit 7 of STATE (Scored flag) + test byte [esi+CARD_STATE], 0x80 + jnz .already_scored add dword [score], 10 + or byte [esi+CARD_STATE], 0x80 ; Set Scored Flag +.already_scored: mov word [esi+CARD_X], bx mov word [esi+CARD_Y], FOUND_Y mov byte [esi+CARD_LOC], 8 @@ -953,7 +949,7 @@ auto_reveal_all: jl .find_lowest cmp dword [temp_val], -1 je .next_col - mov byte [esi+CARD_STATE], 1 + or byte [esi+CARD_STATE], 1 ; Reveal face up .next_col: add ebx, 100 cmp ebx, 740 @@ -995,15 +991,10 @@ deal_from_stock: add esi, deck_data cmp byte [esi+CARD_LOC], 7 jne .n - cmp byte [esi+CARD_STATE], 0 - je .o -.n: dec ecx - jns .f - call reset_stock - popad - ret + test byte [esi+CARD_STATE], 1 ; Already visible? + jnz .n .o: - mov byte [esi+CARD_STATE], 1 + or byte [esi+CARD_STATE], 1 mov byte [esi+CARD_LOC], 9 mov word [esi+CARD_X], WASTE_X mov word [esi+CARD_Y], FOUND_Y @@ -1011,6 +1002,11 @@ deal_from_stock: call move_single_to_top popad ret +.n: dec ecx + jns .f + call reset_stock + popad + ret reset_stock: sub dword [score], 20 @@ -1020,7 +1016,7 @@ reset_stock: add esi, deck_data cmp byte [esi+CARD_LOC], 9 jne .s - mov byte [esi+CARD_STATE], 0 + and byte [esi+CARD_STATE], 0xFE ; Set face down mov byte [esi+CARD_LOC], 7 mov word [esi+CARD_X], STOCK_X mov word [esi+CARD_Y], FOUND_Y @@ -1036,7 +1032,7 @@ init_deck: .r: inc ebx mov byte [edi+CARD_VALUE], bl mov byte [edi+CARD_SUIT], al - mov byte [edi+CARD_STATE], 0 + mov byte [edi+CARD_STATE], 0 ; Face down, Not Scored mov byte [edi+CARD_LOC], 7 add edi, CARD_STRUCT_SIZE cmp ebx, 13 @@ -1087,10 +1083,10 @@ layout_tableau: mov byte [edi+CARD_LOC], dl dec ebp jnz .h - mov byte [edi+CARD_STATE], 1 + or byte [edi+CARD_STATE], 1 ; Top card face up jmp .nx .h: - mov byte [edi+CARD_STATE], 0 + and byte [edi+CARD_STATE], 0xFE ; Other cards face down .nx: add edi, CARD_STRUCT_SIZE add ecx, STACK_OFFSET @@ -1110,13 +1106,13 @@ layout_tableau: mov word [edi+CARD_X], STOCK_X mov word [edi+CARD_Y], FOUND_Y mov byte [edi+CARD_LOC], 7 - mov byte [edi+CARD_STATE], 0 + and byte [edi+CARD_STATE], 0xFE add edi, CARD_STRUCT_SIZE jmp .sf .fin: ret ; --- DATA & FONTS --- -title db 'Solitare V1.5.1', 0 +title db 'Solitare V1.5.2', 0 score dd 0 game_won db 0 mouse_lock dd 0 @@ -1133,6 +1129,7 @@ active_stack rd 13 skin_h dd 0 font_8x12: +; S, C, O, R, E, -, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 db 01111100b,10000010b,10000000b,10000000b,01111100b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; S db 01111100b,10000010b,10000000b,10000000b,10000000b,10000000b,10000000b,10000010b,01111100b,00000000b,00000000b,00000000b ; C db 01111100b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; O @@ -1151,6 +1148,7 @@ db 01111100b,10000010b,10000010b,10000010b,01111100b,10000010b,10000010b,1000001 db 01111100b,10000010b,10000010b,10000010b,10000010b,01111110b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 9 font_5x7: +; A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, Hearts, Diamonds, Clubs, Spades db 01110000b,10001000b,10001000b,11111000b,10001000b,10001000b,10001000b ; A db 11110000b,00001000b,00010000b,00100000b,01000000b,10000000b,11111000b ; 2 db 11110000b,00001000b,00001000b,01110000b,00001000b,00001000b,11110000b ; 3 -- 2.49.1 From 8f499f78d50746e26d1bd782620cb03f4c191acd Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Mar 2026 17:23:46 +0000 Subject: [PATCH 18/19] Upload files to "programs/games/solitare" Final version of game --- programs/games/solitare/solitare.asm | 477 ++++++++++++++++++++------- 1 file changed, 354 insertions(+), 123 deletions(-) diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm index 8da904563..3a42fb8d8 100644 --- a/programs/games/solitare/solitare.asm +++ b/programs/games/solitare/solitare.asm @@ -1,13 +1,13 @@ -; Solitare V1.5.2 -; Platform: KolibriOS / MenuetOS -; Author: Max (Refactored/Fixed) -; Scoring Fix: Cards only give points ONCE, even if moved back and forth. +; Solitare V1.5.3 FINAL +; Platform: KolibriOS +; Author: Max +; Format: FASM (Flat Assembler) format binary as 'run' use32 org 0x0 -; --- SYSTEM INCLUDES --- +; --- EXTERNAL INCLUDES --- include 'macros.inc' include 'KOSfuncs.inc' @@ -27,12 +27,11 @@ COL_RED equ 0xCC0000 COL_BLACK equ 0x000000 COL_SLOT equ 0x185018 -; Card structure offsets CARD_STRUCT_SIZE equ 12 CARD_VALUE equ 0 CARD_SUIT equ 1 -CARD_STATE equ 2 ; Bit 0: Face-up, Bit 7: Already Scored -CARD_LOC equ 3 ; 0-6: Tableau, 7: Stock, 8: Foundation, 9: Waste +CARD_STATE equ 2 +CARD_LOC equ 3 CARD_X equ 4 CARD_Y equ 6 CARD_OLD_X equ 8 @@ -44,6 +43,9 @@ FOUNDATION_X equ 350 FOUND_Y equ 20 SCORE_Y equ 535 +BTN_REPLAY equ 100 +BTN_EXIT equ 101 + ; --- HEADER --- db 'MENUET01' dd 0x01 @@ -56,18 +58,19 @@ dd 0, 0 start: mov esp, stacktop - ; Get system skin height + ; Get system skin height for proper coordinate calculation mcall SF_STYLE_SETTINGS, SSF_GET_SKIN_HEIGHT mov [skin_h], eax - call init_deck - call shuffle_deck - call layout_tableau - mov dword [score], 0 - mov byte [game_won], 0 + call init_game_state event_loop: + ; --- GLOBAL EXIT CHECK --- + cmp byte [exit_request], 1 + je .force_exit + mcall SF_CHECK_EVENT + cmp eax, 1 ; Redraw event je on_redraw cmp eax, 2 ; Key event @@ -75,9 +78,37 @@ event_loop: cmp eax, 3 ; Button event je on_button - call handle_mouse + ; If win condition met, run animation + cmp byte [game_won], 1 + je .win_animation - ; Update display if dragging or forced + call handle_mouse + jmp .check_redraw + +.win_animation: + call update_cascade + mov byte [force_redraw], 1 + + ; Logic to spawn win thread once + cmp byte [win_thread_active], 0 + jne .check_reset + inc dword [win_timer] + cmp dword [win_timer], 120 ; Delay before popup + jl .check_reset + + mov byte [win_thread_active], 1 + call create_win_thread + +.check_reset: + cmp byte [should_reset], 1 + jne .no_reset + call init_game_state + call draw_main_window +.no_reset: + mcall SF_SLEEP, 1 + jmp update_screen_only + +.check_redraw: cmp dword [active_card_count], 0 ja update_screen_only cmp byte [force_redraw], 1 @@ -86,6 +117,9 @@ event_loop: mcall SF_SLEEP, 1 jmp event_loop +.force_exit: + mcall SF_TERMINATE_PROCESS + on_key: mcall SF_GET_KEY jmp event_loop @@ -93,65 +127,258 @@ on_key: on_button: mcall SF_GET_BUTTON shr eax, 8 - cmp eax, 1 ; Window close button + cmp eax, 1 ; Close button jne event_loop + mcall SF_TERMINATE_PROCESS on_redraw: - mcall SF_REDRAW, SSF_BEGIN_DRAW - mov ebx, 100 shl 16 + (WIN_W + 9) - mov eax, [skin_h] - add eax, WIN_H + 5 - mov ecx, 100 shl 16 - mov cx, ax - mcall SF_CREATE_WINDOW, , , 0x14000000 or COL_TABLE, , title - mcall SF_REDRAW, SSF_END_DRAW + call draw_main_window mov byte [force_redraw], 1 jmp update_screen_only update_screen_only: mov byte [force_redraw], 0 call prepare_buffer + + ; Render buffer to window mov edx, 4 shl 16 add dx, word [skin_h] - mcall SF_PUT_IMAGE, screen_buffer, WIN_W shl 16 + WIN_H, edx + mcall SF_PUT_IMAGE, screen_buffer, WIN_W shl 16 + WIN_H jmp event_loop -; --- MOUSE HANDLING --- +; --- WIN WINDOW THREAD LOGIC --- + +create_win_thread: + mcall SF_CREATE_THREAD, SSF_CREATE_THREAD, win_thread_entry, win_stack_top + ret + +win_thread_entry: + mcall SF_THREAD_INFO, win_proc_info, -1 + + ; Center win window relative to main window + mov eax, [win_proc_info + 34] + add eax, 220 + shl eax, 16 + add eax, 300 + mov [win_pos_x], eax + + mov eax, [win_proc_info + 38] + add eax, 200 + shl eax, 16 + add eax, 180 + mov [win_pos_y], eax + +.redr: + mcall SF_REDRAW, SSF_BEGIN_DRAW + mcall SF_CREATE_WINDOW, [win_pos_x], [win_pos_y], 0x34FFFFFF, 0x80505050, title_win + mcall SF_DRAW_TEXT, 70 shl 16 + 35, 0x80000000, msg_congrats + mcall SF_DRAW_TEXT, 100 shl 16 + 65, 0x80000000, msg_score_lbl + mov eax, [score] + mov edi, score_str + call int_to_string + mcall SF_DRAW_TEXT, 160 shl 16 + 65, 0x80000000, score_str + + mcall SF_DEFINE_BUTTON, 40 shl 16 + 100, 100 shl 16 + 30, BTN_REPLAY, 0xCCCCCC + mcall SF_DRAW_TEXT, 66 shl 16 + 110, 0x80000000, txt_replay + mcall SF_DEFINE_BUTTON, 160 shl 16 + 100, 100 shl 16 + 30, BTN_EXIT, 0xCCCCCC + mcall SF_DRAW_TEXT, 194 shl 16 + 110, 0x80000000, txt_exit + mcall SF_REDRAW, SSF_END_DRAW + +.wait_ev: + mcall SF_WAIT_EVENT + cmp eax, 1 + je .redr + cmp eax, 3 + jne .wait_ev + mcall SF_GET_BUTTON + shr eax, 8 + + cmp eax, BTN_EXIT + je .trigger_exit + cmp eax, BTN_REPLAY + jne .wait_ev + +.replay_game: + mov byte [should_reset], 1 + mcall SF_TERMINATE_PROCESS + jmp .wait_ev + +.trigger_exit: + ; Signal the main thread to terminate the entire process + mov byte [exit_request], 1 + mcall SF_TERMINATE_PROCESS + +; --- GAME ENGINE LOGIC --- + +init_game_state: + call init_deck + call shuffle_deck + call layout_tableau + mov dword [score], 0 + mov byte [game_won], 0 + mov dword [win_timer], 0 + mov byte [win_thread_active], 0 + mov byte [should_reset], 0 + mov byte [exit_request], 0 + mov dword [active_cascade_idx], -1 + mov dword [cascade_timer], 0 + ret + +draw_main_window: + mcall SF_REDRAW, SSF_BEGIN_DRAW + mov ebx, 100 shl 16 + (WIN_W + 9) + mov eax, [skin_h] + add eax, WIN_H + 5 + mov ecx, 100 shl 16 + mov cx, ax + mcall SF_CREATE_WINDOW, , , 0x14000000 or COL_TABLE, 0, title + mcall SF_REDRAW, SSF_END_DRAW + ret + +int_to_string: + pushad + mov ebx, 10 + xor ecx, ecx +.l1: xor edx, edx + div ebx + add dl, '0' + push edx + inc ecx + test eax, eax + jnz .l1 +.l2: pop edx + mov [edi], dl + inc edi + loop .l2 + mov byte [edi], 0 + popad + ret + +update_cascade: + pushad + inc dword [cascade_timer] + cmp dword [cascade_timer], 3 + jl .move_active + mov dword [cascade_timer], 0 + cmp dword [active_cascade_idx], 51 + jge .move_active + inc dword [active_cascade_idx] +.move_active: + mov ecx, [active_cascade_idx] + cmp ecx, 0 + jl .done +.l: + push ecx + imul esi, ecx, CARD_STRUCT_SIZE + add esi, deck_data + imul edi, ecx, 4 + add edi, card_vectors + + ; Apply Gravity (Vertical velocity increases) + inc word [edi+2] + + ; Update Y Position + mov ax, [edi+2] + add [esi+CARD_Y], ax + + ; Update X Position + mov ax, [edi] + add [esi+CARD_X], ax + + ; Bounce off the bottom + mov ax, [esi+CARD_Y] + add ax, CARD_H + cmp ax, WIN_H + jl .no_y_bounce + mov word [esi+CARD_Y], WIN_H - CARD_H + mov ax, [edi+2] + neg ax + sar ax, 1 ; Dampen vertical bounce (energy loss) + mov [edi+2], ax +.no_y_bounce: + + ; Bounce off the left wall + mov ax, [esi+CARD_X] + cmp ax, 0 + jg .not_left + mov word [esi+CARD_X], 0 + neg word [edi] ; Reverse X velocity +.not_left: + + ; Bounce off the right wall + add ax, CARD_W + cmp ax, WIN_W + jl .no_x_bounce + mov word [esi+CARD_X], WIN_W - CARD_W + neg word [edi] ; Reverse X velocity +.no_x_bounce: + + pop ecx + dec ecx + jns .l +.done: + popad + ret + +init_cascade_vectors: + pushad + xor ecx, ecx +.l: + imul edi, ecx, 4 + add edi, card_vectors + + ; Get pseudo-random value from system time + mcall SF_GET_SYS_TIME + push eax + + ; Random Horizontal Velocity (-7 to +8 range) + and eax, 0x0F + sub eax, 7 + jnz .x_ok + inc eax ; Avoid 0 horizontal speed for variety +.x_ok: + mov [edi], ax + + ; Random Initial Vertical Kick (Bounce up) + pop eax + shr eax, 4 + and eax, 0x07 ; 0 to 7 range + neg eax ; Make it negative (moving UP) + sub eax, 4 ; Ensure a minimum upward kick + mov [edi+2], ax + + inc ecx + cmp ecx, 52 + jl .l + popad + ret handle_mouse: pushad mcall SF_MOUSE_GET, SSF_WINDOW_POSITION mov ebp, eax shr ebp, 16 - sub ebp, 5 ; Mouse X correction - + sub ebp, 5 and eax, 0xFFFF sub eax, [skin_h] - mov edi, eax ; Mouse Y in workspace - + mov edi, eax mcall SF_MOUSE_GET, SSF_BUTTON - test eax, 1 ; Left click? + test eax, 1 jnz .dragging_state - cmp dword [mouse_lock], 1 jne .exit - mov dword [mouse_lock], 0 cmp dword [active_card_count], 0 je .exit - call check_stack_move mov dword [active_card_count], 0 mov byte [force_redraw], 1 popad ret - .dragging_state: cmp dword [mouse_lock], 1 je .no_deal_click - - ; Stock pile interaction cmp ebp, STOCK_X jb .find_card cmp ebp, STOCK_X+CARD_W @@ -160,13 +387,11 @@ handle_mouse: jb .find_card cmp edi, FOUND_Y+CARD_H jae .find_card - mov dword [mouse_lock], 1 call deal_from_stock mov byte [force_redraw], 1 popad ret - .find_card: mov ebx, 51 .f_loop: @@ -174,7 +399,6 @@ handle_mouse: add edx, deck_data movsx esi, word [edx+CARD_X] movsx ecx, word [edx+CARD_Y] - cmp ebp, esi jb .next_s add esi, CARD_W @@ -185,21 +409,17 @@ handle_mouse: add ecx, CARD_H cmp edi, ecx jae .next_s - - test byte [edx+CARD_STATE], 1 ; Is card face up? + test byte [edx+CARD_STATE], 1 jz .next_s - mov dword [mouse_lock], 1 mov [active_stack], ebx mov dword [active_card_count], 1 - mov ax, word [edx+CARD_X] sub ax, bp mov [mouse_off_x], ax mov ax, word [edx+CARD_Y] sub ax, di mov [mouse_off_y], ax - mov eax, ebx call build_active_stack popad @@ -209,11 +429,9 @@ handle_mouse: jns .f_loop popad ret - .no_deal_click: cmp dword [active_card_count], 0 je .exit_drag -.drag_active: xor ecx, ecx .d_lp: cmp ecx, [active_card_count] @@ -221,20 +439,17 @@ handle_mouse: mov eax, [active_stack + ecx*4] imul eax, CARD_STRUCT_SIZE add eax, deck_data - mov dx, [mouse_off_x] add dx, bp mov [eax+CARD_X], 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+CARD_Y], dx - inc ecx jmp .d_lp .exit_drag: @@ -244,8 +459,6 @@ handle_mouse: popad ret -; --- RENDERING --- - prepare_buffer: mov edi, screen_buffer mov ecx, WIN_W * WIN_H @@ -260,10 +473,8 @@ prepare_buffer: add edi, 3 dec ecx jnz .clear_loop - call draw_slots call render_score_ui - xor ecx, ecx .draw_loop: call is_card_active @@ -277,7 +488,6 @@ prepare_buffer: inc ecx cmp ecx, 52 jl .draw_loop - xor ecx, ecx .draw_active: cmp ecx, [active_card_count] @@ -290,7 +500,6 @@ prepare_buffer: pop ecx inc ecx jmp .draw_active - .done_rendering: ret @@ -772,11 +981,10 @@ check_stack_move: popad ret .found_match: - ; FIXED SCORING: Check Bit 7 of STATE (Scored flag) test byte [esi+CARD_STATE], 0x80 jnz .already_scored add dword [score], 10 - or byte [esi+CARD_STATE], 0x80 ; Set Scored Flag + or byte [esi+CARD_STATE], 0x80 .already_scored: mov word [esi+CARD_X], bx mov word [esi+CARD_Y], FOUND_Y @@ -922,6 +1130,7 @@ check_win: jne .out add dword [score], 100 mov byte [game_won], 1 + call init_cascade_vectors .out: popad ret @@ -949,7 +1158,7 @@ auto_reveal_all: jl .find_lowest cmp dword [temp_val], -1 je .next_col - or byte [esi+CARD_STATE], 1 ; Reveal face up + or byte [esi+CARD_STATE], 1 .next_col: add ebx, 100 cmp ebx, 740 @@ -991,7 +1200,7 @@ deal_from_stock: add esi, deck_data cmp byte [esi+CARD_LOC], 7 jne .n - test byte [esi+CARD_STATE], 1 ; Already visible? + test byte [esi+CARD_STATE], 1 jnz .n .o: or byte [esi+CARD_STATE], 1 @@ -1016,7 +1225,7 @@ reset_stock: add esi, deck_data cmp byte [esi+CARD_LOC], 9 jne .s - and byte [esi+CARD_STATE], 0xFE ; Set face down + and byte [esi+CARD_STATE], 0xFE mov byte [esi+CARD_LOC], 7 mov word [esi+CARD_X], STOCK_X mov word [esi+CARD_Y], FOUND_Y @@ -1032,7 +1241,7 @@ init_deck: .r: inc ebx mov byte [edi+CARD_VALUE], bl mov byte [edi+CARD_SUIT], al - mov byte [edi+CARD_STATE], 0 ; Face down, Not Scored + mov byte [edi+CARD_STATE], 0 mov byte [edi+CARD_LOC], 7 add edi, CARD_STRUCT_SIZE cmp ebx, 13 @@ -1083,10 +1292,10 @@ layout_tableau: mov byte [edi+CARD_LOC], dl dec ebp jnz .h - or byte [edi+CARD_STATE], 1 ; Top card face up + or byte [edi+CARD_STATE], 1 jmp .nx .h: - and byte [edi+CARD_STATE], 0xFE ; Other cards face down + and byte [edi+CARD_STATE], 0xFE .nx: add edi, CARD_STRUCT_SIZE add ecx, STACK_OFFSET @@ -1111,68 +1320,90 @@ layout_tableau: jmp .sf .fin: ret -; --- DATA & FONTS --- -title db 'Solitare V1.5.2', 0 -score dd 0 -game_won db 0 -mouse_lock dd 0 -force_redraw db 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 +; --- DATA SECTION --- +title db 'Solitare V1.5.3', 0 +title_win db 'Winner!', 0 +msg_congrats db 'Congrats You Win', 0 +msg_score_lbl db 'SCORE: ', 0 +txt_replay db 'REPLAY', 0 +txt_exit db 'EXIT', 0 +score_str rb 16 +score dd 0 +game_won db 0 +win_timer dd 0 +win_thread_active db 0 +should_reset db 0 +exit_request db 0 ; GLOBAL EXIT FLAG +mouse_lock dd 0 +force_redraw db 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 -skin_h dd 0 - -font_8x12: -; S, C, O, R, E, -, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 -db 01111100b,10000010b,10000000b,10000000b,01111100b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; S -db 01111100b,10000010b,10000000b,10000000b,10000000b,10000000b,10000000b,10000010b,01111100b,00000000b,00000000b,00000000b ; C -db 01111100b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; O -db 11111100b,10000010b,10000010b,10000010b,11111100b,10010000b,10001000b,10000100b,10000010b,00000000b,00000000b,00000000b ; R -db 11111110b,10000000b,10000000b,10000000b,11111100b,10000000b,10000000b,10000000b,11111110b,00000000b,00000000b,00000000b ; E -db 00000000b,00000000b,00000000b,00000000b,11111111b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b ; - -db 00111100b,01000010b,10000001b,10000001b,10000001b,10000001b,10000001b,01000010b,00111100b,00000000b,00000000b,00000000b ; 0 -db 00011000b,00111000b,00001000b,00001000b,00001000b,00001000b,00001000b,00001000b,00111100b,00000000b,00000000b,00000000b ; 1 -db 01111100b,10000010b,00000010b,00000010b,01111100b,10000000b,10000000b,10000000b,11111110b,00000000b,00000000b,00000000b ; 2 -db 01111100b,10000010b,00000010b,00000010b,00111100b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 3 -db 00001000b,00011000b,00101000b,01001000b,10001000b,11111111b,00001000b,00001000b,00001000b,00000000b,00000000b,00000000b ; 4 -db 11111110b,10000000b,10000000b,11111100b,00000010b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 5 -db 01111100b,10000010b,10000000b,11111100b,10000010b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 6 -db 11111110b,00000010b,00000100b,00001000b,00010000b,00100000b,00100000b,00100000b,00100000b,00000000b,00000000b,00000000b ; 7 -db 01111100b,10000010b,10000010b,10000010b,01111100b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 8 -db 01111100b,10000010b,10000010b,10000010b,10000010b,01111110b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b ; 9 - -font_5x7: -; A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, Hearts, Diamonds, Clubs, Spades -db 01110000b,10001000b,10001000b,11111000b,10001000b,10001000b,10001000b ; A -db 11110000b,00001000b,00010000b,00100000b,01000000b,10000000b,11111000b ; 2 -db 11110000b,00001000b,00001000b,01110000b,00001000b,00001000b,11110000b ; 3 -db 10001000b,10001000b,10001000b,11111000b,00001000b,00001000b,00001000b ; 4 -db 11111000b,10000000b,10000000b,11110000b,00001000b,00001000b,11111000b ; 5 -db 01110000b,10000000b,10000000b,11110000b,10001000b,10001000b,01110000b ; 6 -db 11111000b,00001000b,00010000b,00100000b,01000000b,01000000b,01000000b ; 7 -db 01110000b,10001000b,10001000b,01110000b,10001000b,10001000b,01110000b ; 8 -db 01110000b,10001000b,10001000b,01111000b,00001000b,00001000b,01110000b ; 9 -db 10111000b,10101000b,10101000b,10101000b,10101000b,10101000b,10111000b ; 10 -db 00011000b,00001000b,00001000b,00001000b,00001000b,10001000b,01110000b ; J -db 01110000b,10001000b,10001000b,10001000b,10101000b,10010000b,01101000b ; Q -db 10001000b,10010000b,10100000b,11000000b,10100000b,10010000b,10001000b ; K -db 01010000b,11111000b,11111000b,01110000b,00100000b,00000000b,00000000b ; Hearts -db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,00000000b ; Diamonds -db 00100000b,00100000b,11111000b,11111000b,00100000b,00100000b,01110000b ; Clubs -db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,01110000b ; Spades +active_stack rd 13 +skin_h dd 0 +cascade_timer dd 0 +active_cascade_idx dd -1 +win_pos_x dd 0 +win_pos_y dd 0 align 4 -deck_data: rb 52 * CARD_STRUCT_SIZE +card_vectors: rw 52 * 2 ; (X velocity, Y velocity) per card +win_proc_info: rb 1024 + +font_8x12: +; 0-4 (SCRE-) 5(-) 6-15 (0-9) +db 01111100b,10000010b,10000000b,10000000b,01111100b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b +db 01111100b,10000010b,10000000b,10000000b,10000000b,10000000b,10000000b,10000010b,01111100b,00000000b,00000000b,00000000b +db 01111100b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b +db 11111100b,10000010b,10000010b,10000010b,11111100b,10010000b,10001000b,10000100b,10000010b,00000000b,00000000b,00000000b +db 11111110b,10000000b,10000000b,10000000b,11111100b,10000000b,10000000b,10000000b,11111110b,00000000b,00000000b,00000000b +db 00000000b,00000000b,00000000b,00000000b,11111111b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b,00000000b +db 00111100b,01000010b,10000001b,10000001b,10000001b,10000001b,10000001b,01000010b,00111100b,00000000b,00000000b,00000000b +db 00011000b,00111000b,00001000b,00001000b,00001000b,00001000b,00001000b,00001000b,00111100b,00000000b,00000000b,00000000b +db 01111100b,10000010b,00000010b,00000010b,01111100b,10000000b,10000000b,10000000b,11111110b,00000000b,00000000b,00000000b +db 01111100b,10000010b,00000010b,00000010b,00111100b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b +db 00001000b,00011000b,00101000b,01001000b,10001000b,11111111b,00001000b,00001000b,00001000b,00000000b,00000000b,00000000b +db 11111110b,10000000b,10000000b,11111100b,00000010b,00000010b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b +db 01111100b,10000010b,10000000b,11111100b,10000010b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b +db 11111110b,00000010b,00000100b,00001000b,00010000b,00100000b,00100000b,00100000b,00100000b,00000000b,00000000b,00000000b +db 01111100b,10000010b,10000010b,10000010b,01111100b,10000010b,10000010b,10000010b,01111100b,00000000b,00000000b,00000000b +db 01111100b,10000010b,10000010b,10000010b,10000010b,01111110b,00000010b,10000010b,01111100b,00000000b,00000000b,00000000b + +font_5x7: +db 01110000b,10001000b,10001000b,11111000b,10001000b,10001000b,10001000b +db 11110000b,00001000b,00010000b,00100000b,01000000b,10000000b,11111000b +db 11110000b,00001000b,00001000b,01110000b,00001000b,00001000b,11110000b +db 10001000b,10001000b,10001000b,11111000b,00001000b,00001000b,00001000b +db 11111000b,10000000b,10000000b,11110000b,00001000b,00001000b,11111000b +db 01110000b,10000000b,10000000b,11110000b,10001000b,10001000b,01110000b +db 11111000b,00001000b,00010000b,00100000b,01000000b,01000000b,01000000b +db 01110000b,10001000b,10001000b,01110000b,10001000b,10001000b,01110000b +db 01110000b,10001000b,10001000b,01111000b,00001000b,00001000b,01110000b +db 10111000b,10101000b,10101000b,10101000b,10101000b,10101000b,10111000b +db 00011000b,00001000b,00001000b,00001000b,00001000b,10001000b,01110000b +db 01110000b,10001000b,10001000b,10001000b,10101000b,10010000b,01101000b +db 10001000b,10010000b,10100000b,11000000b,10100000b,10010000b,10001000b +db 01010000b,11111000b,11111000b,01110000b,00100000b,00000000b,00000000b +db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,00000000b +db 00100000b,00100000b,11111000b,11111000b,00100000b,00100000b,01110000b +db 00100000b,01110000b,11111000b,11111000b,01110000b,00100000b,01110000b + +align 4 +deck_data: rb 52 * CARD_STRUCT_SIZE i_end: -align 4096 -screen_buffer: rb WIN_W * WIN_H * 3 + 32768 -stack_bottom: rb 8192 +align 64 +stack_bottom: rb 16384 stacktop: + +align 64 +win_stack_bottom: rb 8192 +win_stack_top: + +screen_buffer: rb WIN_W * WIN_H * 3 + 32768 mem_end: -- 2.49.1 From 88c24062b1dc3c92d597ba54fb7027c99faad376 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Mar 2026 19:04:41 +0000 Subject: [PATCH 19/19] Update programs/games/solitare/solitare.asm --- programs/games/solitare/solitare.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/games/solitare/solitare.asm b/programs/games/solitare/solitare.asm index 3a42fb8d8..f2347325e 100644 --- a/programs/games/solitare/solitare.asm +++ b/programs/games/solitare/solitare.asm @@ -8,8 +8,8 @@ use32 org 0x0 ; --- EXTERNAL INCLUDES --- -include 'macros.inc' -include 'KOSfuncs.inc' +include '..\..\macros.inc' +include '..\..\KOSfuncs.inc' ; --- GAME CONSTANTS --- CARD_W equ 50 -- 2.49.1