add memory lib + maps
This commit is contained in:
parent
c5510b619f
commit
4b62e01e82
10 changed files with 521 additions and 411 deletions
|
|
@ -8,18 +8,20 @@ The processor starts in Real Mode, addressing 1 MB of memory.
|
|||
|
||||
| Physical Start | Physical End | Size | Description | Segment | Source File |
|
||||
| :--- | :--- | :--- | :--- | :--- | :--- |
|
||||
| **`0x00000`** | **`0x003FF`** | 1 KB | **IVT** (Interrupt Vector Table) | `0x0000` | `boot.asm` / `generic.asm` |
|
||||
| **`0x00400`** | **`0x004FF`** | 256 B | **BDA** (BIOS Data Area) Standard | `0x0040` | `common/bda.asm` |
|
||||
| **`0x00500`** | **`0x005FF`** | ~256 B | **Custom BDA** (Driver Data) | `0x0050` | `common/bda.asm` |
|
||||
| ... | ... | ... | *Free / Reserved* | | |
|
||||
| **`0x08000`** | **`0x09FFF`** | 8 KB | **Stack Bottom** | `0x0800` | `boot.asm` |
|
||||
| **`0x0A000`** | **`0x0AFFF`** | ~4 KB | **GUI RAM** (Widget Allocation) | `0x0A00` | `gui/lib.asm` |
|
||||
| **`0x0B000`** | **`0x17FFE`** | ~52 KB | **Stack Top** (Grows downwards) | `0x0800` | `boot.asm` |
|
||||
| ... | ... | ... | *Conventional RAM Free* | | |
|
||||
| **`0xB8000`** | **`0xBFFFF`** | 32 KB | **VRAM** (CGA / MCGA) | `0xB800` | `drivers/gfx_cgam.asm` |
|
||||
| **`0xC0000`** | **`0xDFFFF`** | 128 KB | **Option ROMs** (e.g., VGA BIOS) | `0xC000` | `boot.asm` |
|
||||
| ... | ... | ... | *System Reserved* | | |
|
||||
| **`0xF0000`** | **`0xFFFFF`** | 64 KB | **System BIOS ROM** (Code) | `0xF000` | `boot.asm` |
|
||||
| **`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`** | **`0x07FFF`** | 30.5 KB | **Free** (Low Memory) | | |
|
||||
| **`0x08000`** | **`0x17FFF`** | 64 KB | **Stack** (Grows downwards) | `0x0800` | `memory.asm` |
|
||||
| **`0x18000`** | **`0x18FFF`** | ~4 KB | **GUI RAM** (Widget Allocation) | `0x0A00` | `gui/lib.asm` |
|
||||
| **`0x19000`** | **`0x9FBFF`** | 539 KB | **Free** (Conventional RAM) | | |
|
||||
| **`0x9FC00`** | **`0x9FFFF`** | 1 KB | **EBDA** (Extended BIOS Data Area) | `0x9FC0` | `memory.asm` |
|
||||
| **`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` | `memory.asm` |
|
||||
| **`0xC0000`** | **`0xDFFFF`** | 128 KB | **Option ROMs** (e.g., VGA BIOS) | `0xC000` | `memory.asm` |
|
||||
| **`0xE0000`** | **`0xEFFFF`** | 64 KB | **System Reserved** (BIOS Extension) | `0xE000` | `Hardware` |
|
||||
| **`0xF0000`** | **`0xFFFFF`** | 64 KB | **System BIOS ROM** (Code) | `0xF000` | `memory.asm` |
|
||||
|
||||
### Detailed Zones
|
||||
|
||||
|
|
@ -50,6 +52,10 @@ The project separates the standard IBM BDA from its own variables to avoid confl
|
|||
* **Even Lines (0, 2, 4...)**: Offset `0x0000` - `0x1F3F` (Bank 0).
|
||||
* **Odd Lines (1, 3, 5...)**: Offset `0x2000` - `0x3F3F` (Bank 1).
|
||||
|
||||
#### VGA RAM & System Reserved
|
||||
* **VGA RAM (`0xA0000`)**: Standard 64 KB memory window for VGA graphics modes. Although this project primarily uses the CGA memory at `0xB8000`, this area is physically present when the VGA hardware is emulated.
|
||||
* **System Reserved (`0xE0000`)**: Reserved memory area, typically used for motherboard BIOS extensions or specific hardware mapping.
|
||||
|
||||
#### ROM
|
||||
* **Option ROMs (`0xC0000`)**: Scanned by `setup_load_rom` to initialize the VGA BIOS.
|
||||
* **System ROM (`0xF0000`)**: Contains the compiled binary code. The Reset Vector is at `0xFFFF0`.
|
||||
|
|
@ -64,18 +70,20 @@ Le processeur démarre en mode réel, adressant 1 Mo de mémoire.
|
|||
|
||||
| Adresse Physique (Début) | Adresse Physique (Fin) | Taille | Description | Segment | Fichier Source |
|
||||
| :--- | :--- | :--- | :--- | :--- | :--- |
|
||||
| **`0x00000`** | **`0x003FF`** | 1 Ko | **IVT** (Interrupt Vector Table) | `0x0000` | `boot.asm` / `generic.asm` |
|
||||
| **`0x00400`** | **`0x004FF`** | 256 o | **BDA** (BIOS Data Area) Standard | `0x0040` | `common/bda.asm` |
|
||||
| **`0x00500`** | **`0x005FF`** | ~256 o | **Custom BDA** (Données Drivers) | `0x0050` | `common/bda.asm` |
|
||||
| ... | ... | ... | *Mémoire Libre / Réservée* | | |
|
||||
| **`0x08000`** | **`0x09FFF`** | 8 Ko | **Bas de la Pile** (Stack Bottom) | `0x0800` | `boot.asm` |
|
||||
| **`0x0A000`** | **`0x0AFFF`** | ~4 Ko | **GUI RAM** (Allocation Widgets) | `0x0A00` | `gui/lib.asm` |
|
||||
| **`0x0B000`** | **`0x17FFE`** | ~52 Ko | **Haut de la Pile** (Stack Top) | `0x0800` | `boot.asm` |
|
||||
| ... | ... | ... | *RAM Conventionnelle Libre* | | |
|
||||
| **`0xB8000`** | **`0xBFFFF`** | 32 Ko | **VRAM** (CGA / MCGA) | `0xB800` | `drivers/gfx_cgam.asm` |
|
||||
| **`0xC0000`** | **`0xDFFFF`** | 128 Ko | **Option ROMs** (ex: VGA BIOS) | `0xC000` | `boot.asm` |
|
||||
| ... | ... | ... | *Réservé Système* | | |
|
||||
| **`0xF0000`** | **`0xFFFFF`** | 64 Ko | **System BIOS ROM** (Code) | `0xF000` | `boot.asm` |
|
||||
| **`0x00000`** | **`0x003FF`** | 1 Ko | **IVT** (Interrupt Vector Table) | `0x0000` | `memory.asm` |
|
||||
| **`0x00400`** | **`0x004FF`** | 256 o | **BDA** (BIOS Data Area) Standard | `0x0040` | `memory.asm` |
|
||||
| **`0x00500`** | **`0x005FF`** | ~256 o | **Custom BDA** (Données Drivers) | `0x0050` | `memory.asm` |
|
||||
| **`0x00600`** | **`0x07FFF`** | 30.5 Ko | **Libre** (Mémoire Basse) | | |
|
||||
| **`0x08000`** | **`0x17FFF`** | 64 KB | **Stack** (Grows downwards) | `0x0800` | `memory.asm` |
|
||||
| **`0x18000`** | **`0x18FFF`** | ~4 KB | **GUI RAM** (Widget Allocation) | `0x0A00` | `gui/lib.asm` |
|
||||
| **`0x19000`** | **`0x9FBFF`** | 539 Ko | **Libre** (RAM Conventionnelle) | | |
|
||||
| **`0x9FC00`** | **`0x9FFFF`** | 1 Ko | **EBDA** (Extended BIOS Data Area) | `0x9FC0` | `memory.asm` |
|
||||
| **`0xA0000`** | **`0xAFFFF`** | 64 Ko | **VGA RAM** (Modes Graphiques) | `0xA000` | `Matériel` |
|
||||
| **`0xB0000`** | **`0xB7FFF`** | 32 Ko | **MDA RAM** (Texte Monochrome) | `0xB000` | `Matériel` |
|
||||
| **`0xB8000`** | **`0xBFFFF`** | 32 Ko | **VRAM** (CGA / MCGA) | `0xB800` | `memory.asm` |
|
||||
| **`0xC0000`** | **`0xDFFFF`** | 128 Ko | **Option ROMs** (ex: VGA BIOS) | `0xC000` | `memory.asm` |
|
||||
| **`0xE0000`** | **`0xEFFFF`** | 64 Ko | **Réservé Système** (Extension BIOS) | `0xE000` | `Matériel` |
|
||||
| **`0xF0000`** | **`0xFFFFF`** | 64 Ko | **System BIOS ROM** (Code) | `0xF000` | `memory.asm` |
|
||||
|
||||
### Détails des Zones
|
||||
|
||||
|
|
@ -106,6 +114,10 @@ Le projet sépare la BDA standard IBM de ses propres variables pour éviter les
|
|||
* **Lignes Paires (0, 2, 4...)** : Offset `0x0000` à `0x1F3F` (Bank 0).
|
||||
* **Lignes Impaires (1, 3, 5...)** : Offset `0x2000` à `0x3F3F` (Bank 1).
|
||||
|
||||
#### VGA RAM & Réservé Système
|
||||
* **VGA RAM (`0xA0000`)** : Fenêtre mémoire standard de 64 Ko pour les modes graphiques VGA. Bien que ce projet utilise principalement la mémoire CGA à `0xB8000`, cette zone est physiquement présente lorsque le matériel VGA est émulé.
|
||||
* **Réservé Système (`0xE0000`)** : Zone mémoire réservée, typiquement utilisée pour les extensions du BIOS de la carte mère ou le mappage de matériel spécifique.
|
||||
|
||||
#### ROM
|
||||
* **Option ROMs (`0xC0000`)** : Espace scanné par `setup_load_rom` pour initialiser le BIOS VGA.
|
||||
* **System ROM (`0xF0000`)** : Contient le code binaire compilé. Le Vecteur de Reset est situé à `0xFFFF0`.
|
||||
189
src/boot.asm
189
src/boot.asm
|
|
@ -38,10 +38,11 @@
|
|||
; times 0xFFFF - ($ - $$) db 0xFF
|
||||
|
||||
section .text
|
||||
bits 16
|
||||
bits 16
|
||||
|
||||
%include "./common/chartable.asm"
|
||||
%include "./common/cursor.asm"
|
||||
%include "./common/patterns.asm"
|
||||
%include "./common/generic.asm"
|
||||
|
||||
; definition du BDA
|
||||
|
|
@ -52,6 +53,8 @@ section .text
|
|||
%include "./drivers/mouse_ps2.asm"
|
||||
%include "./drivers/keyboard_ps2.asm"
|
||||
|
||||
%include "./common/debug_cga.asm"
|
||||
|
||||
; GUI
|
||||
%include "./gui/lib.asm"
|
||||
%include "./gui/draw.asm"
|
||||
|
|
@ -102,123 +105,123 @@ reset:
|
|||
push cs
|
||||
pop ds
|
||||
|
||||
; Init du système GUI
|
||||
call gui_init_system
|
||||
; Init du système GUI
|
||||
call gui_init_system
|
||||
call build_interface
|
||||
|
||||
main_loop:
|
||||
; 2. Moteur GUI (Gère tout : Loop, HitTest, Draw, Callbacks)
|
||||
; DS pointe déjà sur GUI_RAM_SEG
|
||||
call gui_process_all
|
||||
call gui_process_all
|
||||
|
||||
; 3. Afficher souris
|
||||
; GFX MOUSE_MOVE
|
||||
GUI GUI_GET_VAL, 5 ; slider
|
||||
|
||||
jmp main_loop
|
||||
;GFX GOTOXY, 5, 20
|
||||
;call print_word_hex
|
||||
|
||||
jmp main_loop
|
||||
|
||||
; --- Callbacks (Fonctions appelées par le moteur) ---
|
||||
on_click_quit:
|
||||
hlt
|
||||
jmp on_click_quit
|
||||
hlt
|
||||
jmp on_click_quit
|
||||
|
||||
|
||||
build_interface:
|
||||
; --- CRÉATION DYNAMIQUE DES BOUTONS ---
|
||||
; On reste dans CS pour lire les arguments,
|
||||
; mais on configure DS=GUI_RAM_SEG pour l'allocation
|
||||
; --- CRÉATION DYNAMIQUE DES BOUTONS ---
|
||||
; On reste dans CS pour lire les arguments,
|
||||
; mais on configure DS=GUI_RAM_SEG pour l'allocation
|
||||
|
||||
; Créer Bouton 1 "QUITTER"
|
||||
call gui_alloc_widget ; Retourne SI = Pointeur nouveau slot
|
||||
jc .mem_full
|
||||
; Créer Bouton 1 "QUITTER"
|
||||
call gui_alloc_widget ; Retourne SI = Pointeur nouveau slot
|
||||
jc .mem_full
|
||||
|
||||
; Remplir les propriétés
|
||||
mov word [gs:si + widget.x], 10
|
||||
mov word [gs:si + widget.y], 10
|
||||
mov word [gs:si + widget.w], 80
|
||||
mov word [gs:si + widget.h], 16
|
||||
mov word [gs:si + widget.text_ofs], str_quit
|
||||
; mov byte [gs:si + widget.user_id], 1 ; Style "Bouton par défaut" (OK)
|
||||
mov word [gs:si + widget.text_seg], cs ; Texte est dans la ROM
|
||||
mov word [gs:si + widget.event_click], on_click_quit ; Fonction à appeler
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_ROUND_BUTTON
|
||||
; Remplir les propriétés
|
||||
mov word [gs:si + widget.x], 10
|
||||
mov word [gs:si + widget.y], 10
|
||||
mov word [gs:si + widget.w], 80
|
||||
mov word [gs:si + widget.h], 16
|
||||
mov word [gs:si + widget.text_ofs], str_quit
|
||||
; mov byte [gs:si + widget.user_id], 1 ; Style "Bouton par défaut" (OK)
|
||||
mov word [gs:si + widget.text_seg], cs ; Texte est dans la ROM
|
||||
mov word [gs:si + widget.event_click], on_click_quit ; Fonction à appeler
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_ROUND_BUTTON
|
||||
|
||||
; Créer Bouton 2 "HELLO"
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
; Créer Bouton 2 "HELLO"
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
|
||||
mov word [gs:si + widget.x], 100
|
||||
mov word [gs:si + widget.y], 50
|
||||
mov word [gs:si + widget.w], 80
|
||||
mov word [gs:si + widget.h], 16
|
||||
mov word [gs:si + widget.text_ofs], str_hello
|
||||
mov word [gs:si + widget.text_seg], cs
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_ROUND_BUTTON
|
||||
mov word [gs:si + widget.x], 100
|
||||
mov word [gs:si + widget.y], 50
|
||||
mov word [gs:si + widget.w], 80
|
||||
mov word [gs:si + widget.h], 16
|
||||
mov word [gs:si + widget.text_ofs], str_hello
|
||||
mov word [gs:si + widget.text_seg], cs
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_ROUND_BUTTON
|
||||
|
||||
; Créer checkbox 3 "option 1"
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
; Créer checkbox 3 "option 1"
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
|
||||
mov word [gs:si + widget.x], 200
|
||||
mov word [gs:si + widget.y], 50
|
||||
mov word [gs:si + widget.w], 100
|
||||
mov word [gs:si + widget.h], 15
|
||||
mov word [gs:si + widget.text_ofs], str_option1
|
||||
mov word [gs:si + widget.text_seg], cs
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_CHECKBOX
|
||||
; Pas de callback
|
||||
mov word [gs:si + widget.x], 200
|
||||
mov word [gs:si + widget.y], 50
|
||||
mov word [gs:si + widget.w], 100
|
||||
mov word [gs:si + widget.h], 15
|
||||
mov word [gs:si + widget.text_ofs], str_option1
|
||||
mov word [gs:si + widget.text_seg], cs
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_CHECKBOX
|
||||
; Pas de callback
|
||||
|
||||
; Créer checkbox 3 "option 2"
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
; Créer checkbox 3 "option 2"
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
|
||||
mov word [gs:si + widget.x], 200
|
||||
mov word [gs:si + widget.y], 50+16
|
||||
mov word [gs:si + widget.w], 100
|
||||
mov word [gs:si + widget.h], 15
|
||||
mov word [gs:si + widget.text_ofs], str_option2
|
||||
mov word [gs:si + widget.text_seg], cs
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_CHECKBOX
|
||||
mov word [gs:si + widget.x], 200
|
||||
mov word [gs:si + widget.y], 50+16
|
||||
mov word [gs:si + widget.w], 100
|
||||
mov word [gs:si + widget.h], 15
|
||||
mov word [gs:si + widget.text_ofs], str_option2
|
||||
mov word [gs:si + widget.text_seg], cs
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_CHECKBOX
|
||||
|
||||
; Créer checkbox 3 "option 2"
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
; Créer checkbox 3 "option 2"
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
|
||||
mov word [gs:si + widget.x], 200
|
||||
mov word [gs:si + widget.y], 50+16*2
|
||||
mov word [gs:si + widget.w], 100
|
||||
mov word [gs:si + widget.h], 15
|
||||
mov word [gs:si + widget.text_ofs], str_option3
|
||||
mov word [gs:si + widget.text_seg], cs
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_CHECKBOX
|
||||
mov word [gs:si + widget.x], 200
|
||||
mov word [gs:si + widget.y], 50+16*2
|
||||
mov word [gs:si + widget.w], 100
|
||||
mov word [gs:si + widget.h], 15
|
||||
mov word [gs:si + widget.text_ofs], str_option3
|
||||
mov word [gs:si + widget.text_seg], cs
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_CHECKBOX
|
||||
|
||||
; Créer Slider (Drag)
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
mov word [gs:si + widget.x], 10
|
||||
mov word [gs:si + widget.y], 100
|
||||
mov word [gs:si + widget.w], 150
|
||||
mov word [gs:si + widget.h], 12
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_SLIDER
|
||||
mov byte [gs:si + widget.attr_mode], SLIDER_HORIZONTAL
|
||||
mov word [gs:si + widget.attr_min], 10 ; X Min
|
||||
mov word [gs:si + widget.attr_max], 140 ; X Max (Widget.x + W - ThumbW)
|
||||
mov word [gs:si + widget.attr_val], 10 ; Position initiale
|
||||
mov byte [gs:si + widget.thumb_pct], 15 ; Curseur fait 15% de la largeur
|
||||
; Créer Slider (Drag)
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
mov word [gs:si + widget.x], 10
|
||||
mov word [gs:si + widget.y], 100
|
||||
mov word [gs:si + widget.w], 150
|
||||
mov word [gs:si + widget.h], 12
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_SLIDER
|
||||
mov byte [gs:si + widget.attr_mode], SLIDER_HORIZONTAL
|
||||
mov word [gs:si + widget.attr_min], 10 ; X Min
|
||||
mov word [gs:si + widget.attr_max], 140 ; X Max (Widget.x + W - ThumbW)
|
||||
mov word [gs:si + widget.attr_val], 10 ; Position initiale
|
||||
mov byte [gs:si + widget.thumb_pct], 15 ; Curseur fait 15% de la largeur
|
||||
; mov word [gs:si + widget.event_drag], on_drag_slider
|
||||
|
||||
; Créer Slider (Drag)
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
mov word [gs:si + widget.x], 400
|
||||
mov word [gs:si + widget.y], 10
|
||||
mov word [gs:si + widget.w], 16
|
||||
mov word [gs:si + widget.h], 150
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_SLIDER
|
||||
mov byte [gs:si + widget.attr_mode], SLIDER_VERTICAL
|
||||
mov word [gs:si + widget.attr_min], 10 ; X Min
|
||||
mov word [gs:si + widget.attr_max], 140 ; X Max (Widget.x + W - ThumbW)
|
||||
mov word [gs:si + widget.attr_val], 140 ; Position initiale
|
||||
mov byte [gs:si + widget.thumb_pct], 25 ; Curseur fait 15% de la largeur
|
||||
call gui_alloc_widget
|
||||
jc .mem_full
|
||||
mov word [gs:si + widget.x], 400
|
||||
mov word [gs:si + widget.y], 10
|
||||
mov word [gs:si + widget.w], 16
|
||||
mov word [gs:si + widget.h], 150
|
||||
mov byte [gs:si + widget.type], WIDGET_TYPE_SLIDER
|
||||
mov byte [gs:si + widget.attr_mode], SLIDER_VERTICAL
|
||||
mov word [gs:si + widget.attr_min], 10 ; X Min
|
||||
mov word [gs:si + widget.attr_max], 140 ; X Max (Widget.x + W - ThumbW)
|
||||
mov word [gs:si + widget.attr_val], 140 ; Position initiale
|
||||
mov byte [gs:si + widget.thumb_pct], 25 ; Curseur fait 15% de la largeur
|
||||
; mov word [gs:si + widget.event_drag], on_drag_slider
|
||||
|
||||
.mem_full:
|
||||
|
|
|
|||
|
|
@ -29,29 +29,29 @@
|
|||
; =============================================================================
|
||||
|
||||
dump_ram_words:
|
||||
jcxz .done ; Sécurité : si CX=0, on sort
|
||||
jcxz .done ; Sécurité : si CX=0, on sort
|
||||
|
||||
.loop:
|
||||
lodsw ; Charge [DS:SI] dans AX et incrémente SI de 2
|
||||
; Note: x86 est Little Endian. Si RAM = 12 34,
|
||||
; AX vaudra 0x3412.
|
||||
lodsw ; Charge [DS:SI] dans AX et incrémente SI de 2
|
||||
; Note: x86 est Little Endian. Si RAM = 12 34,
|
||||
; AX vaudra 0x3412.
|
||||
|
||||
push cx ; Sauvegarde le compteur de boucle principal
|
||||
push si ; Sauvegarde le pointeur (si cga_putc le modifie)
|
||||
push cx ; Sauvegarde le compteur de boucle principal
|
||||
push si ; Sauvegarde le pointeur (si cga_putc le modifie)
|
||||
|
||||
call print_word_hex ; Affiche AX sous forme "XXXX"
|
||||
call print_word_hex ; Affiche AX sous forme "XXXX"
|
||||
|
||||
; (Optionnel) Ajouter un espace entre chaque mot pour la lisibilité
|
||||
mov al, ' '
|
||||
call cga_putc
|
||||
; (Optionnel) Ajouter un espace entre chaque mot pour la lisibilité
|
||||
mov al, ' '
|
||||
call cga_putc
|
||||
|
||||
pop si ; Restaure SI
|
||||
pop cx ; Restaure CX
|
||||
pop si ; Restaure SI
|
||||
pop cx ; Restaure CX
|
||||
|
||||
loop .loop ; Décrémente CX et boucle si != 0
|
||||
loop .loop ; Décrémente CX et boucle si != 0
|
||||
|
||||
.done:
|
||||
ret
|
||||
ret
|
||||
|
||||
; =============================================================================
|
||||
; Fonction : print_word_hex
|
||||
|
|
@ -60,31 +60,30 @@ dump_ram_words:
|
|||
; Sortie : Affiche "1A2B" via cga_putc
|
||||
; =============================================================================
|
||||
print_word_hex:
|
||||
pusha
|
||||
mov dx, ax
|
||||
mov cx, 4 ; 4 caractères hex dans un mot de 16 bits
|
||||
pusha
|
||||
mov dx, ax
|
||||
mov cx, 4 ; 4 caractères hex dans un mot de 16 bits
|
||||
|
||||
.next_digit:
|
||||
; On veut afficher les bits 12-15 d'abord.
|
||||
; L'astuce est de faire une rotation à gauche de 4 bits.
|
||||
; Le quartet de poids fort se retrouve en bas (bits 0-3).
|
||||
rol dx, 4
|
||||
.next_digit:
|
||||
; On veut afficher les bits 12-15 d'abord.
|
||||
; L'astuce est de faire une rotation à gauche de 4 bits.
|
||||
; Le quartet de poids fort se retrouve en bas (bits 0-3).
|
||||
rol dx, 4
|
||||
|
||||
mov ax, dx ; Copie temporaire
|
||||
and al, 0x0F ; On isole les 4 derniers bits (0 à 15)
|
||||
mov ax, dx ; Copie temporaire
|
||||
and al, 0x0F ; On isole les 4 derniers bits (0 à 15)
|
||||
|
||||
call nibble_to_ascii ; Convertit AL en caractère ASCII
|
||||
call nibble_to_ascii ; Convertit AL en caractère ASCII
|
||||
|
||||
; call cga_putc ; Affiche le caractère
|
||||
xor bx, bx
|
||||
mov bl, al
|
||||
push bx
|
||||
call cga_putc
|
||||
add sp, 2
|
||||
loop .next_digit ; Répète 4 fois
|
||||
xor bx, bx
|
||||
mov bl, al
|
||||
push bx
|
||||
call cga_putc
|
||||
add sp, 2
|
||||
loop .next_digit ; Répète 4 fois
|
||||
|
||||
popa
|
||||
ret
|
||||
popa
|
||||
ret
|
||||
|
||||
; =============================================================================
|
||||
; Fonction : nibble_to_ascii
|
||||
|
|
@ -93,12 +92,12 @@ print_word_hex:
|
|||
; Sortie : AL (caractère '0'-'9' ou 'A'-'F')
|
||||
; =============================================================================
|
||||
nibble_to_ascii:
|
||||
cmp al, 9
|
||||
ja .letter ; Si > 9, c'est une lettre (A-F)
|
||||
cmp al, 9
|
||||
ja .letter ; Si > 9, c'est une lettre (A-F)
|
||||
; Sinon c'est un chiffre : 0x0 -> '0'
|
||||
add al, '0'
|
||||
ret
|
||||
|
||||
add al, '0' ; Sinon c'est un chiffre : 0x0 -> '0'
|
||||
ret
|
||||
|
||||
.letter:
|
||||
add al, 'A' - 10 ; Convertit 10 -> 'A', 11 -> 'B', etc.
|
||||
ret
|
||||
.letter: ; Convertit 10 -> 'A', 11 -> 'B', etc.
|
||||
add al, 'A' - 10
|
||||
ret
|
||||
294
src/common/memory.asm
Normal file
294
src/common/memory.asm
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
; =============================================================================
|
||||
; Project : Custom BIOS / ROM
|
||||
; File : memory.asm
|
||||
; Author : Gemini
|
||||
;
|
||||
; Description :
|
||||
; Gestionnaire de mémoire dynamique (Heap) simple pour mode réel.
|
||||
; Utilise un algorithme "First-Fit" avec fusion des blocs libres (coalescing).
|
||||
;
|
||||
; Layout Mémoire :
|
||||
; [STATUS (1b)] [SIZE (2b)] [NEXT (2b)] [ DATA ... ]
|
||||
;
|
||||
; =============================================================================
|
||||
|
||||
%define MEM_HEAP_SEG 0x2000 ; Segment du tas (Phys: 0x20000)
|
||||
%define MEM_HEAP_SIZE 0x8000 ; Taille totale (32 Ko)
|
||||
|
||||
%define MEM_STATUS_FREE 0
|
||||
%define MEM_STATUS_USED 1
|
||||
|
||||
; --- API Codes ---
|
||||
%define MEM_ALLOC 0
|
||||
%define MEM_GET_SIZE 1
|
||||
%define MEM_FREE 2
|
||||
%define MEM_RESOLVE 3
|
||||
|
||||
; --- Macro API ---
|
||||
; Usage: MEM FUNCTION, [ARG1], [ARG2]...
|
||||
%macro MEM 1-*
|
||||
%rep %0 - 1
|
||||
%rotate -1
|
||||
push %1
|
||||
%endrep
|
||||
%rotate -1
|
||||
call word [cs:mem_api_table + ((%1)*2)]
|
||||
add sp, (%0 - 1) * 2
|
||||
%endmacro
|
||||
|
||||
mem_api_table:
|
||||
dw mem_alloc
|
||||
dw mem_get_size
|
||||
dw mem_free
|
||||
dw mem_resolve
|
||||
|
||||
struc mem_block
|
||||
.status resb 1 ; État du bloc (0=Libre, 1=Occupé)
|
||||
.size resw 1 ; Taille des données (sans le header)
|
||||
.next resw 1 ; Offset du prochain bloc (0 = Fin)
|
||||
endstruc
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; mem_init
|
||||
; Initialise le gestionnaire de mémoire.
|
||||
; Crée un seul gros bloc libre couvrant tout le segment.
|
||||
; -----------------------------------------------------------------------------
|
||||
mem_init:
|
||||
push ax
|
||||
push es
|
||||
push di
|
||||
|
||||
mov ax, MEM_HEAP_SEG
|
||||
mov es, ax
|
||||
xor di, di
|
||||
|
||||
; Initialisation du premier bloc (Header)
|
||||
mov byte [es:di + mem_block.status], MEM_STATUS_FREE
|
||||
|
||||
; Taille disponible = Total - TailleHeader
|
||||
mov ax, MEM_HEAP_SIZE
|
||||
sub ax, mem_block_size
|
||||
mov word [es:di + mem_block.size], ax
|
||||
|
||||
mov word [es:di + mem_block.next], 0
|
||||
|
||||
pop di
|
||||
pop es
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; mem_alloc
|
||||
; Alloue un bloc de mémoire.
|
||||
;
|
||||
; Stack: [BP+4] = Taille demandée (word)
|
||||
; Output: AX = Handle (Offset du bloc de données) ou 0 si échec
|
||||
; -----------------------------------------------------------------------------
|
||||
mem_alloc:
|
||||
push bp
|
||||
mov bp, sp
|
||||
sub sp, 2
|
||||
|
||||
%define .curr_ptr word [bp-2]
|
||||
%define .size_requested word [bp+4]
|
||||
|
||||
push bx
|
||||
push cx
|
||||
push es
|
||||
push di
|
||||
|
||||
mov .curr_ptr, 0 ; On commence la recherche à l'offset 0
|
||||
|
||||
mov ax, MEM_HEAP_SEG
|
||||
mov es, ax
|
||||
|
||||
.scan_loop:
|
||||
mov di, .curr_ptr ; DI = Ptr courant
|
||||
|
||||
; 1. Le bloc est-il LIBRE ?
|
||||
cmp byte [es:di + mem_block.status], MEM_STATUS_FREE
|
||||
jne .next_block
|
||||
|
||||
; 2. Tentative de FUSION (Coalescing) avec les blocs suivants
|
||||
.try_merge:
|
||||
mov bx, [es:di + mem_block.next]
|
||||
cmp bx, 0
|
||||
je .check_size ; Pas de suivant, on vérifie la taille
|
||||
|
||||
; Si le suivant est aussi libre, on fusionne
|
||||
cmp byte [es:bx + mem_block.status], MEM_STATUS_FREE
|
||||
jne .check_size
|
||||
|
||||
; Nouvelle Taille = TailleActuelle + Header + TailleSuivant
|
||||
mov ax, [es:bx + mem_block.size]
|
||||
add ax, mem_block_size
|
||||
add [es:di + mem_block.size], ax
|
||||
|
||||
; Mise à jour du chainage (saute le bloc fusionné)
|
||||
mov ax, [es:bx + mem_block.next]
|
||||
mov [es:di + mem_block.next], ax
|
||||
|
||||
jmp .try_merge ; On boucle pour voir si le suivant du suivant est libre
|
||||
|
||||
.check_size:
|
||||
; 3. Vérifier si la taille est suffisante
|
||||
mov ax, .size_requested ; Taille demandée (Argument)
|
||||
cmp [es:di + mem_block.size], ax
|
||||
jb .next_block ; Trop petit
|
||||
|
||||
; 4. Allocation (Split si possible)
|
||||
; Calculer l'espace restant
|
||||
mov cx, [es:di + mem_block.size]
|
||||
sub cx, ax ; CX = Reste
|
||||
|
||||
; Peut-on créer un nouveau bloc dans le reste ? (Header + au moins 1 octet)
|
||||
cmp cx, mem_block_size + 1
|
||||
jb .allocate_full
|
||||
|
||||
; --- SPLIT ---
|
||||
; Marquer le bloc actuel comme utilisé avec la taille demandée
|
||||
mov byte [es:di + mem_block.status], MEM_STATUS_USED
|
||||
mov [es:di + mem_block.size], ax
|
||||
|
||||
; Créer le nouveau header dans l'espace restant
|
||||
mov bx, di
|
||||
add bx, mem_block_size
|
||||
add bx, ax ; BX = Offset du nouveau bloc
|
||||
|
||||
mov byte [es:bx + mem_block.status], MEM_STATUS_FREE
|
||||
|
||||
sub cx, mem_block_size ; Taille utile du nouveau bloc
|
||||
mov [es:bx + mem_block.size], cx
|
||||
|
||||
; Insérer dans la liste chainée
|
||||
mov dx, [es:di + mem_block.next]
|
||||
mov [es:bx + mem_block.next], dx
|
||||
mov [es:di + mem_block.next], bx
|
||||
|
||||
jmp .success
|
||||
|
||||
.allocate_full:
|
||||
; On prend tout le bloc sans le couper
|
||||
mov byte [es:di + mem_block.status], MEM_STATUS_USED
|
||||
|
||||
.success:
|
||||
; Retourner le handle (Offset des DONNÉES = DI + Header)
|
||||
mov ax, di
|
||||
add ax, mem_block_size
|
||||
jmp .done
|
||||
|
||||
.next_block:
|
||||
; Passer au bloc suivant
|
||||
mov di, .curr_ptr
|
||||
mov ax, [es:di + mem_block.next]
|
||||
mov .curr_ptr, ax
|
||||
cmp ax, 0
|
||||
jne .scan_loop
|
||||
|
||||
; Échec : Plus de mémoire ou fragmentation trop élevée
|
||||
xor ax, ax
|
||||
|
||||
.done:
|
||||
pop di
|
||||
pop es
|
||||
pop cx
|
||||
pop bx
|
||||
%undef .curr_ptr
|
||||
%undef .size_requested
|
||||
leave ; Restaure SP et BP
|
||||
ret
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; mem_free
|
||||
; Libère un bloc mémoire.
|
||||
; Stack: [BP+4] = Handle (word)
|
||||
; -----------------------------------------------------------------------------
|
||||
mem_free:
|
||||
push bp
|
||||
mov bp, sp
|
||||
|
||||
%define .handle word [bp+4]
|
||||
|
||||
push es
|
||||
push di
|
||||
push bx
|
||||
|
||||
mov ax, .handle ; Handle
|
||||
test ax, ax
|
||||
jz .done ; Sécurité Handle NULL
|
||||
|
||||
mov bx, MEM_HEAP_SEG
|
||||
mov es, bx
|
||||
|
||||
; Retrouver le header (Handle - HeaderSize)
|
||||
mov di, ax
|
||||
sub di, mem_block_size
|
||||
|
||||
; Marquer simplement comme libre (le coalescing se fera au prochain alloc)
|
||||
mov byte [es:di + mem_block.status], MEM_STATUS_FREE
|
||||
|
||||
.done:
|
||||
pop bx
|
||||
pop di
|
||||
pop es
|
||||
%undef .handle
|
||||
leave
|
||||
ret
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; mem_get_size
|
||||
; Retourne la taille utile d'un bloc.
|
||||
; Stack: [BP+4] = Handle (word)
|
||||
; Output: AX = Taille
|
||||
; -----------------------------------------------------------------------------
|
||||
mem_get_size:
|
||||
push bp
|
||||
mov bp, sp
|
||||
|
||||
%define .handle word [bp+4]
|
||||
|
||||
push es
|
||||
push di
|
||||
|
||||
mov ax, .handle ; Handle
|
||||
test ax, ax
|
||||
jz .error
|
||||
|
||||
mov bx, MEM_HEAP_SEG
|
||||
mov es, bx
|
||||
|
||||
mov di, ax
|
||||
sub di, mem_block_size
|
||||
|
||||
mov ax, [es:di + mem_block.size]
|
||||
jmp .done
|
||||
|
||||
.error:
|
||||
xor ax, ax
|
||||
.done:
|
||||
pop di
|
||||
pop es
|
||||
%undef .handle
|
||||
leave
|
||||
ret
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; mem_resolve
|
||||
; Convertit un handle en pointeur complet Segment:Offset.
|
||||
; Stack: [BP+4] = Handle (word)
|
||||
; Output: DX:AX = Segment:Offset
|
||||
; ES:DI = Segment:Offset (pour utilisation immédiate avec stos/movs)
|
||||
; -----------------------------------------------------------------------------
|
||||
mem_resolve:
|
||||
push bp
|
||||
mov bp, sp
|
||||
|
||||
mov ax, [bp+4] ; Handle
|
||||
mov dx, MEM_HEAP_SEG
|
||||
mov es, dx
|
||||
mov di, ax ; L'offset est le handle lui-même
|
||||
|
||||
; DX contient déjà le segment, AX contient déjà l'offset
|
||||
|
||||
leave
|
||||
ret
|
||||
21
src/common/patterns.asm
Normal file
21
src/common/patterns.asm
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
; =============================================================================
|
||||
; SECTION : PATTERNS & FILL
|
||||
; https://paulsmith.github.io/classic-mac-patterns/
|
||||
; =============================================================================
|
||||
;
|
||||
; pattern ID
|
||||
%define PATTERN_BLACK 0
|
||||
%define PATTERN_GRAY_DARK 1
|
||||
%define PATTERN_GRAY_MID 2
|
||||
%define PATTERN_GRAY_LIGHT 3
|
||||
%define PATTERN_WHITE_LIGHT 4
|
||||
%define PATTERN_WHITE 5
|
||||
|
||||
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)
|
||||
|
|
@ -106,29 +106,6 @@ graph_driver:
|
|||
dw cga_mouse_show ; déplacement du curseur
|
||||
dw cga_mouse_cursor_move ; déplacement du curseur
|
||||
|
||||
|
||||
; =============================================================================
|
||||
; SECTION : PATTERNS & FILL
|
||||
; https://paulsmith.github.io/classic-mac-patterns/
|
||||
; =============================================================================
|
||||
;
|
||||
; pattern ID
|
||||
%define PATTERN_BLACK 0
|
||||
%define PATTERN_GRAY_DARK 1
|
||||
%define PATTERN_GRAY_MID 2
|
||||
%define PATTERN_GRAY_LIGHT 3
|
||||
%define PATTERN_WHITE_LIGHT 4
|
||||
%define PATTERN_WHITE 5
|
||||
|
||||
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)
|
||||
|
||||
; ------------------------------------------------------------
|
||||
; initialise le mode graphique (via l'int 10h)
|
||||
;
|
||||
|
|
|
|||
|
|
@ -1,196 +0,0 @@
|
|||
; =======================
|
||||
; API
|
||||
; =======================
|
||||
%define MEM_INIT 0
|
||||
%define MEM_DETECT 2
|
||||
%define MEM_ALLOC 4
|
||||
%define MEM_FREE 6
|
||||
%define MEM_DUMP_RESET 8
|
||||
%define MEM_DUMP_NEXT 10
|
||||
|
||||
memory_api:
|
||||
dw mem_init
|
||||
dw mem_detect
|
||||
dw mem_alloc
|
||||
dw mem_free
|
||||
dw mem_dump_reset
|
||||
dw mem_dump_next
|
||||
|
||||
; =======================
|
||||
; Contexte en RAM (DS = CTX_SEG)
|
||||
; =======================
|
||||
heap_seg dw 0
|
||||
heap_start dw 0
|
||||
heap_end dw 0
|
||||
free_head dw 0
|
||||
dump_cursor dw 0
|
||||
|
||||
; =======================
|
||||
; Constantes
|
||||
; =======================
|
||||
%define HDR_SIZE 8
|
||||
%define FTR_SIZE 2
|
||||
%define MIN_BLK 12 ; aligné (>= HDR+FTR)
|
||||
%define FLAG_USED 1
|
||||
|
||||
%define MEM_SEG_DEB 0x0800 ; 0x0800:0000 = 0x8000 (32KB) évite IVT/BDA + stack 7C00
|
||||
%define MEM_SEG_END 0xA000 ; 0xA000:0000 = 0xA0000 (début zone vidéo)
|
||||
%define MEM_SEG_STEP 0x0040 ; 1KB = 0x400 bytes = 0x40 paragraphs
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Détection RAM conventionnelle
|
||||
; Teste la RAM de MEM_SEG_DEB -> MEM_SEG_END (0xA000, 640KB), par pas de 1KB.
|
||||
; Méthode: sauvegarde 1 mot, écrit 2 patterns, relit, restaure.
|
||||
;
|
||||
; Résultats:
|
||||
; AX = taille détectée en Ko (KB) à partir de 0 jusqu’au “top conventionnel”
|
||||
; DX = top_segment (segment du premier Ko NON valide) (optionnel)
|
||||
;
|
||||
; Précautions:
|
||||
; - Ne testez PAS une zone où se trouve votre pile / variables.
|
||||
; - Si votre pile est à 0000:7C00 (phys 0x7C00), commencez au moins à 0x0800.
|
||||
; - Ne testez pas au-delà de MEM_SEG_END (0xA000: début VGA/vidéo).
|
||||
; ---------------------------------------------------------------------------
|
||||
memory_setup:
|
||||
xor ax, ax ; AX = compteur KB trouvés
|
||||
mov dx, MEM_SEG_DEB ; DX = segment courant testé
|
||||
mov cx, MEM_SEG_END ; CX = segment fin (exclu)
|
||||
xor di, di ; tester au début du bloc 1KB: ES:0000
|
||||
|
||||
.loop_seg:
|
||||
cmp dx, cx
|
||||
jae .done
|
||||
mov es, dx
|
||||
|
||||
; sauvegarder le mot existant
|
||||
mov bx, [es:di]
|
||||
|
||||
; pattern 1
|
||||
mov word [es:di], 0x55AA
|
||||
cmp word [es:di], 0x55AA
|
||||
jne .fail_restore
|
||||
|
||||
; pattern 2 (inverse)
|
||||
mov word [es:di], 0xAA55
|
||||
cmp word [es:di], 0xAA55
|
||||
jne .fail_restore
|
||||
|
||||
; restaurer
|
||||
mov [es:di], bx
|
||||
|
||||
; OK: avancer d’1KB
|
||||
inc ax ; +1KB valide
|
||||
add dx, MEM_SEG_STEP
|
||||
jmp .loop_seg
|
||||
|
||||
.fail_restore:
|
||||
; restaurer avant de sortir
|
||||
mov [es:di], bx
|
||||
|
||||
.done:
|
||||
; AX contient le nb de KB valides *à partir de MEM_SEG_DEB*.
|
||||
; Si vous voulez une taille “depuis 0KB”, ajoutez MEM_SEG_DEB*16/1024 = MEM_SEG_DEB/64.
|
||||
;
|
||||
; base_kb = MEM_SEG_DEB / 0x0040 (car 1KB = 0x40 segments)
|
||||
mov bx, MEM_SEG_DEB
|
||||
shr bx, 6 ; /64 = /0x40 => KB de base
|
||||
add ax, bx ; AX = taille conventionnelle totale en KB (approx. 0..640)
|
||||
; DX = segment du premier bloc NON valide (top)
|
||||
; DX est déjà positionné (segment courant)
|
||||
|
||||
; stocker l'information dans le BDA
|
||||
mov bx, BDA_SEGMENT
|
||||
mov ds, bx
|
||||
mov [BDA_INFO_MEM_SIZE], ax
|
||||
mov [BDA_INFO_MEM_SEG], dx
|
||||
|
||||
ret
|
||||
|
||||
; -----------------------
|
||||
; mem_detect
|
||||
; AX=conv_kb, DX=ebda_seg, CF=0
|
||||
; -----------------------
|
||||
mem_detect:
|
||||
push ds
|
||||
xor ax, ax
|
||||
int 12h ; AX = KiB conventionnelle
|
||||
mov bx, ax ; conv_kb -> BX
|
||||
|
||||
; Lire EBDA segment depuis BDA:040Eh
|
||||
; On suppose DS peut être changé temporairement
|
||||
mov ax, 0x0040
|
||||
mov ds, ax
|
||||
mov dx, [0x000E] ; EBDA segment (souvent 0x9FC0 etc), 0 si absent
|
||||
pop ds
|
||||
|
||||
mov ax, bx ; AX=conv_kb
|
||||
clc
|
||||
ret
|
||||
|
||||
; -----------------------
|
||||
; mem_init
|
||||
; Entrée (proposée) :
|
||||
; AX = HEAP_SEG (0 => auto)
|
||||
; BX = heap_start_offset (0 => défaut 0x0200)
|
||||
; Sortie:
|
||||
; CF=0 ok, CF=1 err
|
||||
; -----------------------
|
||||
mem_init:
|
||||
; 1) déterminer heap_seg et heap_end en évitant EBDA
|
||||
; 2) créer 1 seul bloc libre [heap_start..heap_end)
|
||||
|
||||
; Implémentation typique:
|
||||
; - si AX=0 : choisir un segment RAM “safe” (ex: 0x7000) OU segment du contexte
|
||||
; - heap_start = (BX!=0 ? BX : 0x0200)
|
||||
; - heap_end = 0xFFFE (ou plus petit selon usage)
|
||||
|
||||
; Puis initialiser le 1er bloc libre:
|
||||
; [heap_start+0] size = heap_end-heap_start
|
||||
; [heap_start+2] flags=0
|
||||
; [heap_start+4] next_free=0
|
||||
; [heap_start+6] prev_free=0
|
||||
; footer à (heap_start+size-2)
|
||||
|
||||
clc
|
||||
ret
|
||||
|
||||
; -----------------------
|
||||
; mem_alloc
|
||||
; CX = bytes demandés
|
||||
; Sortie: ES=heap_seg, DI=payload, CF=0 si ok sinon CF=1
|
||||
; -----------------------
|
||||
mem_alloc:
|
||||
; need = align2(CX) + HDR_SIZE + FTR_SIZE
|
||||
; parcourir free list (first-fit)
|
||||
; split si reste >= MIN_BLK
|
||||
; marquer alloué, unlink free list
|
||||
; ES=heap_seg, DI=blk_off + HDR_SIZE
|
||||
ret
|
||||
|
||||
; -----------------------
|
||||
; mem_free
|
||||
; Entrée: ES:DI = payload
|
||||
; Sortie: CF=0 ok sinon CF=1
|
||||
; -----------------------
|
||||
mem_free:
|
||||
; blk_off = DI - HDR_SIZE
|
||||
; vérifier, marquer libre
|
||||
; coalescer prev/next via footer/header
|
||||
; relinker dans free list
|
||||
ret
|
||||
|
||||
; -----------------------
|
||||
; mem_dump_reset / mem_dump_next
|
||||
; -----------------------
|
||||
mem_dump_reset:
|
||||
mov ax, [heap_start]
|
||||
mov [dump_cursor], ax
|
||||
clc
|
||||
ret
|
||||
|
||||
mem_dump_next:
|
||||
; si dump_cursor >= heap_end => CF=1
|
||||
; lire size/flags à dump_cursor
|
||||
; renvoyer AL état, CX taille payload, DI=offset header, ES=heap_seg
|
||||
; dump_cursor += size
|
||||
ret
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
; =============================================================================
|
||||
; Project : Custom BIOS / ROM
|
||||
; File : gui_lib.asm
|
||||
; File : gui/draw.asm
|
||||
; Author : frater
|
||||
;
|
||||
; License : GNU General Public License v3.0 or later (GPL-3.0+)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
; =============================================================================
|
||||
; Project : Custom BIOS / ROM
|
||||
; File : gui_lib.asm
|
||||
; File : gui/lib.asm
|
||||
; Author : frater
|
||||
;
|
||||
; License : GNU General Public License v3.0 or later (GPL-3.0+)
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
; =============================================================================
|
||||
|
||||
; --- Configuration ---
|
||||
%define GUI_RAM_SEG 0x0A00 ; Segment de données UI
|
||||
%define GUI_RAM_SEG 0x1800 ; Segment de données UI (Safe: après Stack, avant Heap)
|
||||
%define GUI_MAX_WIDGETS 32 ; Nombre max de widgets simultanés
|
||||
|
||||
; Dimensions
|
||||
|
|
@ -47,6 +47,23 @@
|
|||
%define SLIDER_HORIZONTAL 1
|
||||
%define SLIDER_VERTICAL 2
|
||||
|
||||
; =============================================================================
|
||||
; SECTION : API ACTIONS
|
||||
; =============================================================================
|
||||
|
||||
%define GUI_CREATE 0
|
||||
%define GUI_DESTROY 1
|
||||
%define GUI_GET_STATE 2
|
||||
%define GUI_GET_TYPE 3
|
||||
%define GUI_GET_VAL 4
|
||||
|
||||
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
|
||||
|
||||
; --- Structure d'un OBJET (Bouton, etc) ---
|
||||
struc widget
|
||||
.state resb 1 ; État (0=libre, >0=utilisé)
|
||||
|
|
@ -78,10 +95,6 @@ struc widget
|
|||
alignb 2 ; Alignement mémoire pour performance
|
||||
endstruc
|
||||
|
||||
; =============================================================================
|
||||
; SECTION : API ACTIONS
|
||||
; =============================================================================
|
||||
|
||||
%macro GUI 1-*
|
||||
%rep %0 - 1
|
||||
%rotate -1
|
||||
|
|
@ -92,19 +105,6 @@ endstruc
|
|||
add sp, (%0 - 1) * 2
|
||||
%endmacro
|
||||
|
||||
%define GUI_CREATE 0
|
||||
%define GUI_DESTROY 1
|
||||
%define GUI_GET_STATE 2
|
||||
%define GUI_GET_TYPE 3
|
||||
%define GUI_GET_VAL 4
|
||||
|
||||
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
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; gui_api_create
|
||||
; Crée un widget et retourne son ID
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
; =============================================================================
|
||||
; Project : Custom BIOS / ROM
|
||||
; File : gui_window.asm
|
||||
; File : gui/window.asm
|
||||
; Author : frater
|
||||
;
|
||||
; License : GNU General Public License v3.0 or later (GPL-3.0+)
|
||||
|
|
|
|||
Loading…
Reference in a new issue