diff --git a/.gitignore b/.gitignore index 7a5bd8d..4a395c6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ build/ gfx/ roms/ tools/ -doc/generated/ \ No newline at end of file +doc/generated/ +fonts/ diff --git a/doc/API.md b/doc/API.md index 1b3dff5..f1a5416 100644 --- a/doc/API.md +++ b/doc/API.md @@ -4,7 +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/API_CGA.md) : controleur graphique CGA - * [MEMORY](doc/API_MEMORY.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 + * [MEMORY MAP](/doc/MEMORY_MAP.md) : Plan de la mémoire \ No newline at end of file diff --git a/doc/assets/screenshot.md b/doc/assets/screenshot.md index de5bd62..a221cc3 100644 --- a/doc/assets/screenshot.md +++ b/doc/assets/screenshot.md @@ -1,11 +1,12 @@ -![Screenshot of the boot + text test](doc/assets/Capture-2026-01-29-210122.png) + +![Screenshot of the boot + text test](/doc/assets/Capture-2026-01-29-210122.png) Screenshot of early boot version + Text functions -![Screenshot WIP - Buttons & Sliders](doc/assets/Capture-2026-02-03-213148.png) +![Screenshot WIP - Buttons & Sliders](/doc/assets/Capture-2026-02-03-213148.png) Screenshot of early buttons & sliders -![Screenshot WIP - Rounded Buttons & Checkboxes ](doc/assets/Capture-2026-02-06-232336.png) +![Screenshot WIP - Rounded Buttons & Checkboxes ](/doc/assets/Capture-2026-02-06-232336.png) Screenshot of rounded buttons & checkboxes \ No newline at end of file diff --git a/readme.md b/readme.md index edb301b..ce02a66 100644 --- a/readme.md +++ b/readme.md @@ -10,15 +10,15 @@ This project aims to design and implement a **PC-compatible BIOS/ROM from scratc Rather than booting an operating system from disk, the PC starts **directly from the ROM** into a **minimalist graphical interface**, using **CGA High-Resolution Monochrome (640×200)** mode. -![Screenshot 86Box](doc/assets/Capture-86Box.png) +![Screenshot 86Box](/doc/assets/Capture-86Box.png) Screenshot from a CGA Hi res test on 86Box. -![Screenshot QEMU VGA](doc/assets/Screenshot-VGA.png) +![Screenshot QEMU VGA](/doc/assets/Screenshot-VGA.png) Screenshot from a VGA Hi res test on QEMU with "italic Font". -You may want to get a look at the [Older screenshots](doc/assets/screenshot.md) +You may want to get a look at the [Older screenshots](/doc/assets/screenshot.md) The project is intentionally educational, experimental, and minimalist. @@ -80,13 +80,13 @@ To build and run this project, the following tools and components are required: ### API -Get a look at the [API](doc/API.md) for more information. +Get a look at the [API](/doc/API.md) for more information. --- ### Build and Run -[read detailed step to compile an run](doc/build.md) +[read detailed step to compile an run](/doc/build.md) ### Non-Goals @@ -108,15 +108,15 @@ Ce projet consiste à concevoir et développer un **BIOS/ROM PC compatible enti Au lieu de charger un système d’exploitation depuis un disque, le PC **démarre directement depuis la ROM** vers une **interface graphique minimaliste**, utilisant le mode **CGA Haute Résolution Monochrome (640×200)**. -![Screenshot 86Box](doc/assets/Capture-86Box.png) +![Screenshot 86Box](/doc/assets/Capture-86Box.png) Screenshot d'un EcranCGA Hi res test sur 86Box. -![Screenshot QEMU VGA](doc/assets/Screenshot-VGA.png) +![Screenshot QEMU VGA](/doc/assets/Screenshot-VGA.png) screenshot d'un ecran VGA Hi res test avec police Italique sur QEMU. -You may want to get a look at the [Older screenshots](doc/assets/screenshot.md) +You may want to get a look at the [Older screenshots](/doc/assets/screenshot.md) --- @@ -176,14 +176,14 @@ Le BIOS VGA standard de QEMU (vgabios.bin) est utilisé pour initialiser le mat ### API -Consultez la documentation de l'[API](doc/API.md) pour plus d'informations. +Consultez la documentation de l'[API](/doc/API.md) pour plus d'informations. --- ### Compilation et exécution -[read detailed step to compile an run](doc/build.md) +[read detailed step to compile an run](/doc/build.md) ### Hors périmètre diff --git a/src/boot.asm b/src/boot.asm index 5b6ef65..43958f0 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -204,12 +204,19 @@ main_loop: mov .value, 0xFADE .loop: - call gui_process_all - GUI OBJ_GET_VAL, .my_slider - mov .value, ax - cmp ax,.oldval - je .loop + ISADBG ISA_RIGHT, 0x11 + + call gui_process_all + + ; --- TRACE 12 : GUI traitée --- + ISADBG ISA_RIGHT, 0x12 + + ; GUI OBJ_GET_VAL, .my_slider + ;mov .value, ax + + ;cmp ax,.oldval + ;je .loop ; debug ;mov .oldval, ax @@ -228,9 +235,9 @@ main_loop: ;mov al, 0x00 ;int 0x10 - mov dx, CRTC_COLOR_DATA - and ax, 0x001F - out dx, ax + ;mov dx, CRTC_COLOR_DATA + ;and ax, 0x001F + ;out dx, ax jmp .loop leave diff --git a/src/common/bda.asm b/src/common/bda.asm index 68aa575..d9d9b7b 100644 --- a/src/common/bda.asm +++ b/src/common/bda.asm @@ -30,7 +30,9 @@ %define PTR_MOUSE 0x0000 %define PTR_GFX (PTR_MOUSE + mouse_size) +%define PTR_GUI (PTR_GFX + gfx_size) +; ; video related information (compatible with VGA bios) %define BDA_VIDEO_CURR_MODE 0x0049 %define BDA_VIDEO_COLUMNS 0x004A @@ -76,7 +78,10 @@ struc gfx .cur_offset resw 1 ; offset calculé pour le prochain caractère .cur_line_ofs resw 1 ; "interligne" +2000h ou -2000h .cur_shift resb 1 ; x&7 (0..7) +endstruc +struc gui + .wm_active_window_id resb 1 ; ID de la fenêtre active endstruc ; ----------------------------------------------------------------------------------- diff --git a/src/drivers/mouse_ps2.asm b/src/drivers/mouse_ps2.asm index 9b3c9ab..ab40dd9 100644 --- a/src/drivers/mouse_ps2.asm +++ b/src/drivers/mouse_ps2.asm @@ -291,6 +291,7 @@ isr_mouse_handler: in al, i8042_PS2_DATA ; lire octet souris movzx bx, byte [PTR_MOUSE + mouse.idx] + cmp bl,0 jne .read_packet @@ -299,6 +300,7 @@ isr_mouse_handler: jz .done_eoi ; allignement erroné .read_packet: + mov byte [PTR_MOUSE + mouse.buffer + bx], al inc byte [PTR_MOUSE + mouse.idx] @@ -371,9 +373,8 @@ isr_mouse_handler: .done: ; update la position du curseur sur l'écran - ; en ce moment c'est commented out (debug) - ; call cga_mouse_cursor_move GFX MOUSE_MOVE + .done_eoi: mov al, 0x20 out i8259_SLAVE_CMD, al ; EOI PIC esclave diff --git a/src/gui/lib-api.asm b/src/gui/lib-api.asm index d173e67..dd33295 100644 --- a/src/gui/lib-api.asm +++ b/src/gui/lib-api.asm @@ -86,11 +86,11 @@ gui_api_table: ; --- Structure d'un OBJET (Bouton, etc) --- struc widget - .header resw 1 ; HEADER .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 + .win_id resb 1 ; ID de la fenêtre propriétaire .x resw 1 ; Position Xevent_drag .y resw 1 ; Position Y .w resw 1 ; Largeur @@ -133,17 +133,18 @@ endstruc ; ----------------------------------------------------------------------------- ; 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 gs push ax + push si mov ax, .id call gui_get_widget_ptr_internal @@ -161,23 +162,29 @@ gui_api_slider_attr: call gui_slider_update_pixels .err: + pop si pop ax pop gs leave + %undef .id + %undef .min + %undef .max + %undef .val + %undef .pct 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 gs push ax + push si mov ax, .id call gui_get_widget_ptr_internal @@ -187,24 +194,26 @@ gui_api_set_mode: mov byte [gs:si + widget.attr_mode], al .err: - pop gs + pop si pop ax + pop gs leave + %undef .id + %undef .mode 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 gs push ax + push si mov ax, .id call gui_get_widget_ptr_internal @@ -216,13 +225,15 @@ gui_api_set_text: mov word [gs:si + widget.text_ofs], ax .err: - pop gs + pop si pop ax + pop gs leave + %undef .id + %undef .text_ofs + %undef .text_seg ret -%undef .id -%undef .text_ofs -%undef .text_seg + ; ----------------------------------------------------------------------------- ; gui_api_create @@ -254,9 +265,6 @@ gui_api_create: mov cx, widget_size div cx - mov bx, 0xDEAD - mov word [gs:si + widget.header], bx - mov bx, .type mov byte [gs:si + widget.type], bl mov bx, .x @@ -285,12 +293,13 @@ gui_api_create: ; gui_api_get_state ; Arg1: ID ; Out: AX = State -; ----------------------------------------------------------------------------- %define .id word [bp+4] +; ----------------------------------------------------------------------------- gui_api_get_state: push bp mov bp, sp push gs + push si mov ax, .id call gui_get_widget_ptr_internal @@ -303,21 +312,23 @@ gui_api_get_state: .err: mov ax, -1 .done: + pop si pop gs leave + %undef .id 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 push gs + push si mov ax,.id call gui_get_widget_ptr_internal @@ -330,6 +341,7 @@ gui_api_get_type: .err: mov ax, -1 .done: + pop si pop gs leave ret @@ -339,12 +351,14 @@ gui_api_get_type: ; gui_api_get_val ; Arg1: ID ; Out: AX = Attr Val -; ----------------------------------------------------------------------------- %define .id word [bp+4] +; ----------------------------------------------------------------------------- gui_api_get_val: push bp mov bp, sp push gs + push si + mov ax,.id call gui_get_widget_ptr_internal @@ -357,22 +371,25 @@ gui_api_get_val: .err: mov ax, -1 .done: + pop si pop gs leave + %undef .id 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 push gs + push si mov ax,.id call gui_get_widget_ptr_internal @@ -382,23 +399,25 @@ gui_api_set_val: mov [gs:si + widget.thumb_pos], ax .err: + pop si pop gs leave + %undef .id + %undef .val 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 push gs + push si mov ax,.id call gui_get_widget_ptr_internal @@ -411,10 +430,12 @@ gui_api_destroy: .err: mov ax, -1 .done: + pop si pop gs leave + %undef .id ret -%undef .id + ; ----------------------------------------------------------------------------- ; gui_get_widget_ptr @@ -430,8 +451,8 @@ gui_get_widget_ptr: call gui_get_widget_ptr_internal pop ax leave + %undef .id ret -%undef .id ; ----------------------------------------------------------------------------- ; gui_get_widget_ptr_internal @@ -472,7 +493,7 @@ gui_get_widget_ptr_internal: ; Entrée : DS doit pointer vers SEG_GUI ; ----------------------------------------------------------------------------- gui_init_system: - push eax + push ax push cx push es push di @@ -489,7 +510,7 @@ gui_init_system: pop di pop es pop cx - pop eax + pop ax ret ; ----------------------------------------------------------------------------- diff --git a/src/gui/lib-draw.asm b/src/gui/lib-draw.asm index d435cb5..9b9945b 100644 --- a/src/gui/lib-draw.asm +++ b/src/gui/lib-draw.asm @@ -522,7 +522,7 @@ draw_text: push ax ; Sauve X original mov ax, [gs:si + widget.w] sub ax, cx - shr ax, 1 + sar ax, 1 pop dx ; Récupère X original (poussé depuis AX) add ax, dx ; AX = X final centré diff --git a/src/gui/lib-logic.asm b/src/gui/lib-logic.asm index dbfeebd..b33d88b 100644 --- a/src/gui/lib-logic.asm +++ b/src/gui/lib-logic.asm @@ -26,6 +26,9 @@ gui_process_all: mov bl, [PTR_MOUSE + mouse.status] pop ds + ; Récupérer l'ID de la fenêtre active + mov dl, [PTR_GUI + gui.wm_active_window_id] + mov si, 0 ; Pointeur début tableau mov di, GUI_MAX_WIDGETS ; Compteur @@ -34,9 +37,15 @@ gui_process_all: cmp byte [gs:si + widget.state], GUI_STATE_FREE je .next_widget + mov ax, di + ISADBG ISA_LEFT, al + ; --- Logique Widget --- push bx ; Sauver état boutons souris + + ISADBG ISA_RIGHT, 0x20 ; Avant logic call gui_update_logic ; Vérifier collision/clic + ISADBG ISA_RIGHT, 0x21 ; Avant logic ; Si AL=1 (Clic relâché validé), exécuter le callback cmp al, 1 @@ -60,10 +69,15 @@ gui_process_all: ; Dessiner (si l'état a changé ou pour refresh) + ISADBG ISA_RIGHT, 0x22 ; Avant dessin + cmp al,ah je .next_widget ; Si != 0, le widget est à jour, on passe. call gui_draw_single_widget + ISADBG ISA_RIGHT, 0x23 ; Avant dessin + + .next_widget: add si, widget_size dec di diff --git a/src/gui/window.asm b/src/gui/lib-wm-draw.asm similarity index 78% rename from src/gui/window.asm rename to src/gui/lib-wm-draw.asm index da6d9bd..5d22443 100644 --- a/src/gui/window.asm +++ b/src/gui/lib-wm-draw.asm @@ -1,63 +1,3 @@ -; ============================================================================= -; Project : Custom BIOS / ROM -; File : gui/window.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 . -; -; ============================================================================= - -%macro GUI 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 WINDOW 0 - -; ------------------------------------------------------------ -; 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. -; ------------------------------------------------------------ - -gui_driver: - dw draw_window - ; ============================================================================= ; Fonction : draw_window ; Description : Dessine une fenêtre style Mac System 1.0 diff --git a/src/gui/lib-wm.asm b/src/gui/lib-wm.asm new file mode 100644 index 0000000..b5ad4ee --- /dev/null +++ b/src/gui/lib-wm.asm @@ -0,0 +1,121 @@ +; ============================================================================= +; Project : Custom BIOS / ROM +; File : gui/window.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 . +; +; ============================================================================= + +; ============================================================================= +; Project : Custom BIOS / ROM +; File : gui/window-manager.asm +; Description : Gestionnaire de fenêtres (Window Manager) +; ============================================================================= + +%define MAX_WINDOWS 8 + +; --- États d'une fenêtre --- +%define WIN_STATE_FREE 0 ; Slot libre en mémoire +%define WIN_STATE_INACTIVE 1 ; Affichée en arrière-plan +%define WIN_STATE_ACTIVE 2 ; Au premier plan (focus) +%define WIN_STATE_HIDDEN 3 ; Invisible + +struc window + .state resb 1 ; État de la fenêtre + .id resb 1 ; Identifiant unique + .x resw 1 + .y resw 1 + .w resw 1 + .h resw 1 + .title_ofs resw 1 ; Pointeur texte du titre + .title_seg resw 1 + .process_cb resw 1 ; NOUVEAU : Offset du callback (processus de la fenêtre) + .process_seg resw 1 ; Segment du callback +endstruc + +%define window_size 16 + +; Variables globales du WM (à placer dans le segment BDA_CUSTOM ou SEG_GUI) +wm_active_window_id db 0 ; ID de la fenêtre actuellement active + +; ----------------------------------------------------------------------------- +; wm_process_all +; Remplace la boucle principale. Gère les processus de fenêtre puis la GUI. +; ----------------------------------------------------------------------------- +wm_process_all: + pusha + push ds + push gs + + mov ax, SEG_GUI + mov gs, ax + + ; 1. Gérer les processus des fenêtres + mov si, 0 ; On suppose que le pool window commence à l'offset 0 d'une zone dédiée + mov cx, MAX_WINDOWS + + .loop_windows: + cmp byte [gs:si + window.state], WIN_STATE_FREE + je .next_window + + ; VÉRIFICATION : Est-ce que la fenêtre est ACTIVE ? + ; Selon votre règle : on n'appelle pas le processus si elle n'est pas active. + cmp byte [gs:si + window.state], WIN_STATE_ACTIVE + jne .next_window + + ; La fenêtre est active, a-t-elle un processus (callback) défini ? + cmp word [gs:si + window.process_cb], 0 + je .next_window + + ; Exécution du processus spécifique à la fenêtre active + pusha + ; Appel inter-segment (Far Call) ou intra-segment (Near Call) selon l'architecture + ; Ici on simule un near call si tout est dans CS + call word [gs:si + window.process_cb] + popa + + .next_window: + add si, window_size + loop .loop_windows + + ; 2. Appeler le moteur d'événements des widgets (lib-logic) + call gui_process_all + + pop gs + pop ds + popa + ret + +; ----------------------------------------------------------------------------- +; wm_set_active +; Change la fenêtre active (Focus) +; In: AL = window_id +; ----------------------------------------------------------------------------- +wm_set_active: + push gs + push bx + + ; Sauvegarder le nouvel ID actif + mov [wm_active_window_id], al + + ; Note : Ici vous pourriez rajouter une boucle pour passer toutes les + ; autres fenêtres en WIN_STATE_INACTIVE et redessiner le tout pour + ; mettre la fenêtre active au premier plan (Z-Order). + + pop bx + pop gs + ret \ No newline at end of file