widget + Event control
This commit is contained in:
parent
2555203968
commit
259dc3697d
7 changed files with 694 additions and 292 deletions
|
|
@ -1,209 +0,0 @@
|
||||||
; Compilation: nasm -f bin bios.asm -o bios.bin
|
|
||||||
; Taille: 64 KB
|
|
||||||
|
|
||||||
BITS 16
|
|
||||||
|
|
||||||
section .text
|
|
||||||
org 0x0000
|
|
||||||
|
|
||||||
%define BIOS_DATA_SEG 0x0050
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------
|
|
||||||
; POINT D'ENTRÉE DU BIOS (Cible du jump du reset vector)
|
|
||||||
; ------------------------------------------------------------------
|
|
||||||
start:
|
|
||||||
cli
|
|
||||||
cld
|
|
||||||
xor ax, ax
|
|
||||||
mov ds, ax
|
|
||||||
mov es, ax
|
|
||||||
mov ss, ax
|
|
||||||
mov sp, 0x7000
|
|
||||||
|
|
||||||
; Créer une table "cohérente" de handler
|
|
||||||
call setup_ivt
|
|
||||||
|
|
||||||
; Initialisation du PIC (Indispensable pour IRQ0/IRQ1)
|
|
||||||
mov al, 0x11
|
|
||||||
out 0x20, al
|
|
||||||
out 0xA0, al
|
|
||||||
mov al, 0x08 ; IRQ0-7 -> INT 08h-0Fh
|
|
||||||
out 0x21, al
|
|
||||||
mov al, 0x70 ; IRQ8-15 -> INT 70h-77h
|
|
||||||
out 0xA1, al
|
|
||||||
|
|
||||||
mov al, 0x04
|
|
||||||
out 0x21, al
|
|
||||||
mov al, 0x02
|
|
||||||
out 0xA1, al
|
|
||||||
|
|
||||||
mov al, 0x01
|
|
||||||
out 0x21, al
|
|
||||||
out 0xA1, al
|
|
||||||
|
|
||||||
; Scan et Initialisation des options ROMS (VGA BIOS, etc)
|
|
||||||
call setup_load_rom
|
|
||||||
|
|
||||||
; initialise l'écran en mode texte
|
|
||||||
mov ax,0x0003
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
; Installation des ISR
|
|
||||||
mov word [0x08*4], timer_isr
|
|
||||||
mov word [0x08*4+2], 0xF000
|
|
||||||
|
|
||||||
mov word [0x09*4], keyboard_isr
|
|
||||||
mov word [0x09*4+2], 0xF000
|
|
||||||
|
|
||||||
; Démasquer IRQ0 et IRQ1
|
|
||||||
mov al, 0xFC
|
|
||||||
out 0x21, al
|
|
||||||
sti
|
|
||||||
|
|
||||||
mov ax, BIOS_DATA_SEG
|
|
||||||
mov es, ax
|
|
||||||
mov di, 0x0 ; Adresse physique de tes variables
|
|
||||||
mov cx, 4
|
|
||||||
xor ax,ax
|
|
||||||
rep stosb ; Met 4 octets à zéro
|
|
||||||
|
|
||||||
main_loop:
|
|
||||||
mov ax,BIOS_DATA_SEG
|
|
||||||
mov fs,ax
|
|
||||||
|
|
||||||
mov al, [fs:0x00] ; Timer
|
|
||||||
mov di, 0
|
|
||||||
call draw_hex_byte
|
|
||||||
|
|
||||||
mov al, [fs:0x01] ; Clavier
|
|
||||||
mov di, 6
|
|
||||||
call draw_hex_byte
|
|
||||||
|
|
||||||
mov al, [fs:0x02] ; Clavier
|
|
||||||
mov di, 12
|
|
||||||
call draw_hex_byte
|
|
||||||
|
|
||||||
jmp main_loop
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------
|
|
||||||
; HANDLERS & HELPERS
|
|
||||||
; ------------------------------------------------------------------
|
|
||||||
default_isr:
|
|
||||||
iret
|
|
||||||
|
|
||||||
|
|
||||||
timer_isr:
|
|
||||||
push ax
|
|
||||||
push gs
|
|
||||||
|
|
||||||
mov ax, BIOS_DATA_SEG
|
|
||||||
mov gs, ax
|
|
||||||
|
|
||||||
inc byte [gs:0x00]
|
|
||||||
|
|
||||||
mov al, 0x20
|
|
||||||
out 0x20, al
|
|
||||||
|
|
||||||
pop gs
|
|
||||||
pop ax
|
|
||||||
iret
|
|
||||||
|
|
||||||
keyboard_isr:
|
|
||||||
push ax
|
|
||||||
push gs
|
|
||||||
|
|
||||||
mov ax, BIOS_DATA_SEG
|
|
||||||
mov gs, ax
|
|
||||||
|
|
||||||
in al, 0x60 ; Ack clavier
|
|
||||||
mov byte [gs:0x02],al
|
|
||||||
|
|
||||||
inc byte [gs:0x01]
|
|
||||||
|
|
||||||
mov al, 0x20
|
|
||||||
out 0x20, al
|
|
||||||
|
|
||||||
pop gs
|
|
||||||
pop ax
|
|
||||||
iret
|
|
||||||
|
|
||||||
draw_hex_byte:
|
|
||||||
push ax
|
|
||||||
|
|
||||||
mov bx, 0xb800
|
|
||||||
mov es,bx
|
|
||||||
|
|
||||||
shr al, 4
|
|
||||||
call .draw_nibble
|
|
||||||
pop ax
|
|
||||||
; add di, 2
|
|
||||||
|
|
||||||
.draw_nibble:
|
|
||||||
and al, 0x0F
|
|
||||||
add al, '0'
|
|
||||||
cmp al, '9'
|
|
||||||
jbe .print
|
|
||||||
add al, 7
|
|
||||||
.print:
|
|
||||||
mov ah, 0x0F ; Blanc sur Noir
|
|
||||||
stosw
|
|
||||||
ret
|
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------
|
|
||||||
; construire une table "vide" de pointeur ISR
|
|
||||||
; ----------------------------------------------------------------------------
|
|
||||||
setup_ivt:
|
|
||||||
; installation de la table d'interrupts
|
|
||||||
xor ax, ax
|
|
||||||
mov es, ax ; ES = 0000h -> base IVT
|
|
||||||
xor di, di ; DI = 0000h -> offset IVT
|
|
||||||
|
|
||||||
mov ax, default_isr ; offset du handler
|
|
||||||
mov dx, cs ; segment du handler (ROM)
|
|
||||||
|
|
||||||
mov cx, 256 ; 256 vecteurs
|
|
||||||
.fill:
|
|
||||||
stosw ; write offset (AX) -> [ES:DI], DI += 2
|
|
||||||
xchg ax, dx ; AX = segment, DX = offset
|
|
||||||
stosw ; write segment (AX) -> [ES:DI], DI += 2
|
|
||||||
xchg ax, dx ; AX = offset, DX = segment
|
|
||||||
loop .fill
|
|
||||||
; fin de la table d'interrupt
|
|
||||||
ret
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
|
||||||
; Détection les ROM supplementaires
|
|
||||||
; Teste la RAM de 0xC000 jusqu’à 0xE000, par pas de 2KB.
|
|
||||||
;
|
|
||||||
; Si une ROM est détectée, le code de la ROM sera appelé.
|
|
||||||
; ---------------------------------------------------------------------------
|
|
||||||
setup_load_rom:
|
|
||||||
mov bx, 0xC000
|
|
||||||
.scanloop:
|
|
||||||
mov gs, bx
|
|
||||||
cmp word[gs:0x0000],0xAA55 ; ROM signature
|
|
||||||
jne .nextblock
|
|
||||||
|
|
||||||
; appel le code (en 0x0003) de la ROM
|
|
||||||
push cs
|
|
||||||
push word .nextblock ; address de retour
|
|
||||||
|
|
||||||
push bx ; segment
|
|
||||||
push 0x0003 ; offset entry rom
|
|
||||||
retf ; call far ds:0x0003
|
|
||||||
.nextblock:
|
|
||||||
add bx, 0x80 ; add 2kb
|
|
||||||
cmp bx, 0xE000
|
|
||||||
jbe .scanloop
|
|
||||||
ret
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------
|
|
||||||
; Padding jusqu'au reset vector
|
|
||||||
; ------------------------------------------------------------------
|
|
||||||
times 0xFFF0 - ($ - $$) db 0xFF
|
|
||||||
|
|
||||||
|
|
||||||
reset_vector:
|
|
||||||
jmp 0xF000:start
|
|
||||||
db '06/01/2026'
|
|
||||||
db 0 ; le stub tient dans 16 octets (ou moins)
|
|
||||||
62
src/boot.asm
62
src/boot.asm
|
|
@ -26,7 +26,6 @@
|
||||||
; configuration du bios
|
; configuration du bios
|
||||||
;
|
;
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
%define DEBUG_PORT 0xe9 ; 0x402 ou 0xe9
|
|
||||||
|
|
||||||
; initial stack
|
; initial stack
|
||||||
%define STACK_SEG 0x0800 ; segment de base
|
%define STACK_SEG 0x0800 ; segment de base
|
||||||
|
|
@ -45,25 +44,15 @@ section .text
|
||||||
%include "./common/cursor.asm"
|
%include "./common/cursor.asm"
|
||||||
|
|
||||||
; definition du BDA
|
; definition du BDA
|
||||||
%include "./bda.asm"
|
%include "./common/bda.asm"
|
||||||
|
|
||||||
; %include "./services/macros.asm"
|
|
||||||
%include "./common/debug_cga.asm"
|
%include "./common/debug_cga.asm"
|
||||||
%include "./drivers/gfx_cgam.asm"
|
%include "./drivers/gfx_cgam.asm"
|
||||||
|
%include "./services/gui_lib.asm"
|
||||||
%include "./drivers/mouse_ps2.asm"
|
%include "./drivers/mouse_ps2.asm"
|
||||||
%include "./drivers/keyboard_ps2.asm"
|
%include "./drivers/keyboard_ps2.asm"
|
||||||
%include "./services/generic.asm"
|
%include "./services/generic.asm"
|
||||||
%include "./services/gui_window.asm"
|
; %include "./services/gui_window.asm"
|
||||||
|
|
||||||
err_vganok db 'VGA Not Initialized',0
|
|
||||||
|
|
||||||
cpt_txt db '0123456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789',0
|
|
||||||
helloworld db 'Hello World !',0
|
|
||||||
|
|
||||||
W_T db '1 - TEXT WHITE - TRANSPARENT',0
|
|
||||||
B_T db '2 - TEXT BLACK - TRANSPARENT',0
|
|
||||||
W_B db '3 - TEXT WHITE - ON BLACK',0
|
|
||||||
B_W db '4 - TEXT BLACK - ON WHITE',0
|
|
||||||
|
|
||||||
reset:
|
reset:
|
||||||
cli
|
cli
|
||||||
|
|
@ -111,7 +100,12 @@ reset:
|
||||||
push cs
|
push cs
|
||||||
pop ds
|
pop ds
|
||||||
|
|
||||||
GUI WINDOW, 50,50,250,100,helloworld
|
setup_gui:
|
||||||
|
; Initialiser le segment de données correct pour le texte du bouton
|
||||||
|
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_DRAW, 50,50,250,100,0
|
; GFX RECTANGLE_DRAW, 50,50,250,100,0
|
||||||
|
|
||||||
|
|
@ -126,6 +120,25 @@ reset:
|
||||||
mov ax,BDA_DATA_SEG
|
mov ax,BDA_DATA_SEG
|
||||||
mov ds,ax
|
mov ds,ax
|
||||||
endless:
|
endless:
|
||||||
|
|
||||||
|
; 1. Récupérer souris
|
||||||
|
mov ax, [BDA_MOUSE + mouse.x]
|
||||||
|
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
|
||||||
|
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)
|
||||||
|
cmp al, 1
|
||||||
|
je action_quitter
|
||||||
|
|
||||||
|
; 4. Afficher le curseur souris (Important : après avoir dessiné le bouton)
|
||||||
|
; GFX MOUSE_MOVE
|
||||||
|
|
||||||
GFX TXT_MODE, GFX_TXT_BLACK
|
GFX TXT_MODE, GFX_TXT_BLACK
|
||||||
GFX GOTOXY, 0, 180
|
GFX GOTOXY, 0, 180
|
||||||
|
|
||||||
|
|
@ -139,6 +152,10 @@ endless:
|
||||||
|
|
||||||
jmp endless
|
jmp endless
|
||||||
|
|
||||||
|
action_quitter:
|
||||||
|
hlt
|
||||||
|
jmp action_quitter
|
||||||
|
|
||||||
|
|
||||||
; -----------------------------------------------------------
|
; -----------------------------------------------------------
|
||||||
; timer ISR (IRQ -> INT)
|
; timer ISR (IRQ -> INT)
|
||||||
|
|
@ -158,6 +175,21 @@ 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
|
||||||
; ------------------------------------------------------------------
|
; ------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
; https://wiki.nox-rhea.org/back2root/ibm-pc-ms-dos/hardware/informations/bios_data_area
|
; https://wiki.nox-rhea.org/back2root/ibm-pc-ms-dos/hardware/informations/bios_data_area
|
||||||
;
|
;
|
||||||
|
|
||||||
%define BDA_SEGMENT 0x0040 ; segment BDA
|
%define BDA_SEGMENT 0x0040 ; segment BDA
|
||||||
|
|
||||||
; custom vars
|
; custom vars
|
||||||
%define BDA_INFO_MEM_SIZE 0x0014 ; Memory size in Kbytes
|
%define BDA_INFO_MEM_SIZE 0x0014 ; Memory size in Kbytes
|
||||||
|
|
@ -46,34 +46,33 @@
|
||||||
%define BKG_TOTAL_BYTES (BKG_TOTAL_DWORDS * 4) ; 64
|
%define BKG_TOTAL_BYTES (BKG_TOTAL_DWORDS * 4) ; 64
|
||||||
|
|
||||||
struc mouse
|
struc mouse
|
||||||
.buffer resb 4 ; i8042 input buffer
|
.buffer resb 4 ; i8042 input buffer
|
||||||
.idx resb 1 ; index in the buffer
|
.idx resb 1 ; index in the buffer
|
||||||
.packetlen resb 1 ; max buffer len (3 ou 4)
|
.packetlen resb 1 ; max buffer len (3 ou 4)
|
||||||
.status resb 1 ; mouse status (button etc)
|
.status resb 1 ; mouse status (button etc)
|
||||||
.wheel resb 1 ; if a packet size is 4; experimental
|
.wheel resb 1 ; if a packet size is 4; experimental
|
||||||
.x resw 1 ;
|
.x resw 1 ;
|
||||||
.y resw 1 ;
|
.y resw 1 ;
|
||||||
; cursor management
|
; cursor management
|
||||||
.cur_x resw 1 ; preservation des x,y du background
|
.cur_x resw 1 ; preservation des x,y du background
|
||||||
.cur_y resw 1 ;
|
.cur_y resw 1 ;
|
||||||
.cur_addr_start resw 1 ; adresse de départ de la sauvegarde
|
.cur_addr_start resw 1 ; adresse de départ de la sauvegarde
|
||||||
|
.cur_drawing resb 1 ;
|
||||||
.cur_drawing resb 1 ;
|
.cur_counter resb 1 ; compteur de fois que le curseur a été caché (0 = visible, <0 = invisible)
|
||||||
.cur_counter resb 1 ; compteur de fois que le curseur a été caché (0 = visible, <0 = invisible)
|
.cur_seg resw 1 ; segment / offset of the pointer
|
||||||
.cur_seg resw 1 ; segment / offset of the pointer
|
.cur_ofs resw 1 ;
|
||||||
.cur_ofs resw 1 ;
|
.bkg_saved resb 1 ; background saved
|
||||||
.bkg_saved resb 1 ; background saved
|
alignb 4 ; alignement 4 bytes
|
||||||
alignb 4 ; alignement 4 bytes
|
.bkg_buffer resd 16 ; buffer for saved background
|
||||||
.bkg_buffer resd 16 ; buffer for saved background
|
|
||||||
endstruc
|
endstruc
|
||||||
|
|
||||||
struc gfx
|
struc gfx
|
||||||
.cur_x resw 1 ; x,y en pixel
|
.cur_x resw 1 ; x,y en pixel
|
||||||
.cur_y resw 1
|
.cur_y resw 1
|
||||||
.cur_offset resw 1 ; offset calculé pour le prochain caractère
|
.cur_offset resw 1 ; offset calculé pour le prochain caractère
|
||||||
.cur_line_ofs resw 1 ; "interligne" +2000h ou -2000h
|
.cur_line_ofs resw 1 ; "interligne" +2000h ou -2000h
|
||||||
.cur_shift resb 1 ; x&7 (0..7)
|
.cur_shift resb 1 ; x&7 (0..7)
|
||||||
.cur_mode resb 1 ;
|
.cur_mode resb 1 ;
|
||||||
endstruc
|
endstruc
|
||||||
|
|
||||||
%define BDA_MOUSE 0x0000
|
%define BDA_MOUSE 0x0000
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
;
|
;
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
|
%define DEBUG_PORT 0xe9 ; 0x402 ou 0xe9
|
||||||
|
|
||||||
debug_puts:
|
debug_puts:
|
||||||
.next:
|
.next:
|
||||||
|
|
|
||||||
|
|
@ -215,8 +215,8 @@ cga_set_charpos:
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
|
|
||||||
; --- Définition des arguments ---
|
; --- Définition des arguments ---
|
||||||
%define .x word [bp+4]
|
%define .x word [bp+4]
|
||||||
%define .y word [bp+6]
|
%define .y word [bp+6]
|
||||||
|
|
||||||
pusha
|
pusha
|
||||||
push fs
|
push fs
|
||||||
|
|
@ -260,6 +260,10 @@ cga_set_charpos:
|
||||||
mov [fs:BDA_GFX + gfx.cur_offset], bx
|
mov [fs:BDA_GFX + gfx.cur_offset], bx
|
||||||
|
|
||||||
pop fs
|
pop fs
|
||||||
|
|
||||||
|
; clean defs
|
||||||
|
%undef .x
|
||||||
|
%undef .y
|
||||||
popa
|
popa
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
@ -460,6 +464,11 @@ cga_putpixel:
|
||||||
and byte [es:di], ah
|
and byte [es:di], ah
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
|
|
||||||
|
; clean defs
|
||||||
|
%undef .x
|
||||||
|
%undef .y
|
||||||
|
%undef .color
|
||||||
popa
|
popa
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
@ -491,6 +500,10 @@ cga_getpixel:
|
||||||
|
|
||||||
pop es
|
pop es
|
||||||
pop di
|
pop di
|
||||||
|
|
||||||
|
; clean defs
|
||||||
|
%undef .x
|
||||||
|
%undef .y
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
@ -592,6 +605,12 @@ cga_line_vertical:
|
||||||
call cga_mouse_show
|
call cga_mouse_show
|
||||||
|
|
||||||
pop es
|
pop es
|
||||||
|
|
||||||
|
; clean defs
|
||||||
|
%undef .x
|
||||||
|
%undef .y1
|
||||||
|
%undef .y2
|
||||||
|
%undef .color
|
||||||
popa
|
popa
|
||||||
leave ; Leave gère le 'mov sp, bp / pop bp'
|
leave ; Leave gère le 'mov sp, bp / pop bp'
|
||||||
ret
|
ret
|
||||||
|
|
@ -735,6 +754,11 @@ cga_line_horizontal:
|
||||||
.done:
|
.done:
|
||||||
call cga_mouse_show
|
call cga_mouse_show
|
||||||
pop es
|
pop es
|
||||||
|
|
||||||
|
; clean defs
|
||||||
|
%undef .x1
|
||||||
|
%undef .x2
|
||||||
|
%undef .y
|
||||||
popa
|
popa
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
@ -787,6 +811,10 @@ cga_draw_rect:
|
||||||
GFX LINE_VERT, .x1, .y1, .y2, .color
|
GFX LINE_VERT, .x1, .y1, .y2, .color
|
||||||
GFX LINE_VERT, .x2, .y1, .y2, .color
|
GFX LINE_VERT, .x2, .y1, .y2, .color
|
||||||
|
|
||||||
|
; clean defs
|
||||||
|
%undef .x1
|
||||||
|
%undef .y1
|
||||||
|
%undef .x2
|
||||||
popa
|
popa
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
@ -938,6 +966,11 @@ cga_fill_rect:
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
546
src/services/gui_lib.asm
Normal file
546
src/services/gui_lib.asm
Normal file
|
|
@ -0,0 +1,546 @@
|
||||||
|
; =============================================================================
|
||||||
|
; Project : Custom BIOS / ROM
|
||||||
|
; File : gui_lib.asm
|
||||||
|
; Author : frater
|
||||||
|
;
|
||||||
|
; License : GNU General Public License v3.0 or later (GPL-3.0+)
|
||||||
|
;
|
||||||
|
; This program is free software: you can redistribute it and/or modify
|
||||||
|
; it under the terms of the GNU General Public License as published by
|
||||||
|
; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
; (at your option) any later version.
|
||||||
|
;
|
||||||
|
; This program is distributed in the hope that it will be useful,
|
||||||
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
; GNU General Public License for more details.
|
||||||
|
;
|
||||||
|
; You should have received a copy of the GNU General Public License
|
||||||
|
; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
;
|
||||||
|
; =============================================================================
|
||||||
|
|
||||||
|
; --- Configuration Mémoire ---
|
||||||
|
%define GUI_RAM_SEG 0x0800 ; Segment de données UI
|
||||||
|
%define GUI_MAX_WIDGETS 32 ; Nombre max de widgets simultanés
|
||||||
|
|
||||||
|
; --- Drapeaux & États ---
|
||||||
|
%define GUI_STATE_FREE 0 ; Le slot est vide (mémoire dispo)
|
||||||
|
%define GUI_STATE_NORMAL 1 ; Affiché, repos
|
||||||
|
%define GUI_STATE_HOVER 2 ; Souris dessus
|
||||||
|
%define GUI_STATE_PRESSED 3 ; Clic enfoncé
|
||||||
|
%define GUI_STATE_DISABLED 4 ; Grisé
|
||||||
|
|
||||||
|
; --- Structure d'un OBJET (Bouton, etc) ---
|
||||||
|
struc widget
|
||||||
|
.state resb 1 ; État (0=libre, >0=utilisé)
|
||||||
|
.user_id resb 1 ; ID unique utilisateur
|
||||||
|
.x resw 1 ; Position X
|
||||||
|
.y resw 1 ; Position Y
|
||||||
|
.w resw 1 ; Largeur
|
||||||
|
.h resw 1 ; Hauteur
|
||||||
|
.state resb 1 ; État (0=Normal, 1=Hover, 2=Pressed, 3=Disabled)
|
||||||
|
.text_ofs resw 1 ; Offset du texte
|
||||||
|
.text_seg resw 1 ; Segment du texte
|
||||||
|
.event_click resw 1 ; adresse de la fonction "on click"
|
||||||
|
; .event_hover resw 1 ; adresse de la fonction "on hover"
|
||||||
|
; .event_release resw 1 ; adresse de la fonction "on release"
|
||||||
|
; .event_disable resw 1 ; adresse de la fonction "on disable"
|
||||||
|
; .event_enable resw 1 ; adresse de la fonction "on enable"
|
||||||
|
alignb 2 ; Alignement mémoire pour performance
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
; =============================================================================
|
||||||
|
; SECTION : GESTION MÉMOIRE (ALLOCATION / LIBÉRATION)
|
||||||
|
; =============================================================================
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
; gui_init_system
|
||||||
|
; Initialise toute la mémoire des widgets à 0 (Libre)
|
||||||
|
; Entrée : DS doit pointer vers GUI_RAM_SEG
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
gui_init_system:
|
||||||
|
pushad
|
||||||
|
push ds
|
||||||
|
|
||||||
|
mov ax, GUI_RAM_SEG
|
||||||
|
mov ds, ax
|
||||||
|
|
||||||
|
mov di, 0 ; On commence au début du segment 0x0800
|
||||||
|
mov cx, (widget_size * GUI_MAX_WIDGETS)
|
||||||
|
shl cx, 2 ; cx / 4
|
||||||
|
xor eax, eax
|
||||||
|
rep stosd ; Remplit tout de 0
|
||||||
|
|
||||||
|
pop ds
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
; gui_alloc_widget
|
||||||
|
; Cherche un slot vide et retourne son adresse
|
||||||
|
; Sortie :
|
||||||
|
; - Succès : CF=0 (Carry Clear), SI = Offset du widget
|
||||||
|
; - Echec : CF=1 (Carry Set), SI = Indéfini (ou 0)
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
gui_alloc_widget:
|
||||||
|
push cx
|
||||||
|
push bx
|
||||||
|
push ds
|
||||||
|
|
||||||
|
mov ax, GUI_RAM_SEG
|
||||||
|
mov ds, ax
|
||||||
|
|
||||||
|
mov si, 0 ; Début du pool
|
||||||
|
mov cx, GUI_MAX_WIDGETS
|
||||||
|
|
||||||
|
.loop_find:
|
||||||
|
cmp byte [si + widget.state], GUI_STATE_FREE
|
||||||
|
je .found ; Si state == 0, c'est libre !
|
||||||
|
|
||||||
|
add si, widget_size ; Sinon on passe au suivant
|
||||||
|
loop .loop_find
|
||||||
|
|
||||||
|
; Pas trouvé (Plein)
|
||||||
|
stc ; set Carry Flag : erreur
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.found:
|
||||||
|
; On initialise le slot trouvé
|
||||||
|
mov byte [si + widget.state], GUI_STATE_NORMAL ; Marquer comme occupé
|
||||||
|
|
||||||
|
; Reset des champs critiques pour éviter les déchets
|
||||||
|
mov word [si + widget.callback], 0
|
||||||
|
|
||||||
|
clc ; Clear Carry Flag
|
||||||
|
.done:
|
||||||
|
pop ds
|
||||||
|
pop bx
|
||||||
|
pop cx
|
||||||
|
ret
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
; gui_free_widget
|
||||||
|
; Libère un widget
|
||||||
|
; Entrée : SI = Pointeur widget
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
gui_free_widget:
|
||||||
|
mov byte [si + widget.state], GUI_STATE_FREE
|
||||||
|
; On efface visuellement le widget (optionnel, remplit de blanc)
|
||||||
|
; Pour l'instant on le marque juste libre, il sera redessiné par-dessus.
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; =============================================================================
|
||||||
|
; SECTION : MOTEUR D'ÉVÉNEMENTS (EVENT LOOP)
|
||||||
|
; =============================================================================
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
; gui_process_all
|
||||||
|
; 1. Redessine tous les widgets actifs
|
||||||
|
; 2. Vérifie les clics et appelle les callbacks
|
||||||
|
; Entrée :
|
||||||
|
; CX = Mouse X
|
||||||
|
; DX = Mouse Y
|
||||||
|
; BL = Mouse Buttons
|
||||||
|
; -----------------------------------------------------------------------------
|
||||||
|
gui_process_all:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
mov si, 0 ; Pointeur début tableau
|
||||||
|
mov di, GUI_MAX_WIDGETS ; Compteur
|
||||||
|
|
||||||
|
.loop_widgets:
|
||||||
|
; Est-ce que ce slot est occupé ?
|
||||||
|
cmp byte [si + widget.state], GUI_STATE_FREE
|
||||||
|
je .next_widget
|
||||||
|
|
||||||
|
; --- Logique Widget ---
|
||||||
|
push bx ; Sauver état boutons souris
|
||||||
|
call gui_update_logic ; Vérifier collision/clic
|
||||||
|
|
||||||
|
; Si AL=1 (Clic relâché validé), exécuter le callback
|
||||||
|
cmp al, 1
|
||||||
|
jne .no_action
|
||||||
|
|
||||||
|
; Vérifier si un callback est défini
|
||||||
|
cmp word [si + widget.callback], 0
|
||||||
|
je .no_action
|
||||||
|
|
||||||
|
; APPEL DU CALLBACK (Fonction utilisateur)
|
||||||
|
; On sauve les registres car le callback peut faire n'importe quoi
|
||||||
|
pusha
|
||||||
|
call word [si + widget.callback]
|
||||||
|
popa
|
||||||
|
|
||||||
|
.no_action:
|
||||||
|
pop bx ; Restaurer boutons
|
||||||
|
|
||||||
|
; Dessiner (si l'état a changé ou pour refresh)
|
||||||
|
call gui_draw_single_widget
|
||||||
|
|
||||||
|
.next_widget:
|
||||||
|
add si, widget_size
|
||||||
|
dec di
|
||||||
|
jnz .loop_widgets
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
; =============================================================================
|
||||||
|
; SECTION : LOGIQUE INTERNE ET DESSIN
|
||||||
|
; =============================================================================
|
||||||
|
|
||||||
|
; (Interne) Met à jour l'état d'un seul widget
|
||||||
|
; Entrée : SI=Widget, CX=MouseX, DX=MouseY, BL=Buttons
|
||||||
|
; Sortie : AL=1 si Clicked, 0 sinon. Met à jour [SI].state
|
||||||
|
gui_update_logic:
|
||||||
|
xor ax, ax
|
||||||
|
|
||||||
|
cmp byte [si + widget.state], GUI_STATE_DISABLED
|
||||||
|
je .done
|
||||||
|
|
||||||
|
; --- Hit Test ---
|
||||||
|
cmp cx, [si + widget.x]
|
||||||
|
jl .miss
|
||||||
|
mov bp, [si + widget.x]
|
||||||
|
add bp, [si + widget.w]
|
||||||
|
cmp cx, bp
|
||||||
|
jg .miss
|
||||||
|
|
||||||
|
cmp dx, [si + widget.y]
|
||||||
|
jl .miss
|
||||||
|
mov bp, [si + widget.y]
|
||||||
|
add bp, [si + widget.h]
|
||||||
|
cmp dx, bp
|
||||||
|
jg .miss
|
||||||
|
|
||||||
|
; --- Hit: Souris sur le widget ---
|
||||||
|
test bl, 1 ; Clic gauche ?
|
||||||
|
jz .released
|
||||||
|
|
||||||
|
; Clic enfoncé
|
||||||
|
mov byte [si + widget.state], GUI_STATE_PRESSED
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.released:
|
||||||
|
; Bouton relâché. Était-il pressé avant ?
|
||||||
|
cmp byte [si + widget.state], GUI_STATE_PRESSED
|
||||||
|
jne .hover
|
||||||
|
|
||||||
|
; Clic validé !
|
||||||
|
mov al, 1
|
||||||
|
mov byte [si + widget.state], GUI_STATE_HOVER
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.hover:
|
||||||
|
mov byte [si + widget.state], GUI_STATE_HOVER
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.miss:
|
||||||
|
mov byte [si + widget.state], GUI_STATE_NORMAL
|
||||||
|
.done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
; (Interne) Dessine le widget pointé par SI
|
||||||
|
gui_draw_single_widget:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
; Chargement coords
|
||||||
|
mov ax, [si + widget.x]
|
||||||
|
mov bx, [si + widget.y]
|
||||||
|
mov cx, [si + widget.w]
|
||||||
|
mov dx, [si + widget.h]
|
||||||
|
|
||||||
|
; Calcul X2, Y2
|
||||||
|
mov di, ax
|
||||||
|
add di, cx
|
||||||
|
mov bp, bx
|
||||||
|
add bp, dx
|
||||||
|
|
||||||
|
; Dispatch selon état
|
||||||
|
mov al, [si + widget.state]
|
||||||
|
cmp al, GUI_STATE_PRESSED
|
||||||
|
je .paint_pressed
|
||||||
|
cmp al, GUI_STATE_HOVER
|
||||||
|
je .paint_hover
|
||||||
|
|
||||||
|
.paint_normal:
|
||||||
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 1 ; Blanc
|
||||||
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0 ; Bord Noir
|
||||||
|
GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT
|
||||||
|
jmp .text
|
||||||
|
|
||||||
|
.paint_hover:
|
||||||
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 1
|
||||||
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
||||||
|
; Effet gras
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
dec di
|
||||||
|
dec bp
|
||||||
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
||||||
|
|
||||||
|
; Restauration coords pour le texte
|
||||||
|
mov ax, [si + widget.x]
|
||||||
|
mov bx, [si + widget.y]
|
||||||
|
jmp .text_setup
|
||||||
|
|
||||||
|
.paint_pressed:
|
||||||
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 0 ; Noir
|
||||||
|
GFX TXT_MODE, GFX_TXT_WHITE_TRANSPARENT
|
||||||
|
jmp .text
|
||||||
|
|
||||||
|
.text_setup:
|
||||||
|
; Petit hack pour recentrer le texte après l'effet gras
|
||||||
|
mov cx, [si + widget.w]
|
||||||
|
mov dx, [si + widget.h]
|
||||||
|
|
||||||
|
.text:
|
||||||
|
; --- Centrage Texte (Simplifié) ---
|
||||||
|
push si
|
||||||
|
mov es, [si + widget.text_seg]
|
||||||
|
mov di, [si + widget.text_ofs]
|
||||||
|
xor cx, cx
|
||||||
|
.strlen:
|
||||||
|
cmp byte [es:di], 0
|
||||||
|
je .calc
|
||||||
|
inc cx
|
||||||
|
inc di
|
||||||
|
jmp .strlen
|
||||||
|
.calc:
|
||||||
|
shl cx, 3 ; Largeur texte px
|
||||||
|
push ax ; Sauve X original
|
||||||
|
mov ax, [si + widget.w]
|
||||||
|
sub ax, cx
|
||||||
|
shr ax, 1
|
||||||
|
pop bx ; Récupère X original dans BX (oups, on veut ajouter)
|
||||||
|
add ax, bx ; X final
|
||||||
|
|
||||||
|
push ax ; X final prêt
|
||||||
|
|
||||||
|
mov bx, [si + widget.h]
|
||||||
|
sub bx, 8
|
||||||
|
shr bx, 1
|
||||||
|
add bx, [si + widget.y] ; Y final
|
||||||
|
|
||||||
|
pop cx ; CX = X Final, BX = Y Final
|
||||||
|
|
||||||
|
GFX GOTOXY, cx, bx
|
||||||
|
|
||||||
|
mov dx, [si + widget.text_seg]
|
||||||
|
mov ax, [si + widget.text_ofs]
|
||||||
|
GFX WRITE, dx, ax
|
||||||
|
|
||||||
|
pop si
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; =============================================================================
|
||||||
|
; Fonction : gui_draw_button
|
||||||
|
; Description : Dessine un bouton selon son état (.state)
|
||||||
|
; Entrée : SI = Pointeur vers la structure widget (DS:SI)
|
||||||
|
; =============================================================================
|
||||||
|
gui_draw_button:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
; Charger les propriétés depuis la structure
|
||||||
|
mov ax, [si + widget.x]
|
||||||
|
mov bx, [si + widget.y]
|
||||||
|
mov cx, [si + widget.w]
|
||||||
|
mov dx, [si + widget.h]
|
||||||
|
|
||||||
|
; Calculer X2 et Y2 pour le rectangle
|
||||||
|
mov di, ax ; X1
|
||||||
|
add di, cx ; X2 = X + W
|
||||||
|
mov bp, bx ; Y1
|
||||||
|
add bp, dx ; Y2 = Y + H
|
||||||
|
|
||||||
|
; Vérifier l'état
|
||||||
|
cmp byte [si + widget.state], GUI_STATE_PRESSED
|
||||||
|
je .draw_pressed
|
||||||
|
|
||||||
|
cmp byte [si + widget.state], GUI_STATE_HOVER
|
||||||
|
je .draw_hover
|
||||||
|
|
||||||
|
cmp byte [si + widget.state], GUI_STATE_DISABLED
|
||||||
|
je .draw_disabled
|
||||||
|
|
||||||
|
.draw_normal:
|
||||||
|
; Fond BLANC, Bordure NOIRE, Texte NOIR
|
||||||
|
; 1. Effacer le fond (Rectangle plein blanc) -> On triche, on dessine un rect plein blanc
|
||||||
|
; Note: GFX RECTANGLE_FILL utilise une couleur 0 ou 1. 1 = Blanc.
|
||||||
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 1 ; Fond blanc
|
||||||
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0 ; Bordure noire
|
||||||
|
|
||||||
|
; Configuration texte : Noir sur Transparent
|
||||||
|
GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT
|
||||||
|
jmp .draw_text
|
||||||
|
|
||||||
|
.draw_hover:
|
||||||
|
; Comme normal, mais bordure plus épaisse ou autre effet
|
||||||
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 1
|
||||||
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
||||||
|
|
||||||
|
; Effet "Gras" sur le cadre (on dessine un 2eme rectangle à l'intérieur)
|
||||||
|
inc ax
|
||||||
|
inc bx
|
||||||
|
dec di
|
||||||
|
dec bp
|
||||||
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
||||||
|
|
||||||
|
; Restaurer les coords pour le texte
|
||||||
|
mov ax, [si + widget.x]
|
||||||
|
mov bx, [si + widget.y]
|
||||||
|
mov di, ax
|
||||||
|
add di, [si + widget.w]
|
||||||
|
|
||||||
|
GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT
|
||||||
|
jmp .draw_text
|
||||||
|
|
||||||
|
.draw_pressed:
|
||||||
|
; Fond NOIR, Texte BLANC (Inversé)
|
||||||
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 0 ; Fond Noir
|
||||||
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 1 ; Bordure Blanche (optionnel)
|
||||||
|
|
||||||
|
; Configuration texte : Blanc sur Noir (ou transparent sur fond noir)
|
||||||
|
GFX TXT_MODE, GFX_TXT_WHITE_TRANSPARENT
|
||||||
|
jmp .draw_text
|
||||||
|
|
||||||
|
.draw_disabled:
|
||||||
|
; Fond Blanc, Bordure en pointillé (difficile sans support pointillé),
|
||||||
|
; on va faire simple : Bordure noire, mais on n'écrit pas le texte ou texte gris ?
|
||||||
|
; Pour CGA mono, "Disabled" = Texte normal mais cadre incomplet ou hachuré.
|
||||||
|
; Faisons simple : Cadre normal, mais texte non affiché ou "..."
|
||||||
|
GFX RECTANGLE_FILL, ax, bx, di, bp, 1
|
||||||
|
GFX RECTANGLE_DRAW, ax, bx, di, bp, 0
|
||||||
|
jmp .done ; Pas de texte pour montrer qu'il est désactivé
|
||||||
|
|
||||||
|
.draw_text:
|
||||||
|
; --- Centrage du texte ---
|
||||||
|
; Calcul simple : PosX = BoutonX + (LargeurBouton - (LenChaine * 8)) / 2
|
||||||
|
; Calcul simple : PosY = BoutonY + (HauteurBouton - 8) / 2
|
||||||
|
|
||||||
|
push si
|
||||||
|
; 1. Calculer longueur chaine
|
||||||
|
mov es, [si + widget.text_seg]
|
||||||
|
mov di, [si + widget.text_ofs]
|
||||||
|
xor cx, cx
|
||||||
|
|
||||||
|
.strlen:
|
||||||
|
cmp byte [es:di], 0
|
||||||
|
je .calc_pos
|
||||||
|
inc cx
|
||||||
|
inc di
|
||||||
|
jmp .strlen
|
||||||
|
|
||||||
|
.calc_pos:
|
||||||
|
; CX = Longueur chaine
|
||||||
|
shl cx, 3 ; CX * 8 (largeur en pixels du texte)
|
||||||
|
|
||||||
|
mov ax, [si + widget.w]
|
||||||
|
sub ax, cx ; Marge horizontale totale
|
||||||
|
shr ax, 1 ; Diviser par 2
|
||||||
|
add ax, [si + widget.x] ; X final
|
||||||
|
|
||||||
|
mov bx, [si + widget.h]
|
||||||
|
sub bx, 8 ; Hauteur fonte (8px)
|
||||||
|
shr bx, 1 ; Diviser par 2
|
||||||
|
add bx, [si + widget.y] ; Y final
|
||||||
|
|
||||||
|
; 2. Dessiner
|
||||||
|
GFX GOTOXY, ax, bx
|
||||||
|
|
||||||
|
mov dx, [si + widget.text_seg]
|
||||||
|
mov ax, [si + widget.text_ofs]
|
||||||
|
GFX WRITE, dx, ax
|
||||||
|
|
||||||
|
pop si
|
||||||
|
|
||||||
|
.done:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
; =============================================================================
|
||||||
|
; Fonction : gui_update_button
|
||||||
|
; Description : Met à jour l'état du bouton en fonction de la souris
|
||||||
|
; Entrée :
|
||||||
|
; SI = Pointeur vers widget
|
||||||
|
; CX = Mouse X
|
||||||
|
; DX = Mouse Y
|
||||||
|
; BL = Mouse Status (Bit 0 = Clic gauche)
|
||||||
|
; Sortie :
|
||||||
|
; AL = 1 si le bouton vient d'être cliqué (Relâché), 0 sinon
|
||||||
|
; =============================================================================
|
||||||
|
gui_update_button:
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
|
||||||
|
xor ax, ax ; AL = Return value (0)
|
||||||
|
|
||||||
|
; Si désactivé, on ne fait rien
|
||||||
|
cmp byte [si + widget.state], GUI_STATE_DISABLED
|
||||||
|
je .quit
|
||||||
|
|
||||||
|
; 1. Test de collision (Hit Test)
|
||||||
|
; X >= Widget.X ?
|
||||||
|
cmp cx, [si + widget.x]
|
||||||
|
jl .no_hit
|
||||||
|
|
||||||
|
; X <= Widget.X + Widget.W ?
|
||||||
|
mov di, [si + widget.x]
|
||||||
|
add di, [si + widget.w]
|
||||||
|
cmp cx, di
|
||||||
|
jg .no_hit
|
||||||
|
|
||||||
|
; Y >= Widget.Y ?
|
||||||
|
cmp dx, [si + widget.y]
|
||||||
|
jl .no_hit
|
||||||
|
|
||||||
|
; Y <= Widget.Y + Widget.H ?
|
||||||
|
mov di, [si + widget.y]
|
||||||
|
add di, [si + widget.h]
|
||||||
|
cmp dx, di
|
||||||
|
jg .no_hit
|
||||||
|
|
||||||
|
; --- HIT ! La souris est sur le bouton ---
|
||||||
|
|
||||||
|
; Test du clic (BL bit 0)
|
||||||
|
test bl, 1
|
||||||
|
jz .hovering
|
||||||
|
|
||||||
|
; -> Clic maintenu
|
||||||
|
mov byte [si + widget.state], GUI_STATE_PRESSED
|
||||||
|
jmp .draw_update
|
||||||
|
|
||||||
|
.hovering:
|
||||||
|
; Souris dessus, mais pas de clic
|
||||||
|
; Si on était en PRESSED juste avant, c'est un "CLICK" valide (Relâchement)
|
||||||
|
cmp byte [si + widget.state], GUI_STATE_PRESSED
|
||||||
|
jne .just_hover
|
||||||
|
|
||||||
|
; C'est un click valide !
|
||||||
|
mov al, 1 ; Return CLICKED
|
||||||
|
mov byte [si + widget.state], GUI_STATE_HOVER
|
||||||
|
jmp .draw_update
|
||||||
|
|
||||||
|
.just_hover:
|
||||||
|
mov byte [si + widget.state], GUI_STATE_HOVER
|
||||||
|
jmp .draw_update
|
||||||
|
|
||||||
|
.no_hit:
|
||||||
|
; Souris en dehors
|
||||||
|
mov byte [si + widget.state], GUI_STATE_NORMAL
|
||||||
|
|
||||||
|
.draw_update:
|
||||||
|
; Appelle la fonction de dessin pour mettre à jour le visuel
|
||||||
|
call gui_draw_button
|
||||||
|
|
||||||
|
.quit:
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
ret
|
||||||
|
|
@ -73,10 +73,10 @@ draw_window_source:
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
|
|
||||||
; --- Arguments ---
|
; --- Arguments ---
|
||||||
%define .x word [bp+4]
|
%define .xa word [bp+4]
|
||||||
%define .y word [bp+6]
|
%define .ya word [bp+6]
|
||||||
%define .w word [bp+8]
|
%define .wa word [bp+8]
|
||||||
%define .h word [bp+10]
|
%define .ha word [bp+10]
|
||||||
%define .title word [bp+12]
|
%define .title word [bp+12]
|
||||||
|
|
||||||
pusha
|
pusha
|
||||||
|
|
@ -89,19 +89,19 @@ draw_window_source:
|
||||||
; ----------------------------------------------------
|
; ----------------------------------------------------
|
||||||
; On dessine un rectangle noir décalé de +1,+1
|
; On dessine un rectangle noir décalé de +1,+1
|
||||||
; x1+1, y1+1, x2+1, y2+1 -> NOIR
|
; x1+1, y1+1, x2+1, y2+1 -> NOIR
|
||||||
mov ax, .x
|
mov ax, .xa
|
||||||
add ax, .w
|
add ax, .wa
|
||||||
inc ax ; x2 + 1
|
inc ax ; x2 + 1
|
||||||
mov bx, ax ; BX = right limit
|
mov bx, ax ; BX = right limit
|
||||||
|
|
||||||
mov ax, .y
|
mov ax, .ya
|
||||||
add ax, .h
|
add ax, .ha
|
||||||
inc ax ; y2 + 1
|
inc ax ; y2 + 1
|
||||||
mov dx, ax ; DX = bottom limit
|
mov dx, ax ; DX = bottom limit
|
||||||
|
|
||||||
mov ax, .x
|
mov ax, .xa
|
||||||
inc ax ; x1 + 1
|
inc ax ; x1 + 1
|
||||||
mov cx, .y
|
mov cx, .ya
|
||||||
inc cx ; y1 + 1
|
inc cx ; y1 + 1
|
||||||
|
|
||||||
; Appel cga_fill_rect(x+1, y+1, x+w+1, y+h+1, BLACK)
|
; Appel cga_fill_rect(x+1, y+1, x+w+1, y+h+1, BLACK)
|
||||||
|
|
@ -118,17 +118,17 @@ draw_window_source:
|
||||||
; ----------------------------------------------------
|
; ----------------------------------------------------
|
||||||
; On dessine un rectangle BLANC par dessus l'ombre
|
; On dessine un rectangle BLANC par dessus l'ombre
|
||||||
; Cela crée le corps et "découpe" l'ombre pour ne laisser que le bord visible.
|
; Cela crée le corps et "découpe" l'ombre pour ne laisser que le bord visible.
|
||||||
mov bx, .x
|
mov bx, .xa
|
||||||
add bx, .w ; BX = x2
|
add bx, .wa ; BX = x2
|
||||||
mov dx, .y
|
mov dx, .ya
|
||||||
add dx, .h ; DX = y2
|
add dx, .ha ; DX = y2
|
||||||
|
|
||||||
; Remplissage Blanc (Corps)
|
; Remplissage Blanc (Corps)
|
||||||
push word 1 ; Couleur 1 (Blanc)
|
push word 1 ; Couleur 1 (Blanc)
|
||||||
push dx
|
push dx
|
||||||
push bx
|
push bx
|
||||||
push word .y
|
push word .ya
|
||||||
push word .x
|
push word .xa
|
||||||
call cga_fill_rect
|
call cga_fill_rect
|
||||||
add sp, 10
|
add sp, 10
|
||||||
|
|
||||||
|
|
@ -136,8 +136,8 @@ draw_window_source:
|
||||||
push word 0 ; Couleur 0 (Noir)
|
push word 0 ; Couleur 0 (Noir)
|
||||||
push dx
|
push dx
|
||||||
push bx
|
push bx
|
||||||
push word .y
|
push word .ya
|
||||||
push word .x
|
push word .xa
|
||||||
call cga_draw_rect
|
call cga_draw_rect
|
||||||
add sp, 10
|
add sp, 10
|
||||||
|
|
||||||
|
|
@ -148,13 +148,13 @@ draw_window_source:
|
||||||
%define TITLE_HEIGHT 18
|
%define TITLE_HEIGHT 18
|
||||||
|
|
||||||
; Dessiner la ligne de séparation sous le titre
|
; Dessiner la ligne de séparation sous le titre
|
||||||
mov cx, .y
|
mov cx, .ya
|
||||||
add cx, TITLE_HEIGHT
|
add cx, TITLE_HEIGHT
|
||||||
|
|
||||||
push word 0 ; Couleur Noir
|
push word 0 ; Couleur Noir
|
||||||
push cx ; Y de la ligne
|
push cx ; Y de la ligne
|
||||||
push bx ; X2 (largeur fenêtre)
|
push bx ; X2 (largeur fenêtre)
|
||||||
push word .x ; X1
|
push word .xa ; X1
|
||||||
call cga_line_horizontal
|
call cga_line_horizontal
|
||||||
add sp, 8
|
add sp, 8
|
||||||
|
|
||||||
|
|
@ -162,11 +162,11 @@ draw_window_source:
|
||||||
; On dessine une ligne noire une ligne sur deux à l'intérieur du titre
|
; On dessine une ligne noire une ligne sur deux à l'intérieur du titre
|
||||||
; De y+1 à y+17, step 2
|
; De y+1 à y+17, step 2
|
||||||
|
|
||||||
mov si, .y
|
mov si, .ya
|
||||||
inc si ; Commence à y+1
|
inc si ; Commence à y+1
|
||||||
inc si ; Premier trait noir à y+2 (laissons 1px blanc sous le cadre haut)
|
inc si ; Premier trait noir à y+2 (laissons 1px blanc sous le cadre haut)
|
||||||
|
|
||||||
mov di, .y
|
mov di, .ya
|
||||||
add di, TITLE_HEIGHT
|
add di, TITLE_HEIGHT
|
||||||
dec di ; Fin juste avant la ligne de séparation
|
dec di ; Fin juste avant la ligne de séparation
|
||||||
|
|
||||||
|
|
@ -177,7 +177,7 @@ draw_window_source:
|
||||||
push word 0 ; Noir
|
push word 0 ; Noir
|
||||||
push si ; Y courant
|
push si ; Y courant
|
||||||
push bx ; X2
|
push bx ; X2
|
||||||
push word .x ; X1
|
push word .xa ; X1
|
||||||
call cga_line_horizontal
|
call cga_line_horizontal
|
||||||
add sp, 8
|
add sp, 8
|
||||||
|
|
||||||
|
|
@ -191,9 +191,9 @@ draw_window_source:
|
||||||
; Petit carré blanc à gauche avec contour noir
|
; Petit carré blanc à gauche avec contour noir
|
||||||
; Position: x+6, y+4, taille 9x9 (exemple)
|
; Position: x+6, y+4, taille 9x9 (exemple)
|
||||||
|
|
||||||
mov cx, .x
|
mov cx, .xa
|
||||||
add cx, 6 ; Box X1
|
add cx, 6 ; Box X1
|
||||||
mov dx, .y
|
mov dx, .ya
|
||||||
add dx, 4 ; Box Y1
|
add dx, 4 ; Box Y1
|
||||||
|
|
||||||
mov si, cx
|
mov si, cx
|
||||||
|
|
@ -236,9 +236,9 @@ draw_window_source:
|
||||||
|
|
||||||
.calc_center:
|
.calc_center:
|
||||||
; b) Calcul X Centré = X_win + (W_win/2) - (Len * 8 / 2)
|
; b) Calcul X Centré = X_win + (W_win/2) - (Len * 8 / 2)
|
||||||
mov ax, .w
|
mov ax, .wa
|
||||||
shr ax, 1 ; W / 2
|
shr ax, 1 ; W / 2
|
||||||
add ax, .x ; Centre de la fenêtre
|
add ax, .xa ; Centre de la fenêtre
|
||||||
|
|
||||||
mov bx, cx ; Sauver Len
|
mov bx, cx ; Sauver Len
|
||||||
shl cx, 2 ; Len * 4 (car Len * 8 / 2 = Len * 4)
|
shl cx, 2 ; Len * 4 (car Len * 8 / 2 = Len * 4)
|
||||||
|
|
@ -249,7 +249,7 @@ draw_window_source:
|
||||||
mov cx, ax ; Text X start
|
mov cx, ax ; Text X start
|
||||||
sub cx, 4 ; Padding gauche (Rect X1)
|
sub cx, 4 ; Padding gauche (Rect X1)
|
||||||
|
|
||||||
mov dx, .y
|
mov dx, .ya
|
||||||
add dx, 2 ; Rect Y1 (juste sous le cadre haut)
|
add dx, 2 ; Rect Y1 (juste sous le cadre haut)
|
||||||
|
|
||||||
push bx ; Sauve longueur char pour plus tard
|
push bx ; Sauve longueur char pour plus tard
|
||||||
|
|
@ -261,7 +261,7 @@ draw_window_source:
|
||||||
add si, ax
|
add si, ax
|
||||||
add si, 4 ; Padding droite (Rect X2)
|
add si, 4 ; Padding droite (Rect X2)
|
||||||
|
|
||||||
mov di, .y
|
mov di, .ya
|
||||||
add di, TITLE_HEIGHT
|
add di, TITLE_HEIGHT
|
||||||
dec di ; Rect Y2 (juste au dessus ligne séparation)
|
dec di ; Rect Y2 (juste au dessus ligne séparation)
|
||||||
|
|
||||||
|
|
@ -282,7 +282,7 @@ draw_window_source:
|
||||||
|
|
||||||
; GFX GOTOXY (X, Y) -> Y centré dans la barre de titre
|
; GFX GOTOXY (X, Y) -> Y centré dans la barre de titre
|
||||||
; Centre barre ~9px. Font 8px. Y = Win_Y + 5
|
; Centre barre ~9px. Font 8px. Y = Win_Y + 5
|
||||||
mov dx, .y
|
mov dx, .ya
|
||||||
add dx, 5
|
add dx, 5
|
||||||
|
|
||||||
; Note: GFX GOTOXY utilise des arguments pile, attention à l'ordre API
|
; Note: GFX GOTOXY utilise des arguments pile, attention à l'ordre API
|
||||||
|
|
@ -319,10 +319,10 @@ draw_window:
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
|
|
||||||
; --- Arguments ---
|
; --- Arguments ---
|
||||||
%define .x word [bp+4]
|
%define .xa word [bp+4]
|
||||||
%define .y word [bp+6]
|
%define .ya word [bp+6]
|
||||||
%define .w word [bp+8]
|
%define .wa word [bp+8]
|
||||||
%define .h word [bp+10]
|
%define .ha word [bp+10]
|
||||||
%define .title word [bp+12]
|
%define .title word [bp+12]
|
||||||
; ---- Variables Locales ---
|
; ---- Variables Locales ---
|
||||||
|
|
||||||
|
|
@ -332,19 +332,19 @@ draw_window:
|
||||||
; ----------------------------------------------------
|
; ----------------------------------------------------
|
||||||
; On dessine un rectangle noir décalé de +1,+1
|
; On dessine un rectangle noir décalé de +1,+1
|
||||||
; x1+1, y1+1, x2+1, y2+1 -> NOIR
|
; x1+1, y1+1, x2+1, y2+1 -> NOIR
|
||||||
mov ax, .x
|
mov ax, .xa
|
||||||
add ax, .w
|
add ax, .wa
|
||||||
inc ax ; x2 + 1
|
inc ax ; x2 + 1
|
||||||
mov bx, ax ; BX = right limit
|
mov bx, ax ; BX = right limit
|
||||||
|
|
||||||
mov ax, .y
|
mov ax, .ya
|
||||||
add ax, .h
|
add ax, .ha
|
||||||
inc ax ; y2 + 1
|
inc ax ; y2 + 1
|
||||||
mov dx, ax ; DX = bottom limit
|
mov dx, ax ; DX = bottom limit
|
||||||
|
|
||||||
mov ax, .x
|
mov ax, .xa
|
||||||
inc ax ; x1 + 1
|
inc ax ; x1 + 1
|
||||||
mov cx, .y
|
mov cx, .ya
|
||||||
inc cx ; y1 + 1
|
inc cx ; y1 + 1
|
||||||
|
|
||||||
GFX RECTANGLE_DRAW, ax, cx, bx, dx, 0
|
GFX RECTANGLE_DRAW, ax, cx, bx, dx, 0
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue