diff --git a/doc/MEMORY_MAP.md b/doc/MEMORY_MAP.md
index 53d4f4c..984fdb1 100644
--- a/doc/MEMORY_MAP.md
+++ b/doc/MEMORY_MAP.md
@@ -10,11 +10,13 @@ The processor starts in Real Mode, addressing 1 MB of memory.
| :--- | :--- | :--- | :--- | :--- | :--- |
| **`0x00000`** | **`0x003FF`** | 1 KB | **IVT** (Interrupt Vector Table) | `0x0000` | `memory.asm` |
| **`0x00400`** | **`0x004FF`** | 256 B | **BDA** (BIOS Data Area) Standard | `0x0040` | `memory.asm` |
-| **`0x00500`** | **`0x005FF`** | 256 B | **Custom BDA** (Driver Data) | `0x0050` | `memory.asm` |
-| **`0x00600`** | **`0x00AFF`** | 1.25 KB | **GUI RAM** (Widget Allocation) | `0x0060` | `gui/lib.asm` |
-| **`0x00B00`** | **`0x07FFF`** | 29 KB | **Free** (Low Memory) | | |
+| **`0x00500`** | **`0x006FF`** | ~512 B | **Custom BDA** (Driver Data) | `0x0050` | |
+| **`0x00700`** | **`0x00A6F`** | ~1792 B | **GUI RAM** (Widget Allocation) | **`0x0070`** | `gui/lib-api.asm` |
+| **`0x00A70`** | **`0x07FFF`** | ~ 29 KB | **Free** (Low Memory) | | |
| **`0x08000`** | **`0x17FFF`** | 64 KB | **Stack** (Grows downwards) | `0x0800` | `boot.asm` |
-| **`0x18000`** | **`0x9FFFF`** | 544 KB | **Free** (Conventional RAM) | | |
+| **`0x18000`** | **`0x1FFFF`** | 32 KB | **Free** | | |
+| **`0x20000`** | **`0x2FFFF`** | 64 KB | **Heap** (Dynamic Allocation) | `0x2000` | `memory.asm` |
+| **`0x30000`** | **`0x9FFFF`** | 448 KB | **Free** (Conventional RAM) | | |
| **`0xA0000`** | **`0xAFFFF`** | 64 KB | **VGA RAM** (Graphics Modes) | `0xA000` | `Hardware` |
| **`0xB0000`** | **`0xB7FFF`** | 32 KB | **MDA RAM** (Monochrome Text) | `0xB000` | `Hardware` |
| **`0xB8000`** | **`0xBFFFF`** | 32 KB | **VRAM** (CGA / MCGA) | `0xB800` | `generic.asm` |
@@ -35,11 +37,11 @@ The processor starts in Real Mode, addressing 1 MB of memory.
The project separates the standard IBM BDA from its own variables to avoid conflicts with the VGA BIOS loaded at `0xC000`.
* **Standard BDA (`0040:0000`)**: Used mainly by the VGA BIOS (loaded via QEMU) to store video modes (`0x0049`) and column count (`0x004A`).
-* **Custom BDA (`0050:0000`)**: Defined by `BDA_DATA_SEG`. Stores driver states:
+* **Custom BDA (`0050:0000`)**: Defined by `BDA_CUSTOM_SEG`. Stores driver states:
* **Mouse**: Input buffer, status, coordinates, background buffer (for cursor).
* **Gfx**: Text cursor position, attributes.
- * **GUI RAM**: Segment `0x0060` (Physical `0x00600`).
- * **Layout**: Located in low memory (`0x0060`) to avoid any collision with the Stack (`0x0800`).
+ * **GUI RAM**: Segment `0x0063` (Physical `0x00630`).
+ * **Layout**: Located in low memory to avoid any collision with the Stack (`0x0800`).
#### Stack
* **Stack**: Grows downwards from physical address `0xFFFE` (16-bit aligned) of the "Stack Segment" defined by `STACK_SEG`.
@@ -71,11 +73,13 @@ Le processeur démarre en mode réel, adressant 1 Mo de mémoire.
| :--- | :--- | :--- | :--- | :--- | :--- |
| **`0x00000`** | **`0x003FF`** | 1 KB | **IVT** (Interrupt Vector Table) | `0x0000` | `memory.asm` |
| **`0x00400`** | **`0x004FF`** | 256 B | **BDA** (BIOS Data Area) Standard | `0x0040` | `memory.asm` |
-| **`0x00500`** | **`0x005FF`** | 256 B | **Custom BDA** (Driver Data) | `0x0050` | `memory.asm` |
-| **`0x00600`** | **`0x00AFF`** | 1.25 KB | **GUI RAM** (Widget Allocation) | `0x0060` | `gui/lib.asm` |
-| **`0x00B00`** | **`0x07FFF`** | 29 KB | **Free** (Low Memory) | | |
+| **`0x00500`** | **`0x006FF`** | ~512 B | **Custom BDA** (Driver Data) | `0x0050` | |
+| **`0x00700`** | **`0x00A6F`** | ~1792 B | **GUI RAM** (Widget Allocation) | **`0x0070`** | `gui/lib-api.asm` |
+| **`0x00A70`** | **`0x07FFF`** | ~ 29 KB | **Free** (Low Memory) | | |
| **`0x08000`** | **`0x17FFF`** | 64 KB | **Stack** (Grows downwards) | `0x0800` | `boot.asm` |
-| **`0x18000`** | **`0x9FFFF`** | 544 KB | **Free** (Conventional RAM) | | |
+| **`0x18000`** | **`0x1FFFF`** | 32 KB | **Libre** | | |
+| **`0x20000`** | **`0x2FFFF`** | 64 KB | **Heap** (Allocation Dynamique) | `0x2000` | `memory.asm` |
+| **`0x30000`** | **`0x9FFFF`** | 448 KB | **Libre** (RAM Conventionnelle) | | |
| **`0xA0000`** | **`0xAFFFF`** | 64 KB | **VGA RAM** (Graphics Modes) | `0xA000` | `Hardware` |
| **`0xB0000`** | **`0xB7FFF`** | 32 KB | **MDA RAM** (Monochrome Text) | `0xB000` | `Hardware` |
| **`0xB8000`** | **`0xBFFFF`** | 32 KB | **VRAM** (CGA / MCGA) | `0xB800` | `generic.asm` |
@@ -96,11 +100,11 @@ Le processeur démarre en mode réel, adressant 1 Mo de mémoire.
Le projet sépare la BDA standard IBM de ses propres variables pour éviter les conflits avec le BIOS VGA chargé en `0xC000`.
* **BDA Standard (`0040:0000`)** : Utilisée principalement par le BIOS VGA (chargé via QEMU) pour stocker les modes vidéo (`0x0049`) et le nombre de colonnes (`0x004A`).
-* **Custom BDA (`0050:0000`)** : Définie par `BDA_DATA_SEG`. Stocke l'état des drivers :
+* **Custom BDA (`0050:0000`)** : Définie par `BDA_CUSTOM_SEG`. Stocke l'état des drivers :
* **Souris** : Buffer d'entrée, état, coordonnées, buffer de sauvegarde du fond (pour le curseur).
* **Gfx** : Position du curseur texte, attributs.
- * **GUI RAM** : Segment `0x0060`.
- * **Organisation** : Située en mémoire basse (`0x0060`) pour éviter toute collision avec la Pile (`0x0800`).
+ * **GUI RAM** : Segment `0x0063` (Physique `0x00630`).
+ * **Organisation** : Située en mémoire basse pour éviter toute collision avec la Pile (`0x0800`).
#### Stack
* **Stack** : Grandit vers le bas depuis l'adresse physique `0xFFFE` (Alignement sur 16 bits) du "stack Segment" défini par `STACK_SEG`.
diff --git a/src/boot-ok.asm b/src/boot-ok.asm
new file mode 100644
index 0000000..9630900
--- /dev/null
+++ b/src/boot-ok.asm
@@ -0,0 +1,274 @@
+; =============================================================================
+; Project : Custom BIOS / ROM
+; File : boot.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 .
+;
+; =============================================================================
+
+ bits 16
+; ---------------------------------------------------------------------------
+;
+; configuration du bios
+;
+; ---------------------------------------------------------------------------
+
+; initial stack
+%define STACK_SEG 0x0800 ; segment de base
+%define GFX_DRIVERS 'CGA'
+
+section .text
+ bits 16
+
+%include "./common/chartable.asm"
+%include "./common/cursor.asm"
+%include "./common/patterns.asm"
+%include "./common/generic.asm"
+%include "./common/string.asm"
+
+; definition du BDA
+%include "./common/bda.asm"
+
+; drivers
+%if GFX_DRIVERS == 'VGA'
+ %include "./drivers/gfx_vga.asm"
+%else
+ ; default drivers
+ %include "./drivers/gfx_cgam.asm"
+%endif
+
+%include "./drivers/mouse_ps2.asm"
+%include "./drivers/keyboard_ps2.asm"
+
+%include "./common/debug_gfx.asm"
+
+; GUI
+%include "./gui/lib-api.asm"
+
+; --- Données texte ---
+str_quit db "Quitter", 0
+str_hello db "Hello", 0
+str_option1 db "option 1", 0
+str_option2 db "option 2", 0
+str_option3 db "option 3", 0
+
+entrycode:
+ cli
+ mov ax, STACK_SEG ; creation du stack par défaut
+ mov ss, ax
+ mov sp, 0xFFFE ; haut du segment (64ko de stack), mot-aligné
+ cld
+
+ call ivt_setup ; configuration d'une table d'interruption "dummy"
+ call bda_setup ; initialisation du BDA
+
+ ISADBG ISA_GREEN, 0x01
+
+ ; Install IRQ 0 : timer_isr
+ mov ax,cs
+ mov dx,ax
+ mov bx,timer_isr
+ mov ax,i8259_MASTER_INT
+
+ call ivt_setvector
+
+ ISADBG ISA_GREEN, 0x02
+
+ ; initialisation des PIC 8259A
+ call pic_init
+
+ ISADBG ISA_GREEN, 0x04
+
+ ; load Roms
+ call setup_load_rom
+
+ ISADBG ISA_GREEN, 0x08
+
+ ; on vérifie que le BIOS VGA a installé une INT 10h
+ call setup_check_vga
+
+ ISADBG ISA_GREEN, 0x10
+
+ ; enable IRQ 0
+ mov ah,IRQ_ENABLED
+ mov al,0
+ call pic_set_irq_mask
+
+ call kbd_init
+ sti
+
+ DEBUG 0xFADE
+ ISADBG ISA_GREEN, 0x20
+
+ ; on active le mode graphique
+ GFX INIT
+ ISADBG ISA_GREEN, 0xFF
+
+ ; call mouse_reset
+ call mouse_init
+
+ GFX MOUSE_MOVE
+ GFX MOUSE_SHOW
+
+ ISADBG ISA_RED, 0x81
+
+ xor ax,ax
+
+ .loops:
+ call main_loop
+
+ nop
+ jmp .loops
+
+; --- Callbacks (Fonctions appelées par le moteur) ---
+on_click_quit:
+ hlt
+ jmp on_click_quit
+ ret
+
+on_click_hello:
+ ret
+
+%define .oldval word [bp-2]
+%define .my_slider word [bp-4]
+%define .value word [bp-6]
+main_loop:
+ push bp
+ mov bp, sp
+ sub sp, 6
+
+ push cs
+ pop ds
+
+ DEBUG 1
+ ISADBG ISA_LEFT, 1
+
+ ; Init du système GUI
+ call gui_init_system
+ DEBUG 2
+ ISADBG ISA_LEFT, 2
+
+ ; --- CRÉATION DYNAMIQUE DES BOUTONS ---
+
+ ; Créer Bouton 1 "QUITTER"
+ GUI OBJ_CREATE, OBJ_TYPE_BUTTON_ROUNDED, 10, 10, 80, 16
+ GUI OBJ_SET_TEXT, ax, cs, str_quit
+ ; Créer Bouton 2 "HELLO"
+ GUI OBJ_CREATE, OBJ_TYPE_BUTTON_ROUNDED, 100, 50, 80, 16
+ GUI OBJ_SET_TEXT, ax, cs, str_hello
+
+ ; Créer 3 checkbox "option"
+ GUI OBJ_CREATE, OBJ_TYPE_CHECKBOX, 200, 50, 100, 15
+ GUI OBJ_SET_TEXT, ax, cs, str_option1
+
+ GUI OBJ_CREATE, OBJ_TYPE_CHECKBOX, 200, 50+16, 100, 15
+ GUI OBJ_SET_TEXT, ax, cs, str_option2
+
+ GUI OBJ_CREATE, OBJ_TYPE_CHECKBOX, 200, 50+16*2, 100, 15
+ GUI OBJ_SET_TEXT, ax, cs, str_option3
+
+ DEBUG 3
+ ISADBG ISA_LEFT, 3
+
+ ; Créer Slider (Drag)
+ GUI OBJ_CREATE, OBJ_TYPE_SLIDER, 10, 100, 150, 12
+ GUI OBJ_SET_MODE, ax, SLIDER_HORIZONTAL
+ GUI OBJ_SLIDER_SET_ATTR, ax, 10, 140, 10, 15
+
+ GUI OBJ_CREATE, OBJ_TYPE_SLIDER, 400, 10, 16, 150
+ mov .my_slider, ax
+
+ GUI OBJ_SET_MODE, .my_slider, SLIDER_VERTICAL
+ GUI OBJ_SLIDER_SET_ATTR, .my_slider, 0, 31, 0, 12
+
+ mov .oldval, 0x1256
+ mov .value, 0xFADE
+
+ DEBUG 4
+ ISADBG ISA_LEFT, 4
+
+ .loop:
+ call gui_process_all
+ GUI OBJ_GET_VAL, .my_slider
+ mov .value, ax
+
+ cmp ax,.oldval
+ je .loop
+
+ ; debug
+ mov .oldval, ax
+ GFX RECTANGLE_FILL,0,148,50,166, PATTERN_WHITE
+ GFX GOTOXY, 8, 150
+
+ mov ax, .value
+ call print_word_hex
+ ; end debug
+
+ ; change palette...
+ ;and ax, 0x00FF
+ ;mov bh, 0x00
+ ;mov bl, al
+ ;mov ah, 0x0b
+ ;mov al, 0x00
+ ;int 0x10
+
+ mov dx, CRTC_COLOR_DATA
+ and ax, 0x001F
+ out dx, ax
+
+ jmp .loop
+ leave
+ ret
+
+; -----------------------------------------------------------
+; timer ISR (IRQ -> INT)
+; -----------------------------------------------------------
+timer_isr:
+ push ax
+
+ push fs
+ mov ax,BDA_CUSTOM_SEG
+ mov fs,ax
+; exemple de fonctionnement:
+; inc byte [fs:BDA_TIMER]
+
+ mov al, PIC_EOI ; EOI master
+ out i8259_MASTER_CMD, al
+ pop fs
+
+ pop ax
+ iret
+
+; ------------------------------------------------------------------
+; Padding jusqu'au reset vector
+; ------------------------------------------------------------------
+times 0xFFF0 - ($ - $$) db 0xFF
+
+; ------------------------------------------------------------------
+; RESET VECTOR (exécuté par le CPU)
+; ------------------------------------------------------------------
+section .resetvect
+bits 16
+global reset_vector
+
+reset_vector:
+ ; code minimal au reset
+ jmp 0xF000:entrycode
+
+builddate:
+ db __DATE__
+ times 16-($-$$) db 0 ; le stub tient dans 16 octets (ou moins)
diff --git a/src/boot.asm b/src/boot.asm
index 2a4f1d6..3fb0629 100644
--- a/src/boot.asm
+++ b/src/boot.asm
@@ -29,13 +29,9 @@
; initial stack
%define STACK_SEG 0x0800 ; segment de base
+%define GFX_DRIVERS 'VGA'
-;section .text
-; bits 16
-;
-; db 'EXTRA CODE Section',0
-;
-; times 0xFFFF - ($ - $$) db 0xFF
+%define DEBUGER_ENABLED
section .text
bits 16
@@ -50,15 +46,20 @@ section .text
%include "./common/bda.asm"
; drivers
-%include "./drivers/gfx_cgam.asm"
+%if GFX_DRIVERS == 'VGA'
+ %include "./drivers/gfx_vga.asm"
+%else
+ ; default drivers
+ %include "./drivers/gfx_cgam.asm"
+%endif
+
%include "./drivers/mouse_ps2.asm"
%include "./drivers/keyboard_ps2.asm"
-%include "./common/debug_cga.asm"
+%include "./common/debug_gfx.asm"
; GUI
-%include "./gui/lib.asm"
-%include "./gui/draw.asm"
+; %include "./gui/lib-api.asm"
; --- Données texte ---
str_quit db "Quitter", 0
@@ -86,24 +87,12 @@ entrycode:
mov ax,i8259_MASTER_INT
call ivt_setvector
-
- ISADBG ISA_GREEN, 2
-
; initialisation des PIC 8259A
call pic_init
-
- ISADBG ISA_GREEN, 4
-
; load Roms
call setup_load_rom
-
- ISADBG ISA_GREEN, 8
-
; on vérifie que le BIOS VGA a installé une INT 10h
call setup_check_vga
-
- ISADBG ISA_GREEN, 16
-
; enable IRQ 0
mov ah,IRQ_ENABLED
mov al,0
@@ -112,19 +101,18 @@ entrycode:
call kbd_init
sti
- DEBUG 0xFADE
-
ISADBG ISA_GREEN, 32
; on active le mode graphique
GFX INIT
- call mouse_init
+ call mouse_reset
+
+ ; call mouse_init
GFX MOUSE_MOVE
ISADBG ISA_RED, 0x80
GFX MOUSE_SHOW
-
ISADBG ISA_RED, 0x81
.loops:
@@ -155,71 +143,14 @@ main_loop:
ISADBG ISA_LEFT, 1
; Init du système GUI
- call gui_init_system
+; call gui_init_system
DEBUG 2
ISADBG ISA_LEFT, 2
- ; --- CRÉATION DYNAMIQUE DES BOUTONS ---
-
- ; Créer Bouton 1 "QUITTER"
- GUI OBJ_CREATE, OBJ_TYPE_BUTTON_ROUNDED, 10, 10, 80, 16
- GUI OBJ_SET_TEXT, ax, cs, str_quit
- ; Créer Bouton 2 "HELLO"
- GUI OBJ_CREATE, OBJ_TYPE_BUTTON_ROUNDED, 100, 50, 80, 16
- GUI OBJ_SET_TEXT, ax, cs, str_hello
- ; Créer checkbox 3 "option 1"
- GUI OBJ_CREATE, OBJ_TYPE_CHECKBOX, 200, 50, 100, 15
- GUI OBJ_SET_TEXT, ax, cs, str_option1
-
- GUI OBJ_CREATE, OBJ_TYPE_CHECKBOX, 200, 50+16, 100, 15
- GUI OBJ_SET_TEXT, ax, cs, str_option2
-
- GUI OBJ_CREATE, OBJ_TYPE_CHECKBOX, 200, 50+16*2, 100, 15
- GUI OBJ_SET_TEXT, ax, cs, str_option3
-
- DEBUG 3
- ISADBG ISA_LEFT, 3
-
- ; Créer Slider (Drag)
- GUI OBJ_CREATE, OBJ_TYPE_SLIDER, 10, 100, 150, 12
- GUI OBJ_SET_MODE, ax, SLIDER_HORIZONTAL
- GUI OBJ_SLIDER_SET_ATTR, ax, 10, 140, 10, 15
-
- GUI OBJ_CREATE, OBJ_TYPE_SLIDER, 400, 10, 16, 150
- mov .my_slider, ax
-
- GUI OBJ_SET_MODE, .my_slider, SLIDER_VERTICAL
- GUI OBJ_SLIDER_SET_ATTR, .my_slider, 0, 15, 15, 12
-
- mov .oldval, 0x1256
- mov .value, 0xFADE
-
- DEBUG 4
- ISADBG ISA_LEFT, 4
-
- .loop:
- call gui_process_all
- GUI OBJ_GET_VAL, .my_slider
- mov .value, ax
-
- cmp ax,.oldval
- je .loop
-
- ; debug
- mov .oldval, ax
- GFX RECTANGLE_FILL,0,148,50,166, PATTERN_WHITE
- GFX GOTOXY, 8, 150
-
- mov ax, .value
- call print_word_hex
- ; end debug
-
- mov dx, 0x3d9
- mov ax, .value
- and ax, 0x000F
- out dx, al
+ .loop:
+; call gui_process_all
jmp .loop
leave
@@ -232,7 +163,7 @@ timer_isr:
push ax
push fs
- mov ax,BDA_DATA_SEG
+ mov ax,BDA_CUSTOM_SEG
mov fs,ax
; exemple de fonctionnement:
; inc byte [fs:BDA_TIMER]
diff --git a/src/common/bda.asm b/src/common/bda.asm
index f4d18f2..703a306 100644
--- a/src/common/bda.asm
+++ b/src/common/bda.asm
@@ -24,11 +24,9 @@
; https://wiki.nox-rhea.org/back2root/ibm-pc-ms-dos/hardware/informations/bios_data_area
;
-%define BDA_SEGMENT 0x0040 ; segment BDA
-
-; custom vars
-%define BDA_INFO_MEM_SIZE 0x0014 ; Memory size in Kbytes
-%define BDA_INFO_MEM_SEG BDA_INFO_MEM_SIZE+2 ; highest Memory Segment
+%define BDA_SEGMENT 0x0040 ; segment BDA (historically)
+%define BDA_CUSTOM_SEG 0x0050 ; custom data (mouse, gfx cursor, etc..)
+%define BDA_GUI_WIDGET 0x0070 ; Segment de données UI (Safe: après Stack, avant Heap)
; video related information (compatible with VGA bios)
%define BDA_VIDEO_CURR_MODE 0x0049
@@ -38,7 +36,8 @@
;
; information relative à la souris
;
-%define BDA_DATA_SEG 0x0050
+
+%define BDA_BitPP 4
%define BKG_DWORDS_PER_LINE 1 ; 1 dword stocké par ligne
%define BKG_LINES 16
@@ -63,7 +62,8 @@ struc mouse
.cur_ofs resw 1 ;
.bkg_saved resb 1 ; background saved
alignb 4 ; alignement 4 bytes
- .bkg_buffer resd 16 ; buffer for saved background
+ ; buffer for saved background
+ .bkg_buffer resd 16*BDA_BitPP
endstruc
struc gfx
@@ -86,7 +86,7 @@ bda_setup:
pusha
push ds
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov es, ax
mov ax, 0x5F
diff --git a/src/common/debug_cga.asm b/src/common/debug_gfx.asm
similarity index 97%
rename from src/common/debug_cga.asm
rename to src/common/debug_gfx.asm
index 3e40c5e..29bfe4a 100644
--- a/src/common/debug_cga.asm
+++ b/src/common/debug_gfx.asm
@@ -42,8 +42,7 @@ dump_ram_words:
call print_word_hex ; Affiche AX sous forme "XXXX"
; (Optionnel) Ajouter un espace entre chaque mot pour la lisibilité
- mov al, ' '
- call cga_putc
+ GFX PUTCH, ' '
pop si ; Restaure SI
pop cx ; Restaure CX
@@ -77,9 +76,7 @@ print_word_hex:
xor bx, bx
mov bl, al
- push bx
- call cga_putc
- add sp, 2
+ GFX PUTCH, bx
loop .next_digit ; Répète 4 fois
popa
diff --git a/src/common/generic.asm b/src/common/generic.asm
index aff6845..374bb4c 100644
--- a/src/common/generic.asm
+++ b/src/common/generic.asm
@@ -20,16 +20,12 @@
;
; =============================================================================
-%define DISABLE_DEBUGER
-
-%ifndef DISABLE_DEBUGER
-
+%ifdef DEBUGER_ENABLED
%macro DEBUG 1
GFX GOTOXY, 0, 0
mov ax, %1
call print_word_hex
%endmacro
-
;
; Debugger for 86Box
;
@@ -111,6 +107,26 @@
%define IRQ_ENABLED 0x00
%define IRQ_DISABLED 0x01
+; ---------------------------------------------------------------------------
+; CGA/MDA Controler
+; ---------------------------------------------------------------------------
+;
+; MDA 6845
+%define CRTC_6845_MONO 0x03b4
+%define CRTC_6845_MONO_REGISTER 0x03b5
+;
+; CGA 6845
+%define CRTC_6845_COLOR 0x03d4
+%define CRTC_6845_COLOR_REGISTER 0x03d4
+%define CRTC_COLOR_REGISTER 0x03d5
+
+%define CRTC_COLOR_CTRL 0x03d8
+%define CRTC_COLOR_DATA 0x03d9
+
+%define EGAVGA_CONTROLLER 0x03ce
+
+%define VGA_SEQUENCER 0x03c4
+
; ---------------------------------------------------------------------------
; Détection les ROM supplementaires
; Teste la RAM de 0xC000 jusqu’à 0xE000, par pas de 2KB.
diff --git a/src/common/patterns.asm b/src/common/patterns.asm
index 26440a2..c2655d6 100644
--- a/src/common/patterns.asm
+++ b/src/common/patterns.asm
@@ -13,9 +13,16 @@
align 8
pattern_8x8:
- dq 0x0000000000000000 ; pattern_black (Tout à 0 = Noir)
- dq 0x2200880022008800 ; pattern_gray_dark (Majorité de 0)
- dq 0x2288228822882288 ; pattern_gray_mid
- dq 0xAA55AA55AA55AA55 ; pattern_gray_light (50/50)
- dq 0x77DD77DD77DD77DD ; pattern_white_light (Majorité de 1 = Clair)
- dq 0xFFFFFFFFFFFFFFFF ; pattern_white (Tout à 1 = Blanc)
+ dq 0x0000000000000000 ; 0 : pattern_black (Tout à 0 = Noir)
+ dq 0x2200880022008800 ; 1 : pattern_gray_dark (Majorité de 0)
+ dq 0x2288228822882288 ; 2 : pattern_gray_mid
+ dq 0xAA55AA55AA55AA55 ; 3 : pattern_gray_light (50/50)
+ dq 0x77DD77DD77DD77DD ; 4 : pattern_white_light (Majorité de 1 = Clair)
+ dq 0xFFFFFFFFFFFFFFFF ; 5 : pattern_white (Tout à 1 = Blanc)
+
+
+%macro PATTERN_PTR 1
+ mov ax, cs
+ mov ds, ax
+ lea esi, [pattern_8x8 + (%1 * 8)]
+%endmacro
\ No newline at end of file
diff --git a/src/drivers/gfx_cgam.asm b/src/drivers/gfx_cgam.asm
index e932cbe..e2cfb37 100644
--- a/src/drivers/gfx_cgam.asm
+++ b/src/drivers/gfx_cgam.asm
@@ -31,7 +31,6 @@
%define CGA_STRIDE 80
%define CGA_ODD_BANK 0x2000
-
;
; bit : descr
; 0 : text color : 0=black, 1=white
@@ -78,6 +77,7 @@
%define MOUSE_HIDE 11
%define MOUSE_SHOW 12
%define MOUSE_MOVE 13
+%define MOUSE_DRAW 14
; ------------------------------------------------------------
; COMMENTAIRE SUR LA MÉTHODE D'APPEL
@@ -105,6 +105,7 @@ graph_driver:
dw cga_mouse_hide ; déplacement du curseur
dw cga_mouse_show ; déplacement du curseur
dw cga_mouse_cursor_move ; déplacement du curseur
+ dw cga_cursor_draw
; ------------------------------------------------------------
; initialise le mode graphique (via l'int 10h)
@@ -112,7 +113,7 @@ graph_driver:
; ce mode est entrelacé, un bit/pixel, 8 pixels par octet
; ------------------------------------------------------------
cga_init:
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov ds, ax
; init graphics mode
@@ -180,7 +181,7 @@ cga_set_writemode:
push fs
push ax
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov fs,ax
mov ax, .mode
@@ -211,7 +212,7 @@ cga_set_charpos:
pusha
push fs
- mov ax,BDA_DATA_SEG
+ mov ax,BDA_CUSTOM_SEG
mov fs,ax
; store x,y en pixel
@@ -314,7 +315,7 @@ cga_putc:
mov bx, VIDEO_SEG
mov es, bx
- mov bx, BDA_DATA_SEG
+ mov bx, BDA_CUSTOM_SEG
mov fs, bx
mov ax, .car
@@ -1267,7 +1268,7 @@ cga_mouse_hide:
pusha ; Sauvegarder TOUS les registres 32-bits
push ds
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov ds, ax
; Décrémenter le compteur
@@ -1295,7 +1296,7 @@ cga_mouse_show:
pusha
push ds
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov ds, ax
; Incrémenter le compteur
@@ -1327,7 +1328,7 @@ cga_mouse_cursor_move:
push es
; move Data Segment
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov ds, ax
cmp byte [BDA_MOUSE + mouse.cur_counter], 0
@@ -1437,10 +1438,7 @@ cga_cursor_restorebg:
ret
; ============================================================
-; gfx_cursor_draw_rm16_i386_self
-; Entrée:
-; DS = BDA_DATA_SEG
-; Sortie: rien
+; cga_cursor_draw
; Détruit: registres sauvegardés/restaurés (PUSHA/POPA)
; ============================================================
%define .height word [bp-2]
@@ -1456,24 +1454,23 @@ cga_cursor_draw:
push gs
cld ; Sécurité : Direction avant
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov ds, ax
mov ax, VIDEO_SEG
mov es, ax
; --- CLIPPING VERTICAL ---
mov dx, [ds:BDA_MOUSE + mouse.y]
- cmp dx, 200
+ mov bx, GFX_HEIGHT
+ cmp dx, bx
jae .exit_total
mov ax, 16
- mov bx, 200
sub bx, dx ; 200-y
cmp ax, bx
jbe .y_ok ; y<= 200-16
mov ax, bx
-
.y_ok:
mov .height, ax
diff --git a/src/drivers/gfx_vga.asm b/src/drivers/gfx_vga.asm
new file mode 100644
index 0000000..b7d62eb
--- /dev/null
+++ b/src/drivers/gfx_vga.asm
@@ -0,0 +1,619 @@
+; =============================================================================
+; Project : Custom BIOS / ROM
+; File : gfx_vga.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 .
+;
+; =============================================================================
+
+;
+; graphics drivers pour carte video/mode CGA-Mono (640x200x2)
+;
+%define VIDEO_SEG 0A000h
+
+%define GFX_MODE 0x12 ; VGA HiRes (640x480x16)
+%define GFX_WIDTH 640
+%define GFX_HEIGHT 480
+;
+; bit : descr
+; 0 : text color : 0=black, 1=white
+; 1 : transparent : 1=apply background attribut
+;
+%define GFX_TXT_WHITE_TRANSPARENT 00000000b
+%define GFX_TXT_BLACK_TRANSPARENT 00000001b
+%define GFX_TXT_WHITE 00000010b
+%define GFX_TXT_BLACK 00000011b
+
+%macro GFX 1-*
+ ; %1 est l'index de la fonction
+ ; On itère sur les arguments suivants en sens inverse (Convention C)
+
+ %rep %0 - 1 ; Répéter pour (Nombre d'args - 1)
+ %rotate -1 ; Prend le dernier argument
+ push %1 ; L'empile
+ %endrep
+
+ %rotate -1 ; On revient au premier argument (l'index de fonction)
+ call word [cs:graph_driver + ((%1)*2)]
+
+ ; Nettoyage de la pile (Convention CDECL: l'appelant nettoie)
+ ; Chaque argument = 2 octets (1 word).
+ add sp, (%0 - 1) * 2
+%endmacro
+
+; ------------------------------------------------------------
+; TABLE DE SAUT (VECTEURS API)
+; Cette table doit être située au début du driver pour être
+; accessible par la GUI à des offsets fixes.
+; ------------------------------------------------------------
+%define INIT 0
+%define PUTPIXEL 1
+%define GETPIXEL 2
+%define GOTOXY 3
+%define TXT_MODE 4
+%define PUTCH 5
+%define WRITE 6
+%define LINE 7
+%define RECTANGLE 8
+%define RECTANGLE_FILL 9
+%define RECTANGLE_ROUND 10
+%define MOUSE_HIDE 11
+%define MOUSE_SHOW 12
+%define MOUSE_MOVE 13
+%define MOUSE_DRAW 14
+
+; ------------------------------------------------------------
+; COMMENTAIRE SUR LA MÉTHODE D'APPEL
+;
+; GFX FUNCTION, Arg1, Arg2, Arg3
+;
+; GFX GFX_PUTPIXEL, 320, 100, 1
+;
+; Si vous changez le code du driver, tant que la table au début
+; ne change pas d'ordre, la GUI n'a pas besoin d'être recompilée.
+; ------------------------------------------------------------
+align 2
+graph_driver:
+ dw vga_init ; init de la carte graphique
+ dw vga_putpixel ; dessin d'un pixel
+ dw vga_none ; lecture d'un pixel
+ dw vga_none ; gotoxy
+ dw vga_none ; mode texte
+ dw vga_none ; dessin d'un caractère
+ dw vga_none ; dessin d'une chaine de caractère
+ dw vga_none ; dessin d'une ligne (Bresenham) avec décision horizontale/verticale
+ dw vga_none ; dessin d'un rectangle
+ dw vga_none ; dessin d'un rectangle plein
+ dw vga_none ; dessin d'un rectangle arrondi
+ dw vga_mouse_hide ; cache la souris
+ dw vga_mouse_show ; montre la souris
+ dw vga_mouse_cursor_move ; déplacement du curseur
+ dw vga_cursor_draw
+
+; ------------------------------------------------------------
+; dummy function
+;
+; cette fonction ne sert a rien, juste a "occuper" l'espace
+; dans la table pour fonction qui n'existent pas
+; ------------------------------------------------------------
+vga_none:
+ ret
+
+; ------------------------------------------------------------
+; initialise le mode graphique (via l'int 10h)
+;
+; ce mode est entrelacé, un bit/pixel, 8 pixels par octet
+; ------------------------------------------------------------
+vga_init:
+ ; init graphics mode
+ mov ah, 0x00 ; AH=00h set video mode
+ mov al, GFX_MODE
+ int 0x10
+
+ ; dessine un background "check-board"
+ ; Les patterns sont dans le segment de code (CS)
+ push cs
+ pop ds
+
+ PATTERN_PTR PATTERN_GRAY_LIGHT
+ mov bl, 15
+ call vga_background
+ ISADBG ISA_GREEN, 0x88
+ ret
+
+; ------------------------------------------------------------
+; vga_calc_addr
+; Entrée:
+; CX = X (0-639)
+; DX = Y (0-479)
+; Sortie:
+; DI = Offset dans le segment A000h
+; ------------------------------------------------------------
+vga_calc_addr:
+ push ax
+ push dx
+
+ ; Calcul de Y * 80
+ ; 80 = 64 + 16 (soit Y<<6 + Y<<4) pour éviter une multiplication lente
+ mov ax, dx ; AX = Y
+ shl ax, 4 ; AX = Y * 16
+ mov di, ax ; DI = Y * 16
+ shl ax, 2 ; AX = (Y * 16) * 4 = Y * 64
+ add di, ax ; DI = (Y * 64) + (Y * 16) = Y * 80
+
+ ; Ajout de X / 8
+ shr cx, 3 ; CX = X / 8 (octet horizontal)
+ add di, cx ; DI = (Y * 80) + (X / 8)
+
+ pop dx
+ pop ax
+ ret
+
+; Entrée: ESI = Pointeur vers le tableau de 8 octets (pattern 8x8)
+; BL = Couleur de premier plan (0-15)
+vga_background:
+; pushad
+
+ ; Configuration VGA pour le remplissage de masse
+ mov dx, VGA_SEQUENCER ; Sequencer
+ mov ax, 0F02h ; Map Mask (Index 2) = 0Fh (Tous les plans)
+ out dx, ax
+
+ ; Graphics Controller
+ mov dx, EGAVGA_CONTROLLER
+ mov ax, 0305h ; Mode Register (Index 5) = Mode 3
+ out dx, ax
+
+ mov al, 00h ; Set/Reset (Index 0) = Couleur
+ mov ah, bl
+ out dx, ax
+
+ ; Initialisation mémoire
+ mov ax, VIDEO_SEG
+ mov es, ax
+ xor edi, edi ; ES:EDI = Début mémoire vidéo
+ movzx esi, si ; Nettoyer ESI (garder SI) pour l'adressage
+
+ ; Boucle principale (480 lignes)
+ xor edx, edx ; EDX servira d'index pour le pattern (0-7)
+ mov ecx, 480
+
+ .line_loop:
+ mov al, [esi + edx] ; Charger l'octet du pattern pour la ligne actuelle
+ ; Répliquer l'octet AL dans EAX (ex: 0xAA -> 0xAAAAAAAA) pour le 32-bit
+ mov ah, al ; copy byte 0 -> byte 1
+ mov bx, ax ; préserve word
+ shl eax, 16 ; shift low word -> hi word
+ mov ax, bx ; EAX contient maintenant 4 fois le pattern de 8 pixels
+
+ mov bp, 20 ; 80 octets / 4 (32-bit) = 20 itérations par ligne
+ .row_loop:
+ mov bl, [es:di] ; LATCH LOAD : Lecture indispensable en Mode 3
+ stosd
+ ;mov [es:edi], eax ; Écrit 32 pixels d'un coup avec le pattern
+ ;add edi, 4
+ dec bp
+ jne .row_loop
+
+ ; Passer à la ligne suivante du pattern (modulo 8)
+ inc edx
+ and edx, 7 ; Si EDX=8, revient à 0
+ loop .line_loop
+
+ ; Cleanup
+ mov dx, EGAVGA_CONTROLLER
+ mov ax, 0005h ; Reset Write Mode 0
+ out dx, ax
+; popad
+ ret
+
+; Entrée: AX = X (0-639), BX = Y (0-479), CL = Couleur (0-15)
+%define .x word [bp+4]
+%define .y word [bp+6]
+%define .color byte [bp+8]
+vga_putpixel:
+ push bp
+ mov bp, sp
+ pusha
+
+ mov bx, .y
+ mov ax, .x
+ mov cl, .color
+ ; Calcul de l'offset (Y * 80 + X/8)
+
+ imul di, bx, 80 ; DI = Y * 80
+ mov bx, ax ; Sauvegarde X
+ shr ax, 3 ; AX = X / 8
+ add di, ax ; DI = Offset final
+
+ ; Calcul du masque de bit (7 - (X % 8))
+ and bx, 7 ; BX = X % 8
+ mov ah, 80h ; Bit 7 à 1
+ shr ah, cl ; Décale pour pointer le bon pixel (cl = bx ici)
+ ; Note: en pratique on utilise souvent une table de pré-calcul pour shr ah, bl
+
+ ; Programmation du Graphics Controller
+ mov dx, EGAVGA_CONTROLLER
+
+ ; Sélection du Bit Mask (Index 8)
+ mov al, 08h
+ out dx, ax ; AH contient le masque calculé
+
+ ; Sélection du Set/Reset (Couleur, Index 0)
+ mov ax, 0000h
+ mov al, 00h
+ mov ah, cl ; Couleur
+ out dx, ax
+
+ ; Enable Set/Reset (On active les 4 plans, Index 1)
+ mov ax, 0F01h
+ out dx, ax
+
+ ; 4. Écriture (Nécessite une lecture préalable pour charger les Latches)
+ mov ax, VIDEO_SEG
+ mov es, ax
+ mov al, [es:di] ; Lecture bidon pour charger les verrous (latches)
+ mov [es:di], al ; L'écriture applique la couleur via le matériel
+
+ ; Reset des registres pour ne pas casser le reste du dessin
+ mov ax, 0FF08h
+ out dx, ax
+ mov ax, 0001h
+ out dx, ax
+
+ popa
+ leave
+ ret
+; clean defs
+%undef .x
+%undef .y
+%undef .color
+
+
+; ------------------------------------------------------------
+; GESTION DU CURSEUR
+; ------------------------------------------------------------
+;
+; ------------------------------------------------------------
+; gère la demande d'effacement du curseur souris
+;
+; ------------------------------------------------------------
+vga_mouse_hide:
+ pushf ; Sauver l'état des flags (interrupts)
+ cli ; Désactiver les interruptions (CRITIQUE)
+ pusha ; Sauvegarder TOUS les registres 32-bits
+ push ds
+
+ mov ax, BDA_CUSTOM_SEG
+ mov ds, ax
+
+ ; Décrémenter le compteur
+ dec byte [BDA_MOUSE + mouse.cur_counter]
+
+ ; Vérifier si on vient juste de passer en mode caché (c-à-d on est à -1)
+ cmp byte [BDA_MOUSE + mouse.cur_counter], -1
+ jne .skip_restore ; Si on est à -2, -3... elle est déjà cachée
+
+ call vga_cursor_restorebg
+
+ .skip_restore:
+ pop ds
+ popa
+ popf ; Restaure les interruptions (STI si elles étaient là)
+ ret
+
+; ------------------------------------------------------------
+; gère la demande d'affichage du curseur souris
+;
+; ------------------------------------------------------------
+vga_mouse_show:
+ pushf
+ cli
+ pusha
+ push ds
+
+ mov ax, BDA_CUSTOM_SEG
+ mov ds, ax
+
+ ; Incrémenter le compteur
+ inc byte [BDA_MOUSE + mouse.cur_counter]
+
+ ; Vérifier si on est revenu à 0 (Visible)
+ cmp byte [BDA_MOUSE + mouse.cur_counter], 0
+ jne .skip_draw ; Si on est encore à -1, -2... on reste caché
+
+ ; C'est la transition Caché -> Visible : On affiche le curseur
+ ; IMPORTANT : On sauve le fond ACTUEL (qui a peut-être changé pendant le hide)
+ call vga_cursor_savebg
+ call vga_cursor_draw
+
+ .skip_draw:
+ pop ds
+ popa
+ popf ; restore également le flag d'interruption
+ ret
+
+
+; ------------------------------------------------------------
+; gère le déplacement du curseur souris
+;
+; ------------------------------------------------------------
+vga_mouse_cursor_move:
+ pusha
+ push ds
+ push es
+
+ ; BDA Data Segment
+ mov ax, BDA_CUSTOM_SEG
+ mov ds, ax
+
+ cmp byte [BDA_MOUSE + mouse.cur_counter], 0
+ jl .done ; Si < 0, on ne dessine rien !
+
+ cmp byte [BDA_MOUSE + mouse.cur_drawing],0
+ jne .done
+
+ mov byte [BDA_MOUSE + mouse.cur_drawing],1
+
+ call vga_cursor_restorebg
+ call vga_cursor_savebg
+ call vga_cursor_draw
+ mov byte [BDA_MOUSE + mouse.cur_drawing],0
+ .done:
+ pop es
+ pop ds
+ popa
+ ret
+
+; Buffer requis : 192 octets (16 lignes * 3 octets * 4 plans)
+; ATTENTION : Vérifiez que mouse.bkg_buffer dans bda.asm est assez grand !
+vga_cursor_savebg:
+ cmp byte [BDA_MOUSE + mouse.bkg_saved], 0
+ jne .done
+
+ push es
+ mov ax, VIDEO_SEG
+ mov es, ax
+
+ ; Calculer l'adresse de départ (y * 80 + x / 8)
+ mov cx, [BDA_MOUSE + mouse.x]
+ mov dx, [BDA_MOUSE + mouse.y]
+ call vga_calc_addr ; Doit retourner DI = offset VRAM
+ mov [BDA_MOUSE + mouse.cur_addr_start], di
+
+ lea si, [BDA_MOUSE + mouse.bkg_buffer]
+
+ mov dx, EGAVGA_CONTROLLER ; Graphics Controller Port
+ mov al, 0x04 ; Read Plane Select Register
+ out dx, al
+ inc dx ; Point sur Data Port (0x03CF)
+
+ xor bl, bl ; BL = Index du plan (0 à 3)
+ .plan_loop:
+ mov al, bl
+ out dx, al ; Sélectionner le plan à lire
+
+ push di ; Sauver l'adresse de départ du curseur
+ mov cx, 16 ; 16 lignes
+ .row_loop:
+ mov ax, [es:di] ; Lit 16 pixels (2 octets)
+ mov [ds:si], ax
+ mov al, [es:di+2] ; Lit le 3eme octet (pour le shift)
+ mov [ds:si+2], al
+ add si, 3
+ add di, 80 ; Ligne suivante (VGA linéaire)
+ loop .row_loop
+
+ pop di ; Revenir en haut pour le plan suivant
+ inc bl
+ cmp bl, 4
+ jne .plan_loop
+
+ ; Reset Read Map Select to 0 (Nettoyage)
+ mov dx, 0x3CE
+ mov ax, 0x0004
+ out dx, ax
+
+ pop es
+ mov byte [BDA_MOUSE + mouse.bkg_saved], 1
+ .done:
+ ret
+
+vga_cursor_restorebg:
+ cmp byte [BDA_MOUSE + mouse.bkg_saved], 0
+ je .done
+
+ push es
+ mov ax, VIDEO_SEG
+ mov es, ax
+
+ mov di, [BDA_MOUSE + mouse.cur_addr_start]
+ lea si, [BDA_MOUSE + mouse.bkg_buffer]
+
+ ; Sécurité : S'assurer que ES pointe bien vers la vidéo pour le restore
+ mov ax, VIDEO_SEG
+ mov es, ax
+
+ ; Sécurité : Réinitialiser le contrôleur graphique pour l'écriture CPU brute
+ mov dx, EGAVGA_CONTROLLER
+ mov ax, 0x0005 ; Mode 0
+ out dx, ax
+ mov ax, 0x0001 ; Enable Set/Reset = 0 (Important !)
+ out dx, ax
+ mov ax, 0xFF08 ; Bit Mask = 0xFF
+ out dx, ax
+ mov ax, 0x0003 ; Function = Replace
+ out dx, ax
+
+ mov dx, VGA_SEQUENCER ; Sequencer Port
+ mov al, 0x02 ; Map Mask Register
+ out dx, al
+ inc dx ; Data Port (0x03C5)
+
+ mov bl, 1 ; Mask initial : Plan 0 (0001b)
+ .plan_loop:
+ mov al, bl
+ out dx, al ; Activer l'écriture uniquement sur ce plan
+
+ push di
+ mov cx, 16
+ .row_loop:
+ lodsw ; Lit 2 octets
+ mov [es:di], ax
+ lodsb ; Lit le 3eme octet
+ mov [es:di+2], al
+ add di, 80
+ loop .row_loop
+
+ pop di
+ shl bl, 1 ; Plan suivant (1 -> 2 -> 4 -> 8)
+ cmp bl, 16 ; Fini après le plan 3 (8)
+ jne .plan_loop
+
+ ; Rétablir le Map Mask sur tous les plans (0x0F)
+ mov dx, VGA_SEQUENCER
+ mov ax, 0x0F02
+ out dx, ax
+
+ pop es
+ mov byte [BDA_MOUSE + mouse.bkg_saved], 0
+ .done:
+ ret
+
+; ============================================================
+; vga_cursor_draw
+; Détruit: registres sauvegardés/restaurés (PUSHA/POPA)
+; ============================================================
+vga_cursor_draw:
+ push bp
+ mov bp, sp
+ sub sp, 4 ; [bp-2]: height, [bp-4]: x_bit_offset
+ ; local variables
+ %define .height word [bp-2]
+ %define .bit_ofs word [bp-4]
+
+ pushad
+ push ds
+ push es
+ push gs
+ ; Note: pushad sauvegarde déjà tous les registres généraux (EAX...EDI)
+
+ cld ; Sécurité : Direction avant
+ mov ax, BDA_CUSTOM_SEG
+ mov ds, ax
+ mov ax, VIDEO_SEG
+ mov es, ax
+
+ ; --- CLIPPING VERTICAL ---
+ mov dx, [BDA_MOUSE + mouse.y]
+ mov bx, GFX_HEIGHT
+ cmp dx, bx
+ jae .exit_total
+
+ mov ax, 16
+ sub bx, dx
+ cmp ax, bx
+ jbe .y_ok
+
+ mov ax, bx
+ .y_ok:
+ mov .height, ax
+
+ ; --- Calcul Adresse et Shift ---
+ mov ax, [BDA_MOUSE + mouse.x]
+ mov cx, ax
+ and ax, 7 ; Reste (0-7) = décalage de bit
+ mov .bit_ofs, ax
+ call vga_calc_addr ; DI = VRAM Offset
+
+ ; --- CONFIG VGA (Write Mode 0, Logic Ops) ---
+ mov dx, VGA_SEQUENCER
+ mov ax, 0x0F02 ; Map Mask = All planes
+ out dx, ax
+
+ mov dx, 0x3CE ; Graphics Controller
+ mov ax, 0x0005 ; Mode 0
+ out dx, ax
+ mov ax, 0x0001 ; Enable Set/Reset = 0 (CPU Data)
+ out dx, ax
+ mov ax, 0xFF08 ; Bit Mask = 0xFF
+ out dx, ax
+
+ ; Source du Sprite -> (GS:SI)
+ mov ax, [BDA_MOUSE + mouse.cur_seg]
+ mov gs, ax
+ mov si, [BDA_MOUSE + mouse.cur_ofs]
+
+ .row_loop:
+ ; --- PREPARE MASKS ---
+ ; On récupère le masque de l'image (AND) et du curseur (XOR)
+ mov ax, [gs:si] ; AX = AND Mask (16 bits)
+ xchg al, ah ; Souvent nécessaire selon l'endianness du sprite
+ xor ebx, ebx
+ mov bx, ax
+ not ebx ; On veut des 1 partout sauf là où le curseur est présent
+
+ ; Décalage pour l'alignement au pixel près
+ mov cx, .bit_ofs
+ ror ebx, cl ; Rotation pour ne pas perdre de bits
+
+ ; --- CONFIG VGA POUR AND ---
+ mov dx, 0x3CE
+ mov ax, 0x0803 ; Data Rotate/Function Select: AND (bits 3-4 = 01b)
+ out dx, ax
+
+ ; Application sur 3 octets (pour couvrir les 16 pixels + le shift)
+ %rep 3
+ mov al, [es:di] ; CHARGE LES LATCHES (Indispensable)
+ mov eax, ebx
+ shr eax, 16 ; Récupère la partie haute (si 32-bit shift utilisé)
+ stosb ; Écrit AL et DI++ (Applique le AND sur les 4 plans)
+ %endrep
+ sub di, 3 ; Revient au début de la ligne pour le XOR
+
+ ; --- CONFIG VGA POUR XOR ---
+ mov ax, 0x1803 ; Data Rotate/Function Select: XOR (bits 3-4 = 11b)
+ out dx, ax
+
+ ; Récupération du masque XOR (la forme blanche/noire du curseur)
+ mov ax, [gs:si+32]
+ ; ... (Appliquer le même décalage et stosb que pour le AND) ...
+
+ ; --- NEXT ROW ---
+ add di, 80 - 3 ; Ligne suivante (80 octets par ligne)
+ add si, 2
+ dec word .height
+ jnz .row_loop
+
+ ; --- RESTORE VGA ---
+ mov dx, 0x3CE
+ mov ax, 0x0003 ; Function = Replace
+ out dx, ax
+ mov ax, 0xFF08 ; Bit Mask = 0xFF
+ out dx, ax
+ mov ax, 0x0001 ; Enable Set/Reset = 0
+ out dx, ax
+
+ .exit_total:
+ pop gs
+ pop es
+ pop ds
+ popad
+ leave
+ ret
+%undef .height
+%undef .mask
diff --git a/src/drivers/mouse_ps2.asm b/src/drivers/mouse_ps2.asm
index b106abb..fad7943 100644
--- a/src/drivers/mouse_ps2.asm
+++ b/src/drivers/mouse_ps2.asm
@@ -43,7 +43,7 @@
;
; ------------------------------------------------------------
mouse_reset:
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov fs,ax
; effacer les variables du drivers
@@ -52,8 +52,8 @@ mouse_reset:
mov byte [fs:BDA_MOUSE + mouse.packetlen],3 ; 3 bytes par défaut
mov byte [fs:BDA_MOUSE + mouse.status],0
- mov word [fs:BDA_MOUSE + mouse.x],320 ; vous pouvez aussi préciser le centre
- mov word [fs:BDA_MOUSE + mouse.y],100 ; vous pouvez aussi préciser le centre
+ mov word [fs:BDA_MOUSE + mouse.x],GFX_WIDTH / 2
+ mov word [fs:BDA_MOUSE + mouse.y],GFX_HEIGHT / 2
mov word [fs:BDA_MOUSE + mouse.cur_x], 0
mov word [fs:BDA_MOUSE + mouse.cur_y], 0
@@ -154,7 +154,7 @@ mouse_init:
;
; ------------------------------------------------------------
mouse_detect_packet_len:
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov fs,ax
mov byte [fs:BDA_MOUSE + mouse.packetlen], 3
@@ -284,7 +284,7 @@ isr_mouse_handler:
push ds
; use BDA segment
- mov ax,BDA_DATA_SEG
+ mov ax,BDA_CUSTOM_SEG
mov ds,ax
; lire un octet depuis le contrôleur et le stocker dans le buffer
diff --git a/src/gui/lib-api.asm b/src/gui/lib-api.asm
new file mode 100644
index 0000000..83ff51c
--- /dev/null
+++ b/src/gui/lib-api.asm
@@ -0,0 +1,528 @@
+; =============================================================================
+; 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 .
+;
+; =============================================================================
+
+; --- Configuration ---
+%define GUI_MAX_WIDGETS 32 ; Nombre max de widgets simultanés
+
+; Dimensions
+%define GUI_CHECKBOX_SIZE 10 ;
+
+; --- 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é
+
+; --- Types de Widgets ---
+%define OBJ_TYPE_LABEL 0
+%define OBJ_TYPE_BUTTON 1
+%define OBJ_TYPE_SLIDER 2
+%define OBJ_TYPE_BUTTON_ROUNDED 3
+%define OBJ_TYPE_CHECKBOX 4
+
+; --- Widgets attributs ---
+%define BUTTON_DEFAULT 0
+%define BUTTON_OK 1
+
+%define SLIDER_HORIZONTAL 1
+%define SLIDER_VERTICAL 2
+
+; =============================================================================
+; SECTION : API ACTIONS
+; =============================================================================
+
+%define OBJ_CREATE 0
+%define OBJ_DESTROY 1
+%define OBJ_GET_STATE 2
+%define OBJ_GET_TYPE 3
+%define OBJ_GET_VAL 4
+%define OBJ_SET_VAL 5
+
+%define OBJ_SET_MODE 6
+%define OBJ_SET_TEXT 7
+
+%define OBJ_GET_PTR 8
+
+%define OBJ_SLIDER_SET_ATTR 9
+
+
+gui_api_table:
+ dw gui_api_create
+ dw gui_api_destroy
+ dw gui_api_get_state
+ dw gui_api_get_type
+ dw gui_api_get_val
+ dw gui_api_set_val
+ dw gui_api_set_mode
+ dw gui_api_set_text
+ dw gui_get_widget_ptr
+ dw gui_api_slider_attr
+
+
+; --- 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
+ .y resw 1 ; Position Y
+ .x2 resw 1 ; Position X2 calculée
+ .y2 resw 1 ; Position Y2 calculée
+ .w resw 1 ; Largeur
+ .h resw 1 ; Hauteur
+ .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_drag resw 1 ; adresse de la fonction "on drag"
+
+ .attr_mode resb 1 ; 0=None, 1=Horiz, 2=Vert
+ .attr_min resw 1 ; Valeur/Position Min
+ .attr_max resw 1 ; Valeur/Position Max
+ .attr_val resw 1 ; Valeur/Position Actuelle
+
+ .thumb_pos resw 1 ; Valeur/Position Actuelle en pixel pour le dessin.
+ .thumb_pct resb 1 ; Taille du curseur en % (1-100)
+
+ .attr_anchor resw 1 ; interne Offset pour le drag
+ alignb 2 ; Alignement mémoire pour performance
+endstruc
+; actuellement 34 octets
+
+%macro GUI 1-*
+ %rep %0 - 1
+ %rotate -1
+ push %1
+ %endrep
+ %rotate -1
+ call word [cs:gui_api_table + ((%1)*2)]
+ add sp, (%0 - 1) * 2
+%endmacro
+
+; -----------------------------------------------------------------------------
+; gui_api_slider_attr
+; -----------------------------------------------------------------------------
+%define .id word [bp+4]
+%define .min word [bp+6]
+%define .max word [bp+8]
+%define .val word [bp+10]
+%define .pct word [bp+12]
+gui_api_slider_attr:
+ push bp
+ mov bp, sp
+ push ax
+
+ push .id ; ID
+ call gui_get_widget_ptr
+ jc .err
+
+ mov ax, .min
+ mov word [gs:si + widget.attr_min], ax
+ mov ax, .max
+ mov word [gs:si + widget.attr_max], ax
+ mov ax, .val
+ mov word [gs:si + widget.attr_val], ax
+ mov ax, .pct
+ mov byte [gs:si + widget.thumb_pct], al
+
+ call gui_slider_update_pixels
+
+ .err:
+ pop ax
+ leave
+ ret
+%undef .id
+%undef .mode
+
+; -----------------------------------------------------------------------------
+; gui_api_set_mode
+; -----------------------------------------------------------------------------
+%define .id word [bp+4]
+%define .mode word [bp+6]
+gui_api_set_mode:
+ push bp
+ mov bp, sp
+ push ax
+
+ push .id
+ call gui_get_widget_ptr
+ jc .err
+
+ mov ax, .mode
+ mov byte [gs:si + widget.attr_mode], al
+
+ .err:
+ pop ax
+ leave
+ ret
+%undef .id
+%undef .mode
+
+; -----------------------------------------------------------------------------
+; gui_api_set_text
+; -----------------------------------------------------------------------------
+%define .id word [bp+4]
+%define .segmt word [bp+6]
+%define .oft word [bp+8]
+gui_api_set_text:
+ push bp
+ mov bp, sp
+ push ax
+
+ push .id
+ call gui_get_widget_ptr
+ jc .err
+
+ mov ax, .segmt
+ mov word [gs:si + widget.text_seg], ax
+ mov ax, .oft ; Offset du texte
+ mov word [gs:si + widget.text_ofs], ax
+
+ .err:
+ pop ax
+ leave
+ ret
+%undef .id
+%undef .text_ofs
+%undef .text_seg
+
+; -----------------------------------------------------------------------------
+; gui_api_create
+; Crée un widget et retourne son ID
+; Out: AX = ID ou -1 si erreur
+;
+; parameters : type, x, y, w, h, text_ofs, text_seg
+;
+; -----------------------------------------------------------------------------
+%define .type word [bp+4]
+%define .x word [bp+6]
+%define .y word [bp+8]
+%define .w word [bp+10]
+%define .h word [bp+12]
+gui_api_create:
+ push bp
+ mov bp, sp
+ push gs
+
+ mov ax, BDA_GUI_WIDGET
+ mov gs, ax
+ call gui_alloc_widget ; Returns GS:SI
+ mov ax, -1
+ jc .done
+
+ ; ID = SI / widget_size
+ mov ax, si
+ xor dx, dx
+ mov cx, widget_size
+ div cx
+
+ mov bx, .type
+ mov byte [gs:si + widget.type], bl
+ mov bx, .x
+ mov word [gs:si + widget.x], bx
+ mov bx, .y
+ mov word [gs:si + widget.y], bx
+ mov bx, .w
+ mov word [gs:si + widget.w], bx
+ mov bx, .h
+ mov word [gs:si + widget.h], bx
+
+ mov byte [gs:si + widget.state], GUI_STATE_NORMAL
+ mov byte [gs:si + widget.oldstate], 0
+.done:
+ pop gs
+ leave
+ ret
+%undef .type
+%undef .x
+%undef .y
+%undef .w
+%undef .h
+
+; -----------------------------------------------------------------------------
+; gui_api_get_state
+; Arg1: ID
+; Out: AX = State
+; -----------------------------------------------------------------------------
+%define .id word [bp+4]
+gui_api_get_state:
+ push bp
+ mov bp, sp
+
+ mov ax, .id ; ID
+ call gui_get_widget_ptr
+ jc .err
+
+ xor ax, ax
+ mov al, [gs:si + widget.state]
+ jmp .done
+
+.err:
+ mov ax, -1
+.done:
+ leave
+ ret
+%undef .id
+
+; -----------------------------------------------------------------------------
+; gui_api_get_type
+; Arg1: ID
+; Out: AX = Type
+; -----------------------------------------------------------------------------
+%define .id word [bp+4]
+gui_api_get_type:
+ push bp
+ mov bp, sp
+
+ mov ax, .id ; ID
+ call gui_get_widget_ptr
+ jc .err
+
+ xor ax, ax
+ mov al, [gs:si + widget.type]
+ jmp .done
+
+.err:
+ mov ax, -1
+.done:
+ leave
+ ret
+%undef .id
+
+; -----------------------------------------------------------------------------
+; gui_api_get_val
+; Arg1: ID
+; Out: AX = Attr Val
+; -----------------------------------------------------------------------------
+%define .id word [bp+4]
+gui_api_get_val:
+ push bp
+ mov bp, sp
+
+ call gui_get_widget_ptr
+ ;jc .err
+
+ call gui_slider_update_value
+ mov ax, [gs:si + widget.attr_val]
+ jmp .done
+
+.err:
+ mov ax, -1
+.done:
+ leave
+ ret
+%undef .id
+
+; -----------------------------------------------------------------------------
+; gui_api_set_val
+; Arg1: ID
+; Arg2: Value
+; -----------------------------------------------------------------------------
+%define .id word [bp+4]
+%define .val word [bp+6]
+gui_api_set_val:
+ push bp
+ mov bp, sp
+
+ mov ax, .id ; ID
+ call gui_get_widget_ptr
+ jc .err
+
+ mov ax, .val
+ mov [gs:si + widget.thumb_pos], ax
+
+.err:
+ leave
+ ret
+%undef .id
+%undef .val
+
+; -----------------------------------------------------------------------------
+; gui_api_destroy
+; Détruit un widget via son ID
+; Arg1: ID
+; Out: AX = 0 (OK), -1 (Error)
+; -----------------------------------------------------------------------------
+%define .id word [bp+4]
+gui_api_destroy:
+ push bp
+ mov bp, sp
+
+ mov ax, .id ; ID
+ call gui_get_widget_ptr
+ jc .err
+
+ call gui_free_widget
+ xor ax, ax
+ jmp .done
+
+.err:
+ mov ax, -1
+.done:
+ leave
+ ret
+%undef .id
+
+; -----------------------------------------------------------------------------
+; gui_get_widget_ptr
+; Helper interne : Convertit ID en Pointeur
+; In: ID
+; Out: GS:SI = Ptr, CF=1 if error
+; -----------------------------------------------------------------------------
+%define .id word [bp+4]
+gui_get_widget_ptr:
+ push bp
+ mov bp, sp
+ push ax
+ push cx
+
+ mov ax, .id
+ cmp ax, GUI_MAX_WIDGETS
+ jae .error
+
+ mov cx, widget_size
+ xor dx, dx
+ mul cx ; AX = Offset
+ mov si, ax
+
+ mov ax, BDA_GUI_WIDGET
+ mov gs, ax
+
+ clc
+ jmp .done
+ .error:
+ stc
+ .done:
+ pop cx
+ pop ax
+ leave
+ ret
+%undef .id
+
+
+; =============================================================================
+; 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 BDA_GUI_WIDGET
+; -----------------------------------------------------------------------------
+gui_init_system:
+ push eax
+ push cx
+ push es
+ push di
+
+ mov ax, BDA_GUI_WIDGET
+ mov es, ax
+
+ cld
+ xor di, di
+ mov cx, (widget_size * GUI_MAX_WIDGETS) / 2
+ xor ax, ax
+ rep stosw ; Plus sûr en mode 16 bits pour l'alignement
+
+ pop di
+ pop es
+ pop cx
+ pop eax
+ ret
+
+; -----------------------------------------------------------------------------
+; gui_alloc_widget
+; Cherche un slot vide et retourne son adresse
+; Sortie :
+; - Succès : CF=0 (Carry Clear), GS:SI = Offset du widget
+; - Echec : CF=1 (Carry Set), GS:SI = Indéfini (ou 0)
+; -----------------------------------------------------------------------------
+gui_alloc_widget:
+ push ax
+ push cx
+ push bx
+
+ mov ax, BDA_GUI_WIDGET
+ mov gs, ax
+
+ mov si, 0 ; Début du pool
+ mov cx, GUI_MAX_WIDGETS
+
+ .loop_find:
+ cmp byte [gs: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 [gs:si + widget.state], GUI_STATE_NORMAL ; Marquer comme occupé
+ mov byte [gs:si + widget.type], OBJ_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
+ mov word [gs:si + widget.event_click], 0
+ mov word [gs:si + widget.event_drag], 0
+ mov byte [gs:si + widget.thumb_pct], 10 ; 10% par défaut
+
+ clc ; Clear Carry Flag
+ .done:
+ pop bx
+ pop cx
+ pop ax
+ ret
+
+; -----------------------------------------------------------------------------
+; gui_free_widget
+; Libère un widget
+; Entrée : SI = Pointeur widget
+; -----------------------------------------------------------------------------
+gui_free_widget:
+ push eax
+ push es
+
+ mov ax, BDA_GUI_WIDGET
+ mov es, ax
+
+ cld
+ mov di, si
+ mov cx, (widget_size)
+ shr cx, 2 ; cx / 4
+ xor eax, eax
+ rep stosd ; Remplit tout de 0
+
+ ; On efface le widget
+ mov byte [es:si + widget.state], GUI_STATE_FREE
+ ; Pour l'instant on le marque juste libre, il n'est pas retirer de l'écran.
+
+ pop es
+ pop eax
+ ret
+
+%include "./gui/lib-logic.asm"
+%include "./gui/lib-draw.asm"
diff --git a/src/gui/draw.asm b/src/gui/lib-draw.asm
similarity index 99%
rename from src/gui/draw.asm
rename to src/gui/lib-draw.asm
index 3db5cd9..e67a82a 100644
--- a/src/gui/draw.asm
+++ b/src/gui/lib-draw.asm
@@ -31,7 +31,7 @@ gui_draw_single_widget:
GFX MOUSE_HIDE ; On cache la souris AVANT de commencer le dessin du widget
- mov ax, GUI_RAM_SEG
+ mov ax, BDA_GUI_WIDGET
mov gs, ax
mov al, [gs:si + widget.state]
@@ -291,12 +291,12 @@ draw_button:
.draw_default_style:
; Bordure extérieure épaisse (2px)
- GFX RECTANGLE, ax, bx, cx, dx, 0
+ ;GFX RECTANGLE, ax, bx, cx, dx, 0
inc ax
inc bx
dec cx
dec dx
- GFX RECTANGLE, ax, bx, cx, dx, 0
+ ;GFX RECTANGLE, ax, bx, cx, dx, 0
; Bordure intérieure fine (après un gap de 1px blanc)
add ax, 2
diff --git a/src/gui/lib.asm b/src/gui/lib-logic.asm
similarity index 51%
rename from src/gui/lib.asm
rename to src/gui/lib-logic.asm
index 1586a44..346a723 100644
--- a/src/gui/lib.asm
+++ b/src/gui/lib-logic.asm
@@ -1,530 +1,3 @@
-; =============================================================================
-; 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 .
-;
-; =============================================================================
-
-; --- Configuration ---
-%define GUI_RAM_SEG 0x080 ; Segment de données UI (Safe: après Stack, avant Heap)
-%define GUI_MAX_WIDGETS 32 ; Nombre max de widgets simultanés
-
-; Dimensions
-%define GUI_CHECKBOX_SIZE 10 ;
-
-; --- 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é
-
-; --- Types de Widgets ---
-%define OBJ_TYPE_LABEL 0
-%define OBJ_TYPE_BUTTON 1
-%define OBJ_TYPE_SLIDER 2
-%define OBJ_TYPE_BUTTON_ROUNDED 3
-%define OBJ_TYPE_CHECKBOX 4
-
-; --- Widgets attributs ---
-%define BUTTON_DEFAULT 0
-%define BUTTON_OK 1
-
-%define SLIDER_HORIZONTAL 1
-%define SLIDER_VERTICAL 2
-
-; =============================================================================
-; SECTION : API ACTIONS
-; =============================================================================
-
-%define OBJ_CREATE 0
-%define OBJ_DESTROY 1
-%define OBJ_GET_STATE 2
-%define OBJ_GET_TYPE 3
-%define OBJ_GET_VAL 4
-%define OBJ_SET_VAL 5
-
-%define OBJ_SET_MODE 6
-%define OBJ_SET_TEXT 7
-
-%define OBJ_GET_PTR 8
-
-%define OBJ_SLIDER_SET_ATTR 9
-
-
-gui_api_table:
- dw gui_api_create
- dw gui_api_destroy
- dw gui_api_get_state
- dw gui_api_get_type
- dw gui_api_get_val
- dw gui_api_set_val
- dw gui_api_set_mode
- dw gui_api_set_text
- dw gui_get_widget_ptr
- dw gui_api_slider_attr
-
-
-; --- 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
- .y resw 1 ; Position Y
- .x2 resw 1 ; Position X2 calculée
- .y2 resw 1 ; Position Y2 calculée
- .w resw 1 ; Largeur
- .h resw 1 ; Hauteur
- .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_drag resw 1 ; adresse de la fonction "on drag"
-
- .attr_mode resb 1 ; 0=None, 1=Horiz, 2=Vert
- .attr_min resw 1 ; Valeur/Position Min
- .attr_max resw 1 ; Valeur/Position Max
- .attr_val resw 1 ; Valeur/Position Actuelle
-
- .thumb_pos resw 1 ; Valeur/Position Actuelle en pixel pour le dessin.
- .thumb_pct resb 1 ; Taille du curseur en % (1-100)
-
- .attr_anchor resw 1 ; interne Offset pour le drag
- alignb 2 ; Alignement mémoire pour performance
-endstruc
-; actuellement 34 octets
-
-%macro GUI 1-*
- %rep %0 - 1
- %rotate -1
- push %1
- %endrep
- %rotate -1
- call word [cs:gui_api_table + ((%1)*2)]
- add sp, (%0 - 1) * 2
-%endmacro
-
-; -----------------------------------------------------------------------------
-; gui_api_slider_attr
-; -----------------------------------------------------------------------------
-%define .id word [bp+4]
-%define .min word [bp+6]
-%define .max word [bp+8]
-%define .val word [bp+10]
-%define .pct word [bp+12]
-gui_api_slider_attr:
- push bp
- mov bp, sp
- push ax
-
- push .id ; ID
- call gui_get_widget_ptr
- jc .err
-
- mov ax, .min
- mov word [gs:si + widget.attr_min], ax
- mov ax, .max
- mov word [gs:si + widget.attr_max], ax
- mov ax, .val
- mov word [gs:si + widget.attr_val], ax
- mov ax, .pct
- mov byte [gs:si + widget.thumb_pct], al
-
- call gui_slider_update_pixels
-
- .err:
- pop ax
- leave
- ret
-%undef .id
-%undef .mode
-
-; -----------------------------------------------------------------------------
-; gui_api_set_mode
-; -----------------------------------------------------------------------------
-%define .id word [bp+4]
-%define .mode word [bp+6]
-gui_api_set_mode:
- push bp
- mov bp, sp
- push ax
-
- push .id
- call gui_get_widget_ptr
- jc .err
-
- mov ax, .mode
- mov byte [gs:si + widget.attr_mode], al
-
- .err:
- pop ax
- leave
- ret
-%undef .id
-%undef .mode
-
-; -----------------------------------------------------------------------------
-; gui_api_set_text
-; -----------------------------------------------------------------------------
-%define .id word [bp+4]
-%define .segmt word [bp+6]
-%define .oft word [bp+8]
-gui_api_set_text:
- push bp
- mov bp, sp
- push ax
-
- push .id
- call gui_get_widget_ptr
- jc .err
-
- mov ax, .segmt
- mov word [gs:si + widget.text_seg], ax
- mov ax, .oft ; Offset du texte
- mov word [gs:si + widget.text_ofs], ax
-
- .err:
- pop ax
- leave
- ret
-%undef .id
-%undef .text_ofs
-%undef .text_seg
-
-; -----------------------------------------------------------------------------
-; gui_api_create
-; Crée un widget et retourne son ID
-; Out: AX = ID ou -1 si erreur
-;
-; parameters : type, x, y, w, h, text_ofs, text_seg
-;
-; -----------------------------------------------------------------------------
-%define .type word [bp+4]
-%define .x word [bp+6]
-%define .y word [bp+8]
-%define .w word [bp+10]
-%define .h word [bp+12]
-gui_api_create:
- push bp
- mov bp, sp
- push gs
-
- mov ax, GUI_RAM_SEG
- mov gs, ax
- call gui_alloc_widget ; Returns GS:SI
- mov ax, -1
- jc .done
-
- ; ID = SI / widget_size
- mov ax, si
- xor dx, dx
- mov cx, widget_size
- div cx
-
- mov bx, .type
- mov byte [gs:si + widget.type], bl
- mov bx, .x
- mov word [gs:si + widget.x], bx
- mov bx, .y
- mov word [gs:si + widget.y], bx
- mov bx, .w
- mov word [gs:si + widget.w], bx
- mov bx, .h
- mov word [gs:si + widget.h], bx
-
- mov byte [gs:si + widget.state], GUI_STATE_NORMAL
- mov byte [gs:si + widget.oldstate], 0
-.done:
- pop gs
- leave
- ret
-%undef .type
-%undef .x
-%undef .y
-%undef .w
-%undef .h
-
-; -----------------------------------------------------------------------------
-; gui_api_get_state
-; Arg1: ID
-; Out: AX = State
-; -----------------------------------------------------------------------------
-%define .id word [bp+4]
-gui_api_get_state:
- push bp
- mov bp, sp
-
- mov ax, .id ; ID
- call gui_get_widget_ptr
- jc .err
-
- xor ax, ax
- mov al, [gs:si + widget.state]
- jmp .done
-
-.err:
- mov ax, -1
-.done:
- leave
- ret
-%undef .id
-
-; -----------------------------------------------------------------------------
-; gui_api_get_type
-; Arg1: ID
-; Out: AX = Type
-; -----------------------------------------------------------------------------
-%define .id word [bp+4]
-gui_api_get_type:
- push bp
- mov bp, sp
-
- mov ax, .id ; ID
- call gui_get_widget_ptr
- jc .err
-
- xor ax, ax
- mov al, [gs:si + widget.type]
- jmp .done
-
-.err:
- mov ax, -1
-.done:
- leave
- ret
-%undef .id
-
-; -----------------------------------------------------------------------------
-; gui_api_get_val
-; Arg1: ID
-; Out: AX = Attr Val
-; -----------------------------------------------------------------------------
-%define .id word [bp+4]
-gui_api_get_val:
- push bp
- mov bp, sp
-
- call gui_get_widget_ptr
- ;jc .err
-
- call gui_slider_update_value
- mov ax, [gs:si + widget.attr_val]
- jmp .done
-
-.err:
- mov ax, -1
-.done:
- leave
- ret
-%undef .id
-
-; -----------------------------------------------------------------------------
-; gui_api_set_val
-; Arg1: ID
-; Arg2: Value
-; -----------------------------------------------------------------------------
-%define .id word [bp+4]
-%define .val word [bp+6]
-gui_api_set_val:
- push bp
- mov bp, sp
-
- mov ax, .id ; ID
- call gui_get_widget_ptr
- jc .err
-
- mov ax, .val
- mov [gs:si + widget.thumb_pos], ax
-
-.err:
- leave
- ret
-%undef .id
-%undef .val
-
-; -----------------------------------------------------------------------------
-; gui_api_destroy
-; Détruit un widget via son ID
-; Arg1: ID
-; Out: AX = 0 (OK), -1 (Error)
-; -----------------------------------------------------------------------------
-%define .id word [bp+4]
-gui_api_destroy:
- push bp
- mov bp, sp
-
- mov ax, .id ; ID
- call gui_get_widget_ptr
- jc .err
-
- call gui_free_widget
- xor ax, ax
- jmp .done
-
-.err:
- mov ax, -1
-.done:
- leave
- ret
-%undef .id
-
-; -----------------------------------------------------------------------------
-; gui_get_widget_ptr
-; Helper interne : Convertit ID en Pointeur
-; In: ID
-; Out: GS:SI = Ptr, CF=1 if error
-; -----------------------------------------------------------------------------
-%define .id word [bp+4]
-gui_get_widget_ptr:
- push bp
- mov bp, sp
- push ax
- push cx
-
- mov ax, .id
- cmp ax, GUI_MAX_WIDGETS
- jae .error
-
- mov cx, widget_size
- xor dx, dx
- mul cx ; AX = Offset
- mov si, ax
-
- mov ax, GUI_RAM_SEG
- mov gs, ax
-
- clc
- jmp .done
- .error:
- stc
- .done:
- pop cx
- pop ax
- leave
- ret
-%undef .id
-
-
-; =============================================================================
-; 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:
- push eax
- push cx
- push es
- push di
-
- mov ax, GUI_RAM_SEG
- mov es, ax
-
- cld
- xor di, di
- mov cx, (widget_size * GUI_MAX_WIDGETS) / 2
- xor ax, ax
- rep stosw ; Plus sûr en mode 16 bits pour l'alignement
-
- pop di
- pop es
- pop cx
- pop eax
- ret
-
-; -----------------------------------------------------------------------------
-; gui_alloc_widget
-; Cherche un slot vide et retourne son adresse
-; Sortie :
-; - Succès : CF=0 (Carry Clear), GS:SI = Offset du widget
-; - Echec : CF=1 (Carry Set), GS:SI = Indéfini (ou 0)
-; -----------------------------------------------------------------------------
-gui_alloc_widget:
- push ax
- push cx
- push bx
-
- mov ax, GUI_RAM_SEG
- mov gs, ax
-
- mov si, 0 ; Début du pool
- mov cx, GUI_MAX_WIDGETS
-
- .loop_find:
- cmp byte [gs: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 [gs:si + widget.state], GUI_STATE_NORMAL ; Marquer comme occupé
- mov byte [gs:si + widget.type], OBJ_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
- mov word [gs:si + widget.event_click], 0
- mov word [gs:si + widget.event_drag], 0
- mov byte [gs:si + widget.thumb_pct], 10 ; 10% par défaut
-
- clc ; Clear Carry Flag
- .done:
- pop bx
- pop cx
- pop ax
- ret
-
-; -----------------------------------------------------------------------------
-; gui_free_widget
-; Libère un widget
-; Entrée : SI = Pointeur widget
-; -----------------------------------------------------------------------------
-gui_free_widget:
- push eax
- push es
-
- mov ax, GUI_RAM_SEG
- mov es, ax
-
- cld
- mov di, si
- mov cx, (widget_size)
- shr cx, 2 ; cx / 4
- xor eax, eax
- rep stosd ; Remplit tout de 0
-
- ; On efface le widget
- mov byte [es:si + widget.state], GUI_STATE_FREE
- ; Pour l'instant on le marque juste libre, il n'est pas retirer de l'écran.
-
- pop es
- pop eax
- ret
-
; =============================================================================
; SECTION : MOTEUR D'ÉVÉNEMENTS (EVENT LOOP)
; =============================================================================
@@ -543,12 +16,12 @@ gui_process_all:
push ds
push gs
- mov ax, GUI_RAM_SEG
+ mov ax, BDA_GUI_WIDGET
mov gs, ax
; Charger l'état de la souris pour toute la passe
push ds
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov ds, ax
mov bl, [BDA_MOUSE + mouse.status]
pop ds
@@ -612,9 +85,9 @@ gui_update_logic:
push ds
push gs
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov ds, ax
- mov ax, GUI_RAM_SEG
+ mov ax, BDA_GUI_WIDGET
mov gs, ax
mov al, byte [gs:si + widget.state]
@@ -962,7 +435,7 @@ gui_logic_slider:
; 4. Target Pos = MouseX - Anchor
; On recharge MouseX depuis la BDA pour être sûr
push ds
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov ds, ax
mov ax, [BDA_MOUSE + mouse.x]
pop ds
@@ -990,7 +463,7 @@ gui_logic_slider:
; 4. Target Pos = MouseY - Anchor
; On recharge MouseY depuis la BDA pour être sûr
push ds
- mov ax, BDA_DATA_SEG
+ mov ax, BDA_CUSTOM_SEG
mov ds, ax
mov ax, [BDA_MOUSE + mouse.y]
pop ds