gui - wip
This commit is contained in:
parent
259dc3697d
commit
88debea9f9
5 changed files with 225 additions and 199 deletions
|
|
@ -22,7 +22,7 @@ The project is intentionally educational, experimental, and minimalist.
|
||||||
- No reuse of existing BIOS code
|
- No reuse of existing BIOS code
|
||||||
- Minimal but functional implementation
|
- Minimal but functional implementation
|
||||||
- Compatible with QEMU
|
- Compatible with QEMU
|
||||||
- Target architecture: **8086 → 80486**
|
- Target architecture: **i386+**
|
||||||
|
|
||||||
- **Boot directly from ROM**
|
- **Boot directly from ROM**
|
||||||
- No DOS, no bootloader, no disk dependency
|
- No DOS, no bootloader, no disk dependency
|
||||||
|
|
@ -145,7 +145,7 @@ Le projet est volontairement **éducatif, expérimental et minimaliste**.
|
||||||
- Aucun code BIOS existant réutilisé
|
- Aucun code BIOS existant réutilisé
|
||||||
- Implémentation minimale mais fonctionnelle
|
- Implémentation minimale mais fonctionnelle
|
||||||
- Compatible avec QEMU
|
- Compatible avec QEMU
|
||||||
- Architecture ciblée : **8086 jusqu’au 486**
|
- Architecture ciblée : **i386+**
|
||||||
|
|
||||||
- **Démarrer directement depuis la ROM**
|
- **Démarrer directement depuis la ROM**
|
||||||
- Sans DOS, sans bootloader, sans disque
|
- Sans DOS, sans bootloader, sans disque
|
||||||
|
|
|
||||||
102
src/boot.asm
102
src/boot.asm
|
|
@ -100,63 +100,68 @@ reset:
|
||||||
push cs
|
push cs
|
||||||
pop ds
|
pop ds
|
||||||
|
|
||||||
setup_gui:
|
; Init du système GUI
|
||||||
; Initialiser le segment de données correct pour le texte du bouton
|
call gui_init_system
|
||||||
mov ax, cs ; ou DS selon où sont tes chaines
|
|
||||||
mov [btn_quit + widget.text_seg], ax
|
|
||||||
|
|
||||||
; GUI WINDOW, 50,50,250,100,helloworld
|
; GFX RECTANGLE_FILL, 50, 50, 100, 30, 1
|
||||||
|
|
||||||
; GFX RECTANGLE_DRAW, 50,50,250,100,0
|
|
||||||
|
|
||||||
;GFX LINE_VERT, 50, 50, 100, 0
|
|
||||||
;GFX LINE_VERT, 300, 50, 100, 0
|
|
||||||
|
|
||||||
;GFX LINE_HORIZ, 50, 300, 50, 0
|
|
||||||
;GFX LINE_HORIZ, 50, 300, 100, 0
|
|
||||||
|
|
||||||
|
|
||||||
|
call build_interface
|
||||||
|
|
||||||
mov ax,BDA_DATA_SEG
|
main_loop:
|
||||||
mov ds,ax
|
; 2. Moteur GUI (Gère tout : Loop, HitTest, Draw, Callbacks)
|
||||||
endless:
|
; DS pointe déjà sur GUI_RAM_SEG
|
||||||
|
call gui_process_all
|
||||||
|
|
||||||
; 1. Récupérer souris
|
; 3. Afficher souris
|
||||||
mov ax, [BDA_MOUSE + mouse.x]
|
; GFX MOUSE_MOVE
|
||||||
mov cx, ax ; CX = Souris X
|
|
||||||
mov ax, [BDA_MOUSE + mouse.y]
|
|
||||||
mov dx, ax ; DX = Souris Y
|
|
||||||
mov bl, [BDA_MOUSE + mouse.status] ; BL = Boutons
|
|
||||||
|
|
||||||
; 2. Gérer le bouton
|
jmp main_loop
|
||||||
mov si, btn_quit ; SI pointe sur l'objet
|
|
||||||
call gui_update_button ; Met à jour l'état et redessine si besoin
|
|
||||||
|
|
||||||
; 3. Vérifier si cliqué (AL = 1)
|
; --- Callbacks (Fonctions appelées par le moteur) ---
|
||||||
cmp al, 1
|
on_click_quit:
|
||||||
je action_quitter
|
hlt
|
||||||
|
jmp on_click_quit
|
||||||
|
|
||||||
; 4. Afficher le curseur souris (Important : après avoir dessiné le bouton)
|
|
||||||
; GFX MOUSE_MOVE
|
|
||||||
|
|
||||||
GFX TXT_MODE, GFX_TXT_BLACK
|
build_interface:
|
||||||
GFX GOTOXY, 0, 180
|
; --- CRÉATION DYNAMIQUE DES BOUTONS ---
|
||||||
|
; On reste dans CS pour lire les arguments,
|
||||||
|
; mais on configure DS=GUI_RAM_SEG pour l'allocation
|
||||||
|
|
||||||
mov ax, [BDA_MOUSE + mouse.x]
|
; Créer Bouton 1 "QUITTER"
|
||||||
call print_word_hex
|
call gui_alloc_widget ; Retourne SI = Pointeur nouveau slot
|
||||||
|
jc .mem_full
|
||||||
|
|
||||||
GFX PUTCH, ' '
|
; Remplir les propriétés
|
||||||
|
mov word [gs:si + widget.x], 10
|
||||||
|
mov word [gs:si + widget.y], 10
|
||||||
|
mov word [gs:si + widget.w], 80
|
||||||
|
mov word [gs:si + widget.h], 20
|
||||||
|
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 ax, [BDA_MOUSE + mouse.y]
|
; Créer Bouton 2 "HELLO"
|
||||||
call print_word_hex
|
call gui_alloc_widget
|
||||||
|
jc .mem_full
|
||||||
|
|
||||||
jmp endless
|
mov word [gs:si + widget.x], 100
|
||||||
|
mov word [gs:si + widget.y], 10
|
||||||
|
mov word [gs:si + widget.w], 80
|
||||||
|
mov word [gs:si + widget.h], 20
|
||||||
|
mov word [gs:si + widget.text_ofs], str_hello
|
||||||
|
mov word [gs:si + widget.text_seg], cs
|
||||||
|
; Pas de callback
|
||||||
|
|
||||||
action_quitter:
|
.mem_full:
|
||||||
hlt
|
ret
|
||||||
jmp action_quitter
|
|
||||||
|
|
||||||
|
|
||||||
|
; --- Données ROM ---
|
||||||
|
str_quit db "QUITTER", 0
|
||||||
|
str_hello db "HELLO", 0
|
||||||
|
|
||||||
; -----------------------------------------------------------
|
; -----------------------------------------------------------
|
||||||
; timer ISR (IRQ -> INT)
|
; timer ISR (IRQ -> INT)
|
||||||
; -----------------------------------------------------------
|
; -----------------------------------------------------------
|
||||||
|
|
@ -175,21 +180,6 @@ timer_isr:
|
||||||
pop ax
|
pop ax
|
||||||
iret
|
iret
|
||||||
|
|
||||||
; Déclaration d'un bouton "Quitter"
|
|
||||||
btn_quit:
|
|
||||||
istruc widget
|
|
||||||
at widget.x, dw 10
|
|
||||||
at widget.y, dw 10
|
|
||||||
at widget.w, dw 80
|
|
||||||
at widget.h, dw 20
|
|
||||||
at widget.state, db GUI_STATE_NORMAL
|
|
||||||
at widget.text_ofs, dw str_quit
|
|
||||||
at widget.text_seg, dw 0 ; Sera rempli au runtime (CS ou DS)
|
|
||||||
at widget.id, db 1
|
|
||||||
iend
|
|
||||||
|
|
||||||
str_quit db "QUITTER", 0
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------
|
; ------------------------------------------------------------------
|
||||||
; Padding jusqu'au reset vector
|
; Padding jusqu'au reset vector
|
||||||
; ------------------------------------------------------------------
|
; ------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -837,13 +837,13 @@ cga_fill_rect:
|
||||||
pusha
|
pusha
|
||||||
push es
|
push es
|
||||||
|
|
||||||
; Setup ES
|
|
||||||
mov ax, VIDEO_SEG
|
mov ax, VIDEO_SEG
|
||||||
mov es, ax
|
mov es, ax
|
||||||
|
|
||||||
call cga_mouse_hide
|
call cga_mouse_hide
|
||||||
|
|
||||||
; 1. Tri des coordonnées
|
; --- 1. Tri des coordonnées (X et Y) ---
|
||||||
|
; Tri X
|
||||||
mov ax, .x1
|
mov ax, .x1
|
||||||
mov bx, .x2
|
mov bx, .x2
|
||||||
cmp ax, bx
|
cmp ax, bx
|
||||||
|
|
@ -853,6 +853,7 @@ cga_fill_rect:
|
||||||
mov .x2, bx
|
mov .x2, bx
|
||||||
.x_sorted:
|
.x_sorted:
|
||||||
|
|
||||||
|
; Tri Y
|
||||||
mov ax, .y1
|
mov ax, .y1
|
||||||
mov bx, .y2
|
mov bx, .y2
|
||||||
cmp ax, bx
|
cmp ax, bx
|
||||||
|
|
@ -862,35 +863,35 @@ cga_fill_rect:
|
||||||
mov .y2, bx
|
mov .y2, bx
|
||||||
.y_sorted:
|
.y_sorted:
|
||||||
|
|
||||||
; Calculer hauteur
|
; --- 2. Calcul de la hauteur ---
|
||||||
sub bx, ax ; BX = y2 - y1
|
mov bx, .y2
|
||||||
inc bx ; BX = hauteur
|
sub bx, .y1
|
||||||
mov dx, bx ; DX = Compteur de hauteur
|
inc bx ; BX = Hauteur finale
|
||||||
|
push bx ; SAUVEGARDER LA HAUTEUR SUR LA PILE [STACK A]
|
||||||
|
; (Car on va utiliser BX dans cga_calc_addr ou juste après)
|
||||||
|
|
||||||
; 2. Calculer l'adresse de départ (Haut-Gauche)
|
; --- 3. Calcul adresse de départ ---
|
||||||
mov cx, .x1 ; CX = x1
|
mov cx, .x1
|
||||||
mov dx, .y1 ; DX = y1
|
mov dx, .y1
|
||||||
push dx ; Sauve Y1 (car cga_calc_addr peut modifier DX/BX selon implémentation)
|
|
||||||
|
|
||||||
; Note: cga_calc_addr attend CX=x, DX=y
|
; Note: cga_calc_addr attend CX=x, DX=y et retourne DI
|
||||||
|
; Si cga_calc_addr modifie BX, la sauvegarde [STACK A] est vitale.
|
||||||
call cga_calc_addr ; DI = Offset début ligne
|
call cga_calc_addr ; DI = Offset début ligne
|
||||||
|
|
||||||
pop bx ; Récupère Y1 dans BX (pour savoir si pair/impair)
|
; --- 4. Préparer les masques ---
|
||||||
|
; Masque Gauche (DH)
|
||||||
; 3. Préparer les masques gauche/droite (comme Line Horizontal)
|
|
||||||
; Masque Gauche
|
|
||||||
mov cx, .x1
|
mov cx, .x1
|
||||||
and cx, 7
|
and cx, 7
|
||||||
mov dh, 0xFF
|
mov dh, 0xFF
|
||||||
shr dh, cl ; DH = Masque Gauche
|
shr dh, cl
|
||||||
|
|
||||||
; Masque Droite
|
; Masque Droite (AH)
|
||||||
mov cx, .x2
|
mov cx, .x2
|
||||||
and cx, 7
|
and cx, 7
|
||||||
inc cx
|
inc cx
|
||||||
mov ah, 0xFF
|
mov ah, 0xFF
|
||||||
shr ah, cl
|
shr ah, cl
|
||||||
not ah ; AH = Masque Droite
|
not ah
|
||||||
|
|
||||||
; Index octets
|
; Index octets
|
||||||
mov si, .x1
|
mov si, .x1
|
||||||
|
|
@ -898,35 +899,32 @@ cga_fill_rect:
|
||||||
mov cx, .x2
|
mov cx, .x2
|
||||||
shr cx, 3 ; CX = Index end byte
|
shr cx, 3 ; CX = Index end byte
|
||||||
|
|
||||||
; Récupérer la hauteur (Y2 - Y1 + 1)
|
; --- 5. Récupérer la hauteur dans un registre sûr ---
|
||||||
mov bp, .y2
|
pop bx ; RESTAURER HAUTEUR DANS BX [STACK A]
|
||||||
sub bp, .y1
|
; BX est maintenant notre compteur de boucle.
|
||||||
inc bp ; BP = Hauteur (Loop counter)
|
; BP reste intact, donc .color est accessible !
|
||||||
|
|
||||||
; Sauvegarder l'état pair/impair initial
|
|
||||||
; Si Y1 est impair, le premier saut de ligne doit être "vers le haut" (-0x2000 + 80)
|
|
||||||
; ou plus simplement : on gère le flip 0x2000 à chaque ligne.
|
|
||||||
|
|
||||||
; --- BOUCLE VERTICALE ---
|
; --- BOUCLE VERTICALE ---
|
||||||
.row_loop:
|
.row_loop:
|
||||||
push di ; Sauve le début de la ligne actuelle
|
push di ; Sauve début ligne
|
||||||
push si ; Sauve index byte start
|
push si ; Sauve index byte
|
||||||
|
|
||||||
; --- Remplissage Horizontal (copié de line_horizontal) ---
|
; --- Remplissage Horizontal ---
|
||||||
|
|
||||||
; Cas Single Byte
|
; Cas Single Byte (Start == End)
|
||||||
cmp si, cx
|
cmp si, cx
|
||||||
je .single_byte_row
|
je .single_byte_row
|
||||||
|
|
||||||
; Partie Gauche
|
; Partie Gauche
|
||||||
mov al, dh ; Masque Gauche
|
mov al, dh
|
||||||
call .apply_mask_fill
|
call .apply_mask_fill
|
||||||
inc di
|
inc di
|
||||||
inc si
|
inc si
|
||||||
|
|
||||||
; Partie Centrale
|
; Partie Centrale (Boucle tant que SI < CX)
|
||||||
jmp .check_mid
|
jmp .check_mid
|
||||||
.mid_loop:
|
.mid_loop:
|
||||||
|
; Ici BP est valide, donc .color est correct
|
||||||
cmp byte .color, 0
|
cmp byte .color, 0
|
||||||
je .blk
|
je .blk
|
||||||
mov byte [es:di], 0xFF
|
mov byte [es:di], 0xFF
|
||||||
|
|
@ -941,42 +939,36 @@ cga_fill_rect:
|
||||||
jl .mid_loop
|
jl .mid_loop
|
||||||
|
|
||||||
; Partie Droite
|
; Partie Droite
|
||||||
mov al, ah ; Masque Droite
|
mov al, ah
|
||||||
call .apply_mask_fill
|
call .apply_mask_fill
|
||||||
jmp .row_done
|
jmp .row_done
|
||||||
|
|
||||||
.single_byte_row:
|
.single_byte_row:
|
||||||
mov al, dh
|
mov al, dh
|
||||||
and al, ah ; Intersection masques
|
and al, ah ; Intersection des masques
|
||||||
call .apply_mask_fill
|
call .apply_mask_fill
|
||||||
|
|
||||||
.row_done:
|
.row_done:
|
||||||
pop si
|
pop si
|
||||||
pop di ; Restaure début de ligne
|
pop di
|
||||||
|
|
||||||
; --- Passage à la ligne suivante (Logique CGA optimisée) ---
|
; --- Passage ligne suivante (CGA Bank Switch) ---
|
||||||
xor di, 0x2000 ; Flip banque
|
xor di, 0x2000
|
||||||
test di, 0x2000
|
test di, 0x2000
|
||||||
jnz .bank_switch_ok ; Si on passe de 0->1, on a descendu d'une ligne visuelle
|
jnz .bank_switch_ok
|
||||||
add di, 80 ; Si on passe de 1->0, on remonte, donc faut ajouter 80
|
add di, 80
|
||||||
.bank_switch_ok:
|
.bank_switch_ok:
|
||||||
|
|
||||||
dec bp
|
dec bx ; On décrémente BX (Hauteur) au lieu de BP
|
||||||
jnz .row_loop
|
jnz .row_loop
|
||||||
|
|
||||||
call cga_mouse_show
|
call cga_mouse_show
|
||||||
pop es
|
pop es
|
||||||
|
|
||||||
; clean defs
|
|
||||||
%undef .x1
|
|
||||||
%undef .y1
|
|
||||||
%undef .x2
|
|
||||||
popa
|
popa
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Helper local pour Fill Rect
|
|
||||||
; AL = Masque, .color = couleur
|
|
||||||
.apply_mask_fill:
|
.apply_mask_fill:
|
||||||
cmp byte .color, 0
|
cmp byte .color, 0
|
||||||
jz .ap_black
|
jz .ap_black
|
||||||
|
|
@ -986,6 +978,14 @@ cga_fill_rect:
|
||||||
not al
|
not al
|
||||||
and byte [es:di], al
|
and byte [es:di], al
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; Nettoyage des defines
|
||||||
|
%undef .x1
|
||||||
|
%undef .y1
|
||||||
|
%undef .x2
|
||||||
|
%undef .y2
|
||||||
|
%undef .color
|
||||||
|
|
||||||
;
|
;
|
||||||
; ------------------------------------------------------------
|
; ------------------------------------------------------------
|
||||||
; GESTION DU CURSEUR
|
; GESTION DU CURSEUR
|
||||||
|
|
|
||||||
|
|
@ -306,14 +306,15 @@ isr_mouse_handler:
|
||||||
|
|
||||||
; debut du décodage des données
|
; debut du décodage des données
|
||||||
mov bl, [BDA_MOUSE + mouse.buffer] ; status
|
mov bl, [BDA_MOUSE + mouse.buffer] ; status
|
||||||
mov al,bl
|
|
||||||
; --- BOUTONS (Optionnel mais recommandé) ---
|
; --- BOUTONS ---
|
||||||
|
mov al,bl ; extraction des boutons
|
||||||
and al, 00000111b ; Bits 0, 1, 2 = Gauche, Droite, Milieu
|
and al, 00000111b ; Bits 0, 1, 2 = Gauche, Droite, Milieu
|
||||||
mov [BDA_MOUSE + mouse.status], al
|
mov [BDA_MOUSE + mouse.status], al
|
||||||
|
|
||||||
xor ax,ax
|
xor ax,ax
|
||||||
mov al, byte [BDA_MOUSE + mouse.buffer+1] ; delta X
|
mov al, byte [BDA_MOUSE + mouse.buffer+1] ; delta X
|
||||||
test bl,00010000b ; signe X
|
test bl,00010000b ; signe X (4eme bit)
|
||||||
jz .x_pos
|
jz .x_pos
|
||||||
mov ah,0xff ; X est négatif
|
mov ah,0xff ; X est négatif
|
||||||
.x_pos:
|
.x_pos:
|
||||||
|
|
@ -321,7 +322,7 @@ isr_mouse_handler:
|
||||||
|
|
||||||
xor ax,ax
|
xor ax,ax
|
||||||
mov al, byte [BDA_MOUSE + mouse.buffer+2] ; delta Y
|
mov al, byte [BDA_MOUSE + mouse.buffer+2] ; delta Y
|
||||||
test bl,00100000b ; signe Y
|
test bl,00100000b ; signe Y (5eme bit)
|
||||||
jz .y_pos
|
jz .y_pos
|
||||||
mov ah,0xff ; y est négatif
|
mov ah,0xff ; y est négatif
|
||||||
.y_pos:
|
.y_pos:
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
|
|
||||||
; --- Configuration Mémoire ---
|
; --- Configuration Mémoire ---
|
||||||
%define GUI_RAM_SEG 0x0800 ; Segment de données UI
|
%define GUI_RAM_SEG 0x0A00 ; Segment de données UI
|
||||||
%define GUI_MAX_WIDGETS 32 ; Nombre max de widgets simultanés
|
%define GUI_MAX_WIDGETS 32 ; Nombre max de widgets simultanés
|
||||||
|
|
||||||
; --- Drapeaux & États ---
|
; --- Drapeaux & États ---
|
||||||
|
|
@ -39,7 +39,6 @@ struc widget
|
||||||
.y resw 1 ; Position Y
|
.y resw 1 ; Position Y
|
||||||
.w resw 1 ; Largeur
|
.w resw 1 ; Largeur
|
||||||
.h resw 1 ; Hauteur
|
.h resw 1 ; Hauteur
|
||||||
.state resb 1 ; État (0=Normal, 1=Hover, 2=Pressed, 3=Disabled)
|
|
||||||
.text_ofs resw 1 ; Offset du texte
|
.text_ofs resw 1 ; Offset du texte
|
||||||
.text_seg resw 1 ; Segment du texte
|
.text_seg resw 1 ; Segment du texte
|
||||||
.event_click resw 1 ; adresse de la fonction "on click"
|
.event_click resw 1 ; adresse de la fonction "on click"
|
||||||
|
|
@ -60,42 +59,46 @@ endstruc
|
||||||
; Entrée : DS doit pointer vers GUI_RAM_SEG
|
; Entrée : DS doit pointer vers GUI_RAM_SEG
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
gui_init_system:
|
gui_init_system:
|
||||||
pushad
|
push eax
|
||||||
push ds
|
push cx
|
||||||
|
push es
|
||||||
|
push di
|
||||||
|
|
||||||
mov ax, GUI_RAM_SEG
|
mov ax, GUI_RAM_SEG
|
||||||
mov ds, ax
|
mov es, ax
|
||||||
|
|
||||||
mov di, 0 ; On commence au début du segment 0x0800
|
xor di, di
|
||||||
mov cx, (widget_size * GUI_MAX_WIDGETS)
|
mov cx, (widget_size * GUI_MAX_WIDGETS)
|
||||||
shl cx, 2 ; cx / 4
|
shl cx, 2 ; cx / 4
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
rep stosd ; Remplit tout de 0
|
rep stosd ; Remplit tout de 0
|
||||||
|
|
||||||
pop ds
|
pop di
|
||||||
popad
|
pop es
|
||||||
|
pop cx
|
||||||
|
pop eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
; gui_alloc_widget
|
; gui_alloc_widget
|
||||||
; Cherche un slot vide et retourne son adresse
|
; Cherche un slot vide et retourne son adresse
|
||||||
; Sortie :
|
; Sortie :
|
||||||
; - Succès : CF=0 (Carry Clear), SI = Offset du widget
|
; - Succès : CF=0 (Carry Clear), DS:SI = Offset du widget
|
||||||
; - Echec : CF=1 (Carry Set), SI = Indéfini (ou 0)
|
; - Echec : CF=1 (Carry Set), DS:SI = Indéfini (ou 0)
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
gui_alloc_widget:
|
gui_alloc_widget:
|
||||||
|
push ax
|
||||||
push cx
|
push cx
|
||||||
push bx
|
push bx
|
||||||
push ds
|
|
||||||
|
|
||||||
mov ax, GUI_RAM_SEG
|
mov ax, GUI_RAM_SEG
|
||||||
mov ds, ax
|
mov gs, ax
|
||||||
|
|
||||||
mov si, 0 ; Début du pool
|
mov si, 0 ; Début du pool
|
||||||
mov cx, GUI_MAX_WIDGETS
|
mov cx, GUI_MAX_WIDGETS
|
||||||
|
|
||||||
.loop_find:
|
.loop_find:
|
||||||
cmp byte [si + widget.state], GUI_STATE_FREE
|
cmp byte [gs:si + widget.state], GUI_STATE_FREE
|
||||||
je .found ; Si state == 0, c'est libre !
|
je .found ; Si state == 0, c'est libre !
|
||||||
|
|
||||||
add si, widget_size ; Sinon on passe au suivant
|
add si, widget_size ; Sinon on passe au suivant
|
||||||
|
|
@ -107,16 +110,16 @@ gui_alloc_widget:
|
||||||
|
|
||||||
.found:
|
.found:
|
||||||
; On initialise le slot trouvé
|
; On initialise le slot trouvé
|
||||||
mov byte [si + widget.state], GUI_STATE_NORMAL ; Marquer comme occupé
|
mov byte [gs:si + widget.state], GUI_STATE_NORMAL ; Marquer comme occupé
|
||||||
|
|
||||||
; Reset des champs critiques pour éviter les déchets
|
; Reset des champs critiques pour éviter les déchets
|
||||||
mov word [si + widget.callback], 0
|
mov word [gs:si + widget.event_click], 0
|
||||||
|
|
||||||
clc ; Clear Carry Flag
|
clc ; Clear Carry Flag
|
||||||
.done:
|
.done:
|
||||||
pop ds
|
|
||||||
pop bx
|
pop bx
|
||||||
pop cx
|
pop cx
|
||||||
|
pop ax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
|
|
@ -125,11 +128,25 @@ gui_alloc_widget:
|
||||||
; Entrée : SI = Pointeur widget
|
; Entrée : SI = Pointeur widget
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
gui_free_widget:
|
gui_free_widget:
|
||||||
mov byte [si + widget.state], GUI_STATE_FREE
|
push eax
|
||||||
|
push es
|
||||||
|
|
||||||
|
mov ax, GUI_RAM_SEG
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
xor di, di
|
||||||
|
mov cx, (widget_size)
|
||||||
|
shl cx, 2 ; cx / 4
|
||||||
|
xor eax, eax
|
||||||
|
rep stosd ; Remplit tout de 0
|
||||||
|
|
||||||
|
mov byte [gs:si + widget.state], GUI_STATE_FREE
|
||||||
; On efface visuellement le widget (optionnel, remplit de blanc)
|
; On efface visuellement le widget (optionnel, remplit de blanc)
|
||||||
; Pour l'instant on le marque juste libre, il sera redessiné par-dessus.
|
; Pour l'instant on le marque juste libre, il sera redessiné par-dessus.
|
||||||
ret
|
|
||||||
|
|
||||||
|
pop es
|
||||||
|
pop eax
|
||||||
|
ret
|
||||||
|
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
; SECTION : MOTEUR D'ÉVÉNEMENTS (EVENT LOOP)
|
; SECTION : MOTEUR D'ÉVÉNEMENTS (EVENT LOOP)
|
||||||
|
|
@ -146,31 +163,46 @@ gui_free_widget:
|
||||||
; -----------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------
|
||||||
gui_process_all:
|
gui_process_all:
|
||||||
pusha
|
pusha
|
||||||
|
push gs
|
||||||
|
|
||||||
|
mov ax, BDA_DATA_SEG
|
||||||
|
mov ds, ax
|
||||||
|
|
||||||
|
mov cx, [BDA_MOUSE + mouse.x]
|
||||||
|
mov dx, [BDA_MOUSE + mouse.y]
|
||||||
|
mov bl, [BDA_MOUSE + mouse.status]
|
||||||
|
|
||||||
|
mov ax, GUI_RAM_SEG
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
mov si, 0 ; Pointeur début tableau
|
mov si, 0 ; Pointeur début tableau
|
||||||
mov di, GUI_MAX_WIDGETS ; Compteur
|
mov di, GUI_MAX_WIDGETS ; Compteur
|
||||||
|
|
||||||
.loop_widgets:
|
.loop_widgets:
|
||||||
; Est-ce que ce slot est occupé ?
|
; Est-ce que ce slot est occupé ?
|
||||||
cmp byte [si + widget.state], GUI_STATE_FREE
|
cmp byte [gs:si + widget.state], GUI_STATE_FREE
|
||||||
je .next_widget
|
je .next_widget
|
||||||
|
|
||||||
|
; mov ah, [gs:si + widget.state] ; AH = Ancien état du widget
|
||||||
|
|
||||||
; --- Logique Widget ---
|
; --- Logique Widget ---
|
||||||
push bx ; Sauver état boutons souris
|
;push bx ; Sauver état boutons souris
|
||||||
|
push ax
|
||||||
call gui_update_logic ; Vérifier collision/clic
|
call gui_update_logic ; Vérifier collision/clic
|
||||||
|
;pop ax
|
||||||
|
|
||||||
; Si AL=1 (Clic relâché validé), exécuter le callback
|
; Si AL=1 (Clic relâché validé), exécuter le callback
|
||||||
cmp al, 1
|
cmp al, 1
|
||||||
jne .no_action
|
jne .no_action
|
||||||
|
|
||||||
; Vérifier si un callback est défini
|
; Vérifier si un callback est défini
|
||||||
cmp word [si + widget.callback], 0
|
cmp word [gs:si + widget.event_click], 0
|
||||||
je .no_action
|
je .no_action
|
||||||
|
|
||||||
; APPEL DU CALLBACK (Fonction utilisateur)
|
; APPEL DU CALLBACK (Fonction utilisateur)
|
||||||
; On sauve les registres car le callback peut faire n'importe quoi
|
; On sauve les registres car le callback peut faire n'importe quoi
|
||||||
pusha
|
pusha
|
||||||
call word [si + widget.callback]
|
call word [gs:si + widget.event_click]
|
||||||
popa
|
popa
|
||||||
|
|
||||||
.no_action:
|
.no_action:
|
||||||
|
|
@ -184,6 +216,7 @@ gui_process_all:
|
||||||
dec di
|
dec di
|
||||||
jnz .loop_widgets
|
jnz .loop_widgets
|
||||||
|
|
||||||
|
pop ds
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
@ -193,25 +226,25 @@ gui_process_all:
|
||||||
|
|
||||||
; (Interne) Met à jour l'état d'un seul widget
|
; (Interne) Met à jour l'état d'un seul widget
|
||||||
; Entrée : SI=Widget, CX=MouseX, DX=MouseY, BL=Buttons
|
; Entrée : SI=Widget, CX=MouseX, DX=MouseY, BL=Buttons
|
||||||
; Sortie : AL=1 si Clicked, 0 sinon. Met à jour [SI].state
|
; Sortie : AL=1 si Clicked, 0 sinon. Met à jour [gs:si].state
|
||||||
gui_update_logic:
|
gui_update_logic:
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
|
|
||||||
cmp byte [si + widget.state], GUI_STATE_DISABLED
|
cmp byte [gs:si + widget.state], GUI_STATE_DISABLED
|
||||||
je .done
|
je .done
|
||||||
|
|
||||||
; --- Hit Test ---
|
; --- Hit Test ---
|
||||||
cmp cx, [si + widget.x]
|
cmp cx, [gs:si + widget.x]
|
||||||
jl .miss
|
jl .miss
|
||||||
mov bp, [si + widget.x]
|
mov bp, [gs:si + widget.x]
|
||||||
add bp, [si + widget.w]
|
add bp, [gs:si + widget.w]
|
||||||
cmp cx, bp
|
cmp cx, bp
|
||||||
jg .miss
|
jg .miss
|
||||||
|
|
||||||
cmp dx, [si + widget.y]
|
cmp dx, [gs:si + widget.y]
|
||||||
jl .miss
|
jl .miss
|
||||||
mov bp, [si + widget.y]
|
mov bp, [gs:si + widget.y]
|
||||||
add bp, [si + widget.h]
|
add bp, [gs:si + widget.h]
|
||||||
cmp dx, bp
|
cmp dx, bp
|
||||||
jg .miss
|
jg .miss
|
||||||
|
|
||||||
|
|
@ -220,26 +253,26 @@ gui_update_logic:
|
||||||
jz .released
|
jz .released
|
||||||
|
|
||||||
; Clic enfoncé
|
; Clic enfoncé
|
||||||
mov byte [si + widget.state], GUI_STATE_PRESSED
|
mov byte [gs:si + widget.state], GUI_STATE_PRESSED
|
||||||
jmp .done
|
jmp .done
|
||||||
|
|
||||||
.released:
|
.released:
|
||||||
; Bouton relâché. Était-il pressé avant ?
|
; Bouton relâché. Était-il pressé avant ?
|
||||||
cmp byte [si + widget.state], GUI_STATE_PRESSED
|
cmp byte [gs:si + widget.state], GUI_STATE_PRESSED
|
||||||
jne .hover
|
jne .hover
|
||||||
|
|
||||||
; Clic validé !
|
; Clic validé !
|
||||||
mov al, 1
|
mov al, 1
|
||||||
mov byte [si + widget.state], GUI_STATE_HOVER
|
mov byte [gs:si + widget.state], GUI_STATE_HOVER
|
||||||
jmp .done
|
jmp .done
|
||||||
|
|
||||||
.hover:
|
.hover:
|
||||||
mov byte [si + widget.state], GUI_STATE_HOVER
|
mov byte [gs:si + widget.state], GUI_STATE_HOVER
|
||||||
jmp .done
|
jmp .done
|
||||||
|
|
||||||
.miss:
|
.miss:
|
||||||
mov byte [si + widget.state], GUI_STATE_NORMAL
|
mov byte [gs:si + widget.state], GUI_STATE_NORMAL
|
||||||
.done:
|
.done:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; (Interne) Dessine le widget pointé par SI
|
; (Interne) Dessine le widget pointé par SI
|
||||||
|
|
@ -247,10 +280,10 @@ gui_draw_single_widget:
|
||||||
pusha
|
pusha
|
||||||
|
|
||||||
; Chargement coords
|
; Chargement coords
|
||||||
mov ax, [si + widget.x]
|
mov ax, [gs:si + widget.x]
|
||||||
mov bx, [si + widget.y]
|
mov bx, [gs:si + widget.y]
|
||||||
mov cx, [si + widget.w]
|
mov cx, [gs:si + widget.w]
|
||||||
mov dx, [si + widget.h]
|
mov dx, [gs:si + widget.h]
|
||||||
|
|
||||||
; Calcul X2, Y2
|
; Calcul X2, Y2
|
||||||
mov di, ax
|
mov di, ax
|
||||||
|
|
@ -259,19 +292,19 @@ gui_draw_single_widget:
|
||||||
add bp, dx
|
add bp, dx
|
||||||
|
|
||||||
; Dispatch selon état
|
; Dispatch selon état
|
||||||
mov al, [si + widget.state]
|
mov al, [gs:si + widget.state]
|
||||||
cmp al, GUI_STATE_PRESSED
|
cmp al, GUI_STATE_PRESSED
|
||||||
je .paint_pressed
|
je .paint_pressed
|
||||||
cmp al, GUI_STATE_HOVER
|
cmp al, GUI_STATE_HOVER
|
||||||
je .paint_hover
|
je .paint_hover
|
||||||
|
|
||||||
.paint_normal:
|
.paint_normal:
|
||||||
GFX RECTANGLE_FILL, ax, bx, di, bp, 1 ; Blanc
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 1 ; Blanc
|
||||||
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0 ; Bord Noir
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0 ; Bord Noir
|
||||||
GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT
|
GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT
|
||||||
jmp .text
|
jmp .text
|
||||||
|
|
||||||
.paint_hover:
|
.paint_hover:
|
||||||
GFX RECTANGLE_FILL, ax, bx, di, bp, 1
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 1
|
||||||
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
||||||
; Effet gras
|
; Effet gras
|
||||||
|
|
@ -282,36 +315,38 @@ gui_draw_single_widget:
|
||||||
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
||||||
|
|
||||||
; Restauration coords pour le texte
|
; Restauration coords pour le texte
|
||||||
mov ax, [si + widget.x]
|
mov ax, [gs:si + widget.x]
|
||||||
mov bx, [si + widget.y]
|
mov bx, [gs:si + widget.y]
|
||||||
jmp .text_setup
|
jmp .text_setup
|
||||||
|
|
||||||
.paint_pressed:
|
.paint_pressed:
|
||||||
GFX RECTANGLE_FILL, ax, bx, di, bp, 0 ; Noir
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 0 ; Noir
|
||||||
GFX TXT_MODE, GFX_TXT_WHITE_TRANSPARENT
|
GFX TXT_MODE, GFX_TXT_WHITE_TRANSPARENT
|
||||||
jmp .text
|
jmp .text
|
||||||
|
|
||||||
.text_setup:
|
.text_setup:
|
||||||
; Petit hack pour recentrer le texte après l'effet gras
|
; Petit hack pour recentrer le texte après l'effet gras
|
||||||
mov cx, [si + widget.w]
|
mov cx, [gs:si + widget.w]
|
||||||
mov dx, [si + widget.h]
|
mov dx, [gs:si + widget.h]
|
||||||
|
|
||||||
.text:
|
.text:
|
||||||
; --- Centrage Texte (Simplifié) ---
|
; --- Centrage Texte (Simplifié) ---
|
||||||
push si
|
push si
|
||||||
mov es, [si + widget.text_seg]
|
mov es, [gs:si + widget.text_seg]
|
||||||
mov di, [si + widget.text_ofs]
|
mov di, [gs:si + widget.text_ofs]
|
||||||
xor cx, cx
|
xor cx, cx
|
||||||
.strlen:
|
|
||||||
|
.strlen:
|
||||||
cmp byte [es:di], 0
|
cmp byte [es:di], 0
|
||||||
je .calc
|
je .calc
|
||||||
inc cx
|
inc cx
|
||||||
inc di
|
inc di
|
||||||
jmp .strlen
|
jmp .strlen
|
||||||
.calc:
|
|
||||||
|
.calc:
|
||||||
shl cx, 3 ; Largeur texte px
|
shl cx, 3 ; Largeur texte px
|
||||||
push ax ; Sauve X original
|
push ax ; Sauve X original
|
||||||
mov ax, [si + widget.w]
|
mov ax, [gs:si + widget.w]
|
||||||
sub ax, cx
|
sub ax, cx
|
||||||
shr ax, 1
|
shr ax, 1
|
||||||
pop bx ; Récupère X original dans BX (oups, on veut ajouter)
|
pop bx ; Récupère X original dans BX (oups, on veut ajouter)
|
||||||
|
|
@ -319,17 +354,17 @@ gui_draw_single_widget:
|
||||||
|
|
||||||
push ax ; X final prêt
|
push ax ; X final prêt
|
||||||
|
|
||||||
mov bx, [si + widget.h]
|
mov bx, [gs:si + widget.h]
|
||||||
sub bx, 8
|
sub bx, 8
|
||||||
shr bx, 1
|
shr bx, 1
|
||||||
add bx, [si + widget.y] ; Y final
|
add bx, [gs:si + widget.y] ; Y final
|
||||||
|
|
||||||
pop cx ; CX = X Final, BX = Y Final
|
pop cx ; CX = X Final, BX = Y Final
|
||||||
|
|
||||||
GFX GOTOXY, cx, bx
|
GFX GOTOXY, cx, bx
|
||||||
|
|
||||||
mov dx, [si + widget.text_seg]
|
mov dx, [gs:si + widget.text_seg]
|
||||||
mov ax, [si + widget.text_ofs]
|
mov ax, [gs:si + widget.text_ofs]
|
||||||
GFX WRITE, dx, ax
|
GFX WRITE, dx, ax
|
||||||
|
|
||||||
pop si
|
pop si
|
||||||
|
|
@ -347,10 +382,10 @@ gui_draw_button:
|
||||||
pusha
|
pusha
|
||||||
|
|
||||||
; Charger les propriétés depuis la structure
|
; Charger les propriétés depuis la structure
|
||||||
mov ax, [si + widget.x]
|
mov ax, [gs:si + widget.x]
|
||||||
mov bx, [si + widget.y]
|
mov bx, [gs:si + widget.y]
|
||||||
mov cx, [si + widget.w]
|
mov cx, [gs:si + widget.w]
|
||||||
mov dx, [si + widget.h]
|
mov dx, [gs:si + widget.h]
|
||||||
|
|
||||||
; Calculer X2 et Y2 pour le rectangle
|
; Calculer X2 et Y2 pour le rectangle
|
||||||
mov di, ax ; X1
|
mov di, ax ; X1
|
||||||
|
|
@ -359,13 +394,13 @@ gui_draw_button:
|
||||||
add bp, dx ; Y2 = Y + H
|
add bp, dx ; Y2 = Y + H
|
||||||
|
|
||||||
; Vérifier l'état
|
; Vérifier l'état
|
||||||
cmp byte [si + widget.state], GUI_STATE_PRESSED
|
cmp byte [gs:si + widget.state], GUI_STATE_PRESSED
|
||||||
je .draw_pressed
|
je .draw_pressed
|
||||||
|
|
||||||
cmp byte [si + widget.state], GUI_STATE_HOVER
|
cmp byte [gs:si + widget.state], GUI_STATE_HOVER
|
||||||
je .draw_hover
|
je .draw_hover
|
||||||
|
|
||||||
cmp byte [si + widget.state], GUI_STATE_DISABLED
|
cmp byte [gs:si + widget.state], GUI_STATE_DISABLED
|
||||||
je .draw_disabled
|
je .draw_disabled
|
||||||
|
|
||||||
.draw_normal:
|
.draw_normal:
|
||||||
|
|
@ -392,10 +427,10 @@ gui_draw_button:
|
||||||
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
||||||
|
|
||||||
; Restaurer les coords pour le texte
|
; Restaurer les coords pour le texte
|
||||||
mov ax, [si + widget.x]
|
mov ax, [gs:si + widget.x]
|
||||||
mov bx, [si + widget.y]
|
mov bx, [gs:si + widget.y]
|
||||||
mov di, ax
|
mov di, ax
|
||||||
add di, [si + widget.w]
|
add di, [gs:si + widget.w]
|
||||||
|
|
||||||
GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT
|
GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT
|
||||||
jmp .draw_text
|
jmp .draw_text
|
||||||
|
|
@ -425,8 +460,8 @@ gui_draw_button:
|
||||||
|
|
||||||
push si
|
push si
|
||||||
; 1. Calculer longueur chaine
|
; 1. Calculer longueur chaine
|
||||||
mov es, [si + widget.text_seg]
|
mov es, [gs:si + widget.text_seg]
|
||||||
mov di, [si + widget.text_ofs]
|
mov di, [gs:si + widget.text_ofs]
|
||||||
xor cx, cx
|
xor cx, cx
|
||||||
|
|
||||||
.strlen:
|
.strlen:
|
||||||
|
|
@ -440,21 +475,21 @@ gui_draw_button:
|
||||||
; CX = Longueur chaine
|
; CX = Longueur chaine
|
||||||
shl cx, 3 ; CX * 8 (largeur en pixels du texte)
|
shl cx, 3 ; CX * 8 (largeur en pixels du texte)
|
||||||
|
|
||||||
mov ax, [si + widget.w]
|
mov ax, [gs:si + widget.w]
|
||||||
sub ax, cx ; Marge horizontale totale
|
sub ax, cx ; Marge horizontale totale
|
||||||
shr ax, 1 ; Diviser par 2
|
shr ax, 1 ; Diviser par 2
|
||||||
add ax, [si + widget.x] ; X final
|
add ax, [gs:si + widget.x] ; X final
|
||||||
|
|
||||||
mov bx, [si + widget.h]
|
mov bx, [gs:si + widget.h]
|
||||||
sub bx, 8 ; Hauteur fonte (8px)
|
sub bx, 8 ; Hauteur fonte (8px)
|
||||||
shr bx, 1 ; Diviser par 2
|
shr bx, 1 ; Diviser par 2
|
||||||
add bx, [si + widget.y] ; Y final
|
add bx, [gs:si + widget.y] ; Y final
|
||||||
|
|
||||||
; 2. Dessiner
|
; 2. Dessiner
|
||||||
GFX GOTOXY, ax, bx
|
GFX GOTOXY, ax, bx
|
||||||
|
|
||||||
mov dx, [si + widget.text_seg]
|
mov dx, [gs:si + widget.text_seg]
|
||||||
mov ax, [si + widget.text_ofs]
|
mov ax, [gs:si + widget.text_ofs]
|
||||||
GFX WRITE, dx, ax
|
GFX WRITE, dx, ax
|
||||||
|
|
||||||
pop si
|
pop si
|
||||||
|
|
@ -482,27 +517,27 @@ gui_update_button:
|
||||||
xor ax, ax ; AL = Return value (0)
|
xor ax, ax ; AL = Return value (0)
|
||||||
|
|
||||||
; Si désactivé, on ne fait rien
|
; Si désactivé, on ne fait rien
|
||||||
cmp byte [si + widget.state], GUI_STATE_DISABLED
|
cmp byte [gs:si + widget.state], GUI_STATE_DISABLED
|
||||||
je .quit
|
je .quit
|
||||||
|
|
||||||
; 1. Test de collision (Hit Test)
|
; 1. Test de collision (Hit Test)
|
||||||
; X >= Widget.X ?
|
; X >= Widget.X ?
|
||||||
cmp cx, [si + widget.x]
|
cmp cx, [gs:si + widget.x]
|
||||||
jl .no_hit
|
jl .no_hit
|
||||||
|
|
||||||
; X <= Widget.X + Widget.W ?
|
; X <= Widget.X + Widget.W ?
|
||||||
mov di, [si + widget.x]
|
mov di, [gs:si + widget.x]
|
||||||
add di, [si + widget.w]
|
add di, [gs:si + widget.w]
|
||||||
cmp cx, di
|
cmp cx, di
|
||||||
jg .no_hit
|
jg .no_hit
|
||||||
|
|
||||||
; Y >= Widget.Y ?
|
; Y >= Widget.Y ?
|
||||||
cmp dx, [si + widget.y]
|
cmp dx, [gs:si + widget.y]
|
||||||
jl .no_hit
|
jl .no_hit
|
||||||
|
|
||||||
; Y <= Widget.Y + Widget.H ?
|
; Y <= Widget.Y + Widget.H ?
|
||||||
mov di, [si + widget.y]
|
mov di, [gs:si + widget.y]
|
||||||
add di, [si + widget.h]
|
add di, [gs:si + widget.h]
|
||||||
cmp dx, di
|
cmp dx, di
|
||||||
jg .no_hit
|
jg .no_hit
|
||||||
|
|
||||||
|
|
@ -513,27 +548,27 @@ gui_update_button:
|
||||||
jz .hovering
|
jz .hovering
|
||||||
|
|
||||||
; -> Clic maintenu
|
; -> Clic maintenu
|
||||||
mov byte [si + widget.state], GUI_STATE_PRESSED
|
mov byte [gs:si + widget.state], GUI_STATE_PRESSED
|
||||||
jmp .draw_update
|
jmp .draw_update
|
||||||
|
|
||||||
.hovering:
|
.hovering:
|
||||||
; Souris dessus, mais pas de clic
|
; Souris dessus, mais pas de clic
|
||||||
; Si on était en PRESSED juste avant, c'est un "CLICK" valide (Relâchement)
|
; Si on était en PRESSED juste avant, c'est un "CLICK" valide (Relâchement)
|
||||||
cmp byte [si + widget.state], GUI_STATE_PRESSED
|
cmp byte [gs:si + widget.state], GUI_STATE_PRESSED
|
||||||
jne .just_hover
|
jne .just_hover
|
||||||
|
|
||||||
; C'est un click valide !
|
; C'est un click valide !
|
||||||
mov al, 1 ; Return CLICKED
|
mov al, 1 ; Return CLICKED
|
||||||
mov byte [si + widget.state], GUI_STATE_HOVER
|
mov byte [gs:si + widget.state], GUI_STATE_HOVER
|
||||||
jmp .draw_update
|
jmp .draw_update
|
||||||
|
|
||||||
.just_hover:
|
.just_hover:
|
||||||
mov byte [si + widget.state], GUI_STATE_HOVER
|
mov byte [gs:si + widget.state], GUI_STATE_HOVER
|
||||||
jmp .draw_update
|
jmp .draw_update
|
||||||
|
|
||||||
.no_hit:
|
.no_hit:
|
||||||
; Souris en dehors
|
; Souris en dehors
|
||||||
mov byte [si + widget.state], GUI_STATE_NORMAL
|
mov byte [gs:si + widget.state], GUI_STATE_NORMAL
|
||||||
|
|
||||||
.draw_update:
|
.draw_update:
|
||||||
; Appelle la fonction de dessin pour mettre à jour le visuel
|
; Appelle la fonction de dessin pour mettre à jour le visuel
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue