From e7ec6211fd27243339074a78c52aa9f38cb76c00 Mon Sep 17 00:00:00 2001 From: Frater <13979047+saintfrater@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:16:06 +0100 Subject: [PATCH] =?UTF-8?q?ajout=20=C3=A0=20la=20fonction=20rectangle=20fi?= =?UTF-8?q?ll=20le=20remplissage=20par=20un=20pattern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/boot.asm | 8 +- src/drivers/gfx_cgam.asm | 169 +++++++++++++++++++++------------------ src/services/gui_lib.asm | 45 ++++++++--- 3 files changed, 131 insertions(+), 91 deletions(-) diff --git a/src/boot.asm b/src/boot.asm index 72fb954..e6f0d61 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -137,6 +137,7 @@ build_interface: mov word [gs:si + widget.text_ofs], str_quit mov word [gs:si + widget.text_seg], cs ; Texte est dans la ROM mov word [gs:si + widget.event_click], on_click_quit ; Fonction à appeler + mov byte [gs:si + widget.type], WIDGET_TYPE_BUTTON ; Créer Bouton 2 "HELLO" call gui_alloc_widget @@ -148,6 +149,7 @@ build_interface: mov word [gs:si + widget.h], 20 mov word [gs:si + widget.text_ofs], str_hello mov word [gs:si + widget.text_seg], cs + mov byte [gs:si + widget.type], WIDGET_TYPE_BUTTON ; Pas de callback ; Créer Slider (Drag) @@ -159,6 +161,7 @@ build_interface: mov word [gs:si + widget.h], 20 mov word [gs:si + widget.text_ofs], str_drag mov word [gs:si + widget.text_seg], cs + mov byte [gs:si + widget.type], WIDGET_TYPE_SLIDER mov byte [gs:si + widget.drag_mode], 1 ; Horizontal mov word [gs:si + widget.drag_min], 10 mov word [gs:si + widget.drag_max], 200 @@ -181,7 +184,8 @@ timer_isr: push fs mov ax,BDA_DATA_SEG mov fs,ax -; inc byte [fs:BDA_TIMER] +; exemple de fonctionnement: +; inc byte [fs:BDA_TIMER] mov al, PIC_EOI ; EOI master out i8259_MASTER_CMD, al @@ -209,5 +213,3 @@ reset_vector: builddate: db '06/01/2026' times 16-($-$$) db 0 ; le stub tient dans 16 octets (ou moins) - - diff --git a/src/drivers/gfx_cgam.asm b/src/drivers/gfx_cgam.asm index cbb79eb..afdd69f 100644 --- a/src/drivers/gfx_cgam.asm +++ b/src/drivers/gfx_cgam.asm @@ -114,6 +114,17 @@ graph_driver: xchg ah,al %endmacro + +; ============================================================================= +; SECTION : PATTERNS & FILL +; ============================================================================= + +align 8 +pattern_black dq 0x0000000000000000 +pattern_gray_dark dq 0xDDFF77FFDDFF77FF +pattern_gray_mid dq 0xDD77DD77DD77DD77 +pattern_gray_light dq 0xAA55AA55AA55AA55 +pattern_white dq 0xFFFFFFFFFFFFFFFF ; ------------------------------------------------------------ ; initialise le mode graphique (via l'int 10h) ; @@ -312,6 +323,8 @@ cga_putc: push fs push es + call cga_mouse_hide ; Protection souris + mov bx, VIDEO_SEG mov es, bx mov bx, BDA_DATA_SEG @@ -393,6 +406,8 @@ cga_putc: inc word [fs:BDA_GFX + gfx.cur_offset] add word [fs:BDA_GFX + gfx.cur_x], 8 + call cga_mouse_show ; Restauration souris + pop es pop fs popa @@ -447,9 +462,8 @@ cga_write: cga_putpixel: push bp mov bp, sp - - pusha + call cga_mouse_hide ; Protection souris mov cx, .x mov dx, .y call cga_calc_addr @@ -467,6 +481,7 @@ cga_putpixel: and byte [es:di], ah .done: + call cga_mouse_show ; Restauration souris popa leave ret @@ -526,24 +541,18 @@ cga_background: rep stosd ret - - - ; ------------------------------------------------------------ ; cga_line_vertical (x, y0, y1, color) ; ; Dessine une ligne x, y0, y1, color ; ------------------------------------------------------------ +%define .x word [bp+4] +%define .y1 word [bp+6] +%define .y2 word [bp+8] +%define .color byte [bp+10] cga_line_vertical: push bp mov bp, sp - - ; --- Définition des arguments --- - %define .x word [bp+4] - %define .y1 word [bp+6] - %define .y2 word [bp+8] - %define .color byte [bp+10] - pusha push es @@ -607,30 +616,26 @@ cga_line_vertical: call cga_mouse_show pop es - - ; clean defs - %undef .x - %undef .y1 - %undef .y2 - %undef .color popa leave ; Leave gère le 'mov sp, bp / pop bp' ret - +; clean defs +%undef .x +%undef .y1 +%undef .y2 +%undef .color ; ------------------------------------------------------------ ; cga_line_horizontal ; Dessine une ligne horizontale de (x1, y) à (x2, y) ; ------------------------------------------------------------ +; --- Définition des arguments --- +%define .x1 word [bp+4] +%define .x2 word [bp+6] +%define .y word [bp+8] +%define .color byte [bp+10] cga_line_horizontal: push bp mov bp, sp - - ; --- Définition des arguments --- - %define .x1 word [bp+4] - %define .x2 word [bp+6] - %define .y word [bp+8] - %define .color byte [bp+10] - pusha push es @@ -756,31 +761,27 @@ cga_line_horizontal: .done: call cga_mouse_show pop es - - ; clean defs - %undef .x1 - %undef .x2 - %undef .y popa leave ret - +; clean defs +%undef .x1 +%undef .x2 +%undef .y ; ------------------------------------------------------------ ; cga_draw_rect ; Dessine un rectangle vide (contour) ; Entrée : x1, y1, x2, y2, color ; ------------------------------------------------------------ +; Arguments +%define .x1 word [bp+4] +%define .y1 word [bp+6] +%define .x2 word [bp+8] +%define .y2 word [bp+10] +%define .color word [bp+12] ; word pour l'alignement pile (mais on utilise byte) cga_draw_rect: push bp mov bp, sp - - ; Arguments - %define .x1 word [bp+4] - %define .y1 word [bp+6] - %define .x2 word [bp+8] - %define .y2 word [bp+10] - %define .color word [bp+12] ; word pour l'alignement pile (mais on utilise byte) - pusha ; 1. Ordonner X (x1 < x2) @@ -803,6 +804,8 @@ cga_draw_rect: mov .y2, bx .y_ok: + call cga_mouse_hide + ; 3. Dessiner les 4 lignes ; Pour éviter les pixels en double dans les coins, on peut ajuster légèrement, ; mais pour un driver simple, tracer les 4 lignes brutes est acceptable. @@ -813,29 +816,35 @@ cga_draw_rect: GFX LINE_VERT, .x1, .y1, .y2, .color GFX LINE_VERT, .x2, .y1, .y2, .color - ; clean defs - %undef .x1 - %undef .y1 - %undef .x2 + call cga_mouse_show popa leave ret +; clean defs +%undef .x1 +%undef .y1 +%undef .x2 +%undef .y2 +%undef .color ; ------------------------------------------------------------ ; cga_fill_rect ; Dessine un rectangle plein -; Entrée : x1, y1, x2, y2, color +; Entrée : x1, y1, x2, y2, pattern_offset (CS:Offset) ; ------------------------------------------------------------ +%define .x1 word [bp+4] +%define .y1 word [bp+6] +%define .x2 word [bp+8] +%define .y2 word [bp+10] +%define .pat word [bp+12] + +; Variable locale pour l'index du motif (y % 8) +%define .pat_idx word [bp-2] + cga_fill_rect: push bp mov bp, sp - - %define .x1 word [bp+4] - %define .y1 word [bp+6] - %define .x2 word [bp+8] - %define .y2 word [bp+10] - %define .color byte [bp+12] - + sub sp, 2 ; Reserve espace pour .pat_idx pusha push es @@ -865,6 +874,11 @@ cga_fill_rect: mov .y2, bx .y_sorted: + ; --- Init Pattern Index --- + mov ax, .y1 + and ax, 7 + mov .pat_idx, ax + ; --- 2. Calcul de la hauteur --- mov bx, .y2 sub bx, .y1 @@ -904,13 +918,24 @@ cga_fill_rect: ; --- 5. Récupérer la hauteur dans un registre sûr --- pop bx ; RESTAURER HAUTEUR DANS BX [STACK A] ; BX est maintenant notre compteur de boucle. - ; BP reste intact, donc .color est accessible ! - ; --- BOUCLE VERTICALE --- .row_loop: push di ; Sauve début ligne push si ; Sauve index byte + ; --- Récupérer le byte du motif pour cette ligne --- + push bx + mov bx, .pat_idx + push si + mov si, .pat + mov dl, [cs:si + bx] ; DL = Pattern Byte + pop si + pop bx + + ; Incrémenter index motif pour la prochaine ligne + inc word .pat_idx + and word .pat_idx, 7 + ; --- Remplissage Horizontal --- ; Cas Single Byte (Start == End) @@ -926,14 +951,7 @@ cga_fill_rect: ; Partie Centrale (Boucle tant que SI < CX) jmp .check_mid .mid_loop: - ; Ici BP est valide, donc .color est correct - cmp byte .color, 0 - je .blk - mov byte [es:di], 0xFF - jmp .nxt - .blk: - mov byte [es:di], 0x00 - .nxt: + mov byte [es:di], dl inc di inc si .check_mid: @@ -971,24 +989,23 @@ cga_fill_rect: leave ret -.apply_mask_fill: - cmp byte .color, 0 - jz .ap_black - or byte [es:di], al - ret -.ap_black: + ; helper + .apply_mask_fill: + push ax not al and byte [es:di], al + pop ax + and al, dl ; Motif masqué + or byte [es:di], al ; Applique ret +; Nettoyage des defines +%undef .x1 +%undef .y1 +%undef .x2 +%undef .y2 +%undef .pat_idx - ; Nettoyage des defines - %undef .x1 - %undef .y1 - %undef .x2 - %undef .y2 - %undef .color - -; +; ----------------------------------------------------------------------------- ; ------------------------------------------------------------ ; GESTION DU CURSEUR ; ------------------------------------------------------------ diff --git a/src/services/gui_lib.asm b/src/services/gui_lib.asm index 0a54bde..3f498d7 100644 --- a/src/services/gui_lib.asm +++ b/src/services/gui_lib.asm @@ -31,6 +31,11 @@ %define GUI_STATE_PRESSED 3 ; Clic enfoncé %define GUI_STATE_DISABLED 4 ; Grisé +; --- Types de Widgets --- +%define WIDGET_TYPE_BUTTON 0 +%define WIDGET_TYPE_SLIDER 1 +%define WIDGET_TYPE_LABEL 2 + ; --- Event mask --- %define EVENT_NONE 00000000b %define EVENT_HOVER 00000001b @@ -44,6 +49,7 @@ ; --- Structure d'un OBJET (Bouton, etc) --- struc widget .state resb 1 ; État (0=libre, >0=utilisé) + .type resb 1 ; Type (0=Button, 1=Slider...) .oldstate resb 1 ; widget a-t-il été modifié ? .user_id resb 1 ; ID unique utilisateur .x resw 1 ; Position X @@ -127,6 +133,7 @@ gui_alloc_widget: .found: ; On initialise le slot trouvé mov byte [gs:si + widget.state], GUI_STATE_NORMAL ; Marquer comme occupé + mov byte [gs:si + widget.type], WIDGET_TYPE_BUTTON ; Type par défaut mov byte [gs:si + widget.oldstate], 0 ; doit etre dessiné ; Reset des champs critiques pour éviter les déchets @@ -330,7 +337,7 @@ gui_update_logic: and byte [gs:si + widget.event], ~EVENT_HOVER jmp .done -.logic_pressed: + .logic_pressed: ; Si le bouton est relâché, on sort du mode Drag/Pressed test bl, 1 jz .released ; On saute vers la logique de relâchement standard (HitTest) @@ -342,36 +349,36 @@ gui_update_logic: je .drag_v jmp .done -.drag_h: + .drag_h: mov ax, cx sub ax, [gs:si + widget.drag_anchor] ; X = MouseX - Anchor ; Clamp Min cmp ax, [gs:si + widget.drag_min] jge .chk_max_h mov ax, [gs:si + widget.drag_min] -.chk_max_h: + .chk_max_h: ; Clamp Max cmp ax, [gs:si + widget.drag_max] jle .apply_pos mov ax, [gs:si + widget.drag_max] jmp .apply_pos -.drag_v: + .drag_v: mov ax, dx sub ax, [gs:si + widget.drag_anchor] ; Y = MouseY - Anchor ; Clamp (Simplifié, on pourrait ajouter drag_min_y) ; Ici on utilise les mêmes champs min/max pour l'axe choisi jmp .apply_pos -.apply_pos: + .apply_pos: ; Mise à jour position (si changement) cmp byte [gs:si + widget.drag_mode], 1 je .upd_x mov [gs:si + widget.y], ax jmp .force_redraw -.upd_x: + .upd_x: mov [gs:si + widget.x], ax -.force_redraw: + .force_redraw: mov byte [gs:si + widget.oldstate], 255 ; Force le redessin .done: @@ -384,7 +391,7 @@ gui_draw_single_widget: mov al, [gs:si + widget.state] cmp al, [gs:si + widget.oldstate] - je .done + je .skip_draw mov [gs:si + widget.oldstate], al ; marque comme à jour @@ -398,6 +405,13 @@ gui_draw_single_widget: add cx, ax add dx, bx +; GFX MOUSE_HIDE ; éviter que la souris ne laisse des traces + + ; Dispatch selon le type + cmp byte [gs:si + widget.type], WIDGET_TYPE_SLIDER + je .draw_slider + ; Par défaut (Button, Label...) -> continue vers .paint_normal/pressed + ; Dispatch selon état cmp byte [gs:si + widget.state], GUI_STATE_PRESSED je .paint_pressed @@ -405,13 +419,13 @@ gui_draw_single_widget: je .paint_hover .paint_normal: - GFX RECTANGLE_FILL, ax, bx, cx, dx, 1 ; Blanc + GFX RECTANGLE_FILL, ax, bx, cx, dx, pattern_white GFX RECTANGLE_DRAW, ax, bx, cx, dx, 0 ; Bord Noir GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT jmp .text .paint_hover: - GFX RECTANGLE_FILL, ax, bx, cx, dx, 1 ; Blanc + GFX RECTANGLE_FILL, ax, bx, cx, dx, pattern_gray_mid ; pattern_white GFX RECTANGLE_DRAW, ax, bx, cx, dx, 0 ; Bord Noir ; Effet gras inc ax @@ -426,7 +440,13 @@ gui_draw_single_widget: jmp .text_setup .paint_pressed: - GFX RECTANGLE_FILL, ax, bx, cx, dx, 0 ; Noir + GFX RECTANGLE_FILL, ax, bx, cx, dx, pattern_black + GFX TXT_MODE, GFX_TXT_WHITE_TRANSPARENT + jmp .text + + .draw_slider: + ; Dessin spécifique Slider (Inverse vidéo pour l'exemple) + GFX RECTANGLE_DRAW, ax, bx, cx, dx, 1 ; Bord Blanc GFX TXT_MODE, GFX_TXT_WHITE_TRANSPARENT jmp .text @@ -473,5 +493,6 @@ gui_draw_single_widget: GFX WRITE, dx, ax .done: + .skip_draw: popa - ret + ret \ No newline at end of file