diff --git a/doc/API.md b/doc/API.md index 392200c..f1a5416 100644 --- a/doc/API.md +++ b/doc/API.md @@ -4,6 +4,7 @@ Le système utilise plusieurs macro *GFX*,*GUI*, etc pour appeler les fonctions Les arguments sont passés sur la pile (Convention C : dernier argument empilé en premier, nettoyage par l'appelant géré par la macro). - * [CGA](/doc/CGA.md) : controleur graphique CGA + * [CGA](/doc/API_CGA.md) : controleur graphique CGA + * [MEMORY](/doc/API_MEMORY.md) : controleur graphique CGA * [MEMORY MAP](/doc/MEMORY_MAP.md) : Plan de la mémoire \ No newline at end of file diff --git a/doc/CGA.md b/doc/API_CGA.md similarity index 100% rename from doc/CGA.md rename to doc/API_CGA.md diff --git a/doc/API_MEMORY.md b/doc/API_MEMORY.md new file mode 100644 index 0000000..9fd2c73 --- /dev/null +++ b/doc/API_MEMORY.md @@ -0,0 +1,38 @@ +# API Gestionnaire de Mémoire (Heap) + +## Description +Ce module fournit un gestionnaire de mémoire dynamique (Heap) simple pour le mode réel x86. Il utilise un algorithme **First-Fit** avec fusion des blocs libres (coalescing) lors de l'allocation pour minimiser la fragmentation. + +Le segment de mémoire utilisé est défini par `MEM_HEAP_SEG` (par défaut `0x2000`, soit l'adresse physique `0x20000`). + +## Structure des Données +Chaque bloc mémoire est précédé d'un en-tête de 6 octets (aligné sur 16 bits) : + +| Offset | Taille | Champ | Description | +| :--- | :--- | :--- | :--- | +| +0 | 1 octet | Status | `0` = Libre, `1` = Alloué | +| +1 | 1 octet | Padding | Réservé pour l'alignement | +| +2 | 2 octets | Size | Taille des données utiles (en octets) | +| +4 | 2 octets | Next | Offset du prochain bloc (0 = Fin de liste) | +| +6 | ... | Data | Données utilisateur | + +## Utilisation +L'interaction se fait principalement via la macro `MEM`. + +```nasm +%include "./common/memory.asm" + +; Initialisation (Obligatoire au démarrage) +MEM MEM_INIT + +; Allocation de 100 octets +MEM MEM_ALLOC, 100 +; AX contient le handle (offset) ou 0 si erreur + +; Utilisation du pointeur +mov bx, ax ; Sauvegarde du handle +MEM MEM_RESOLVE, bx +; ES:DI pointe maintenant vers les données + +; Libération +MEM MEM_FREE, bx diff --git a/src/boot.asm b/src/boot.asm index ec63760..eb7c72f 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -44,6 +44,7 @@ section .text %include "./common/cursor.asm" %include "./common/patterns.asm" %include "./common/generic.asm" +%include "./common/string.asm" ; definition du BDA %include "./common/bda.asm" diff --git a/src/common/memory.asm b/src/common/memory.asm index f02278c..8b5481e 100644 --- a/src/common/memory.asm +++ b/src/common/memory.asm @@ -23,6 +23,7 @@ %define MEM_GET_SIZE 1 %define MEM_FREE 2 %define MEM_RESOLVE 3 +%define MEM_INIT 4 ; --- Macro API --- ; Usage: MEM FUNCTION, [ARG1], [ARG2]... @@ -41,9 +42,11 @@ mem_api_table: dw mem_get_size dw mem_free dw mem_resolve + dw mem_init struc mem_block .status resb 1 ; État du bloc (0=Libre, 1=Occupé) + .pad resb 1 ; Padding pour alignement 16-bits .size resw 1 ; Taille des données (sans le header) .next resw 1 ; Offset du prochain bloc (0 = Fin) endstruc @@ -97,6 +100,12 @@ mem_alloc: push es push di + ; Alignement de la taille demandée sur 2 octets (Word align) + mov ax, .size_requested + test ax, 1 + jz .size_aligned + inc word .size_requested +.size_aligned: mov .curr_ptr, 0 ; On commence la recherche à l'offset 0 mov ax, MEM_HEAP_SEG @@ -208,8 +217,6 @@ mem_free: push bp mov bp, sp - - push es push di push bx @@ -218,6 +225,10 @@ mem_free: test ax, ax jz .done ; Sécurité Handle NULL + ; Sécurité : Vérifier si le handle est dans le segment + cmp ax, MEM_HEAP_SIZE + ja .done + mov bx, MEM_HEAP_SEG mov es, bx diff --git a/src/common/string.asm b/src/common/string.asm new file mode 100644 index 0000000..74b4474 --- /dev/null +++ b/src/common/string.asm @@ -0,0 +1,75 @@ +; ----------------------------------------------------------------------------- +; strcpy +; Copie une chaine ASCIIZ +; ----------------------------------------------------------------------------- +%define .dest_seg word [bp+4] +%define .dest_ofs word [bp+6] +%define .src_seg word [bp+8] +%define .src_ofs word [bp+10] +strcpy: + push bp + mov bp, sp + push ds + push es + push si + push di + + mov ax, .src_seg + mov ds, ax + mov si, .src_ofs + + mov ax, .dest_seg + mov es, ax + mov di, .dest_ofs + +.loop: + lodsb + stosb + test al, al + jnz .loop + + pop di + pop si + pop es + pop ds + leave + ret +%undef .dest_seg +%undef .dest_ofs +%undef .src_seg +%undef .src_ofs + + +; ----------------------------------------------------------------------------- +; strlen +; Calcule la longueur d'une chaine [es:di] +; Out: CX = Length +; ----------------------------------------------------------------------------- +%define .str_seg word [bp+4] +%define .str_ofs word [bp+6] +strlen: + push bp + mov bp, sp + push ax + push es + push di + xor cx, cx + mov ax, .str_seg + mov es, ax + mov di, .str_ofs + +.loop: + cmp byte [es:di], 0 + je .done + inc cx + inc di + jmp .loop + +.done: + pop di + pop es + pop ax + leave + ret +%undef .str_seg +%undef .str_ofs diff --git a/src/gui/draw.asm b/src/gui/draw.asm index 711660c..281422c 100644 --- a/src/gui/draw.asm +++ b/src/gui/draw.asm @@ -56,7 +56,8 @@ gui_draw_single_widget: ; Dispatch selon le type cmp byte [gs:si + widget.type], OBJ_TYPE_LABEL jne .case_1 - jmp .done + call draw_label + jmp .done .case_1: cmp byte [gs:si + widget.type], OBJ_TYPE_SLIDER @@ -451,29 +452,31 @@ draw_checkbox: GFX WRITE, dx, ax ret + +; +; dessine un label (texte simple) +; +draw_label: + GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT + call draw_text + ret + ; ; affiche le texte au centre du widget gs:si ; draw_text: - ; Petit hack pour recentrer le texte après l'effet gras - mov cx, [gs:si + widget.w] - mov dx, [gs:si + widget.h] - - .text: - ; --- Centrage Texte (Simplifié) --- + ; --- Centrage Texte --- mov es, [gs:si + widget.text_seg] mov di, [gs:si + widget.text_ofs] xor cx, cx - .strlen: - cmp byte [es:di], 0 - je .calc - inc cx - inc di - jmp .strlen + push di + push es + call strlen + add sp, 4 ; Fix: Nettoyage de la pile (2 args * 2 octets) .calc: - shl cx, 3 ; Largeur texte px + shl cx, 3 ; Largeur texte px : x = strlen * 8 push ax ; Sauve X original mov ax, [gs:si + widget.w] sub ax, cx