From ddc4ef393c613c18fea35b4c8628caa37cbf36e8 Mon Sep 17 00:00:00 2001 From: Frater <13979047+saintfrater@users.noreply.github.com> Date: Tue, 17 Feb 2026 21:04:59 +0100 Subject: [PATCH] VGA - Write --- doc/MEMORY_MAP.md | 4 +- src/boot-cga.asm | 2 +- src/boot-vga.asm | 33 +++---- src/common/bda.asm | 4 +- src/drivers/gfx_cgam.asm | 46 +++++----- src/drivers/gfx_vga.asm | 186 +++++++++++++++++++++----------------- src/drivers/mouse_ps2.asm | 6 +- src/drivers/textmode.asm | 8 +- src/gui/lib-logic.asm | 8 +- 9 files changed, 157 insertions(+), 140 deletions(-) diff --git a/doc/MEMORY_MAP.md b/doc/MEMORY_MAP.md index 984fdb1..bc07199 100644 --- a/doc/MEMORY_MAP.md +++ b/doc/MEMORY_MAP.md @@ -37,7 +37,7 @@ 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_CUSTOM_SEG`. Stores driver states: +* **Custom BDA (`0050:0000`)**: Defined by `SEG_BDA_CUSTOM`. Stores driver states: * **Mouse**: Input buffer, status, coordinates, background buffer (for cursor). * **Gfx**: Text cursor position, attributes. * **GUI RAM**: Segment `0x0063` (Physical `0x00630`). @@ -100,7 +100,7 @@ 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_CUSTOM_SEG`. Stocke l'état des drivers : +* **Custom BDA (`0050:0000`)** : Définie par `SEG_BDA_CUSTOM`. 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 `0x0063` (Physique `0x00630`). diff --git a/src/boot-cga.asm b/src/boot-cga.asm index 9630900..5ada805 100644 --- a/src/boot-cga.asm +++ b/src/boot-cga.asm @@ -241,7 +241,7 @@ timer_isr: push ax push fs - mov ax,BDA_CUSTOM_SEG + mov ax,SEG_BDA_CUSTOM mov fs,ax ; exemple de fonctionnement: ; inc byte [fs:BDA_TIMER] diff --git a/src/boot-vga.asm b/src/boot-vga.asm index d4481d6..0576857 100644 --- a/src/boot-vga.asm +++ b/src/boot-vga.asm @@ -130,8 +130,9 @@ main_loop: push cs pop ds + GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT GFX GOTOXY, 5,5 - GFX WRITE, str_hello + GFX WRITE, cs, str_hello ; Init du système GUI @@ -140,20 +141,20 @@ main_loop: .loop: ; call gui_process_all - mov dh, 1 - mov dl, 10 - call scr_gotoxy - - mov ax, BDA_CUSTOM_SEG - mov fs, ax - mov ax, word [fs:PTR_MOUSE + mouse.x] - call scr_puthex16 - - mov al, ' ' - call scr_putc - - mov ax, word [fs:PTR_MOUSE + mouse.y] - call scr_puthex16 +; mov dh, 1 +; mov dl, 10 +; call scr_gotoxy +; +; mov ax, SEG_BDA_CUSTOM +; mov fs, ax +; mov ax, word [fs:PTR_MOUSE + mouse.x] +; call scr_puthex16 +; +; mov al, ' ' +; call scr_putc +; +; mov ax, word [fs:PTR_MOUSE + mouse.y] +; call scr_puthex16 nop jmp .loop @@ -167,7 +168,7 @@ timer_isr: push ax push fs - mov ax,BDA_CUSTOM_SEG + mov ax,SEG_BDA_CUSTOM mov fs,ax ; exemple de fonctionnement: ; inc byte [fs:BDA_TIMER] diff --git a/src/common/bda.asm b/src/common/bda.asm index af0de64..17e40c8 100644 --- a/src/common/bda.asm +++ b/src/common/bda.asm @@ -25,7 +25,7 @@ ; %define BDA_SEGMENT 0x0040 ; segment BDA (historically) -%define BDA_CUSTOM_SEG 0x0050 ; custom data (mouse, gfx cursor, etc..) +%define SEG_BDA_CUSTOM 0x0050 ; custom data (mouse, gfx cursor, etc..) %define BDA_GUI_WIDGET 0x0070 ; Segment de données UI (Safe: après Stack, avant Heap) %define PTR_MOUSE 0x0000 @@ -86,7 +86,7 @@ bda_setup: pusha push ds - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov es, ax mov ax, 0x5F diff --git a/src/drivers/gfx_cgam.asm b/src/drivers/gfx_cgam.asm index c9081c1..28a5505 100644 --- a/src/drivers/gfx_cgam.asm +++ b/src/drivers/gfx_cgam.asm @@ -23,7 +23,7 @@ ; ; graphics drivers pour carte video/mode CGA-Mono (640x200x2) ; -%define VIDEO_SEG 0xB800 ; ou 0xB000 +%define SEG_VIDEO 0xB800 ; ou 0xB000 %define GFX_MODE 0x06 ; MCGA HiRes (B/W) %define GFX_WIDTH 640 @@ -113,7 +113,7 @@ graph_driver: ; ce mode est entrelacé, un bit/pixel, 8 pixels par octet ; ------------------------------------------------------------ cga_init: - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax ; init graphics mode @@ -132,7 +132,7 @@ cga_none: ; ------------------------------------------------------------ ; Calcule DI + AH=mask pour (CX=x, DX=y) en mode CGA 640x200 ; -; Out: ES=VIDEO_SEG, DI=offset, AH=bitmask (0x80 >> (x&7)) +; Out: ES=SEG_VIDEO, DI=offset, AH=bitmask (0x80 >> (x&7)) ; ------------------------------------------------------------ cga_calc_addr: ; calcul de l'offset 'y': @@ -180,7 +180,7 @@ cga_set_writemode: push fs push ax - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov fs,ax mov ax, .mode @@ -212,7 +212,7 @@ cga_set_charpos: pusha push fs - mov ax,BDA_CUSTOM_SEG + mov ax,SEG_BDA_CUSTOM mov fs,ax ; store x,y en pixel @@ -313,9 +313,9 @@ cga_putc: call cga_mouse_hide ; Protection souris - mov bx, VIDEO_SEG + mov bx, SEG_VIDEO mov es, bx - mov bx, BDA_CUSTOM_SEG + mov bx, SEG_BDA_CUSTOM mov fs, bx mov ax, .car @@ -441,7 +441,7 @@ cga_write: ; ; CX = x (0..639) ; DX = y (0..199) -; ES = Target Segment (usually VIDEO_SEG) +; ES = Target Segment (usually SEG_VIDEO) ; BL = color (0=black, !=0=white) ; ------------------------------------------------------------ ; --- Définition des arguments --- @@ -453,7 +453,7 @@ cga_putpixel: mov bp, sp pusha - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax call cga_mouse_hide ; Protection souris @@ -503,7 +503,7 @@ cga_getpixel: mov cx, .x mov dx, .y - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax call cga_calc_addr @@ -525,7 +525,7 @@ cga_getpixel: ; ; ------------------------------------------------------------ cga_background: - mov ax,VIDEO_SEG + mov ax,SEG_VIDEO mov es,ax mov di,0x0000 mov eax,0xaaaaaaaa @@ -554,7 +554,7 @@ cga_line_vertical: push es ; Setup ES = Video Segment - mov ax, VIDEO_SEG ; Utiliser AX plutot que SI pour setup ES + mov ax, SEG_VIDEO ; Utiliser AX plutot que SI pour setup ES mov es, ax call cga_mouse_hide @@ -637,7 +637,7 @@ cga_line_horizontal: push es ; Setup ES = Video Segment - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax call cga_mouse_hide @@ -790,7 +790,7 @@ cga_line: je .do_vert ; --- Bresenham --- - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax call cga_mouse_hide @@ -1009,7 +1009,7 @@ cga_fill_rect: pusha push es - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax ; calcul de l'offset de départ du pattern @@ -1268,7 +1268,7 @@ cga_mouse_hide: pusha ; Sauvegarder TOUS les registres 32-bits push ds - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax ; Décrémenter le compteur @@ -1296,7 +1296,7 @@ cga_mouse_show: pusha push ds - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax ; Incrémenter le compteur @@ -1328,7 +1328,7 @@ cga_mouse_cursor_move: push es ; move Data Segment - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax cmp byte [PTR_MOUSE + mouse.cur_counter], 0 @@ -1339,7 +1339,7 @@ cga_mouse_cursor_move: mov byte [PTR_MOUSE + mouse.cur_drawing],1 - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax call cga_cursor_restorebg @@ -1364,7 +1364,7 @@ cga_cursor_savebg: jne .done push es - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax ; mémoriser position courante (utilisée pour restore) @@ -1410,7 +1410,7 @@ cga_cursor_restorebg: je .done push es - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax ; restaurer depuis la dernière position sauvegardée @@ -1456,9 +1456,9 @@ cga_cursor_draw: push gs cld ; Sécurité : Direction avant - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax ; --- CLIPPING VERTICAL --- diff --git a/src/drivers/gfx_vga.asm b/src/drivers/gfx_vga.asm index 609f340..c981b2a 100644 --- a/src/drivers/gfx_vga.asm +++ b/src/drivers/gfx_vga.asm @@ -23,7 +23,7 @@ ; ; graphics drivers pour carte video/mode CGA-Mono (640x200x2) ; -%define VIDEO_SEG 0A000h +%define SEG_VIDEO 0A000h %define GFX_MODE 0x12 ; VGA HiRes (640x480x16) %define GFX_WIDTH 640 @@ -181,7 +181,7 @@ vga_background: out dx, ax ; Initialisation mémoire - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax xor edi, edi ; ES:EDI = Début mémoire vidéo movzx esi, si ; Nettoyer ESI (garder SI) pour l'adressage @@ -239,7 +239,7 @@ vga_set_writemode: push fs push ax - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov fs,ax mov ax, .mode @@ -254,10 +254,10 @@ vga_set_writemode: ; --------------------------------------------------------------------------- ; gfx_set_charpos (x,y) -; In : CX = x (pixels), DX = y (pixels) +; In : x (pixels), y (pixels) ; Out: variables DS:GFX_CUR_* ; Notes: -; - calcule l'offset VRAM de la scanline y: base = (y&1?2000:0) + (y>>1)*80 + (x>>3) +; - calcule l'offset VRAM de la scanline y: base = (y*80) + (x>>3) ; - stocke aussi shift = x&7 ; --------------------------------------------------------------------------- ; --- Définition des arguments --- @@ -270,7 +270,7 @@ vga_set_charpos: pusha push fs - mov ax,BDA_CUSTOM_SEG + mov ax,SEG_BDA_CUSTOM mov fs,ax ; store x,y en pixel @@ -286,7 +286,7 @@ vga_set_charpos: call vga_calc_addr - mov [fs:PTR_GFX + gfx.cur_offset], bx + mov [fs:PTR_GFX + gfx.cur_offset], di pop fs popa @@ -325,13 +325,6 @@ get_glyph_offset: ; - x non aligné (x&7 != 0) ; - écrit sur 2 bytes (di et di+1) dans chaque banque ; --------------------------------------------------------------------------- -; convert al -> AX aligned with "cl" -%macro ALIGN_BYTE 0 - mov ah,al - xor al,al - shr ax,cl - xchg ah,al -%endmacro ; --- Définition des arguments --- %define .car word [bp+4] @@ -348,11 +341,30 @@ vga_putc: call vga_mouse_hide ; Protection souris - mov bx, VIDEO_SEG + mov dx, EGAVGA_CONTROLLER + ; Forcer le mode de remplacement (écrase la VRAM avec la donnée CPU) + mov ax, 0x0003 ; Index 3: Data Rotate = 0, Function = REPLACE + out dx, ax + ; S'assurer que le mode d'écriture est 0 (Standard) + mov ax, 0x0005 ; index 1: Enable Set/Reset + out dx, ax + ; Désactiver Set/Reset pour laisser passer AX + mov ax, 0x0001 ; Index 1: Enable Set/Reset = 0 + out dx, ax + + mov ax, 0xFF08 ; Bit Mask: 0xFF (on autorise l'écriture sur tous les pixels) + out dx, ax + + mov bx, SEG_VIDEO mov es, bx - mov bx, BDA_CUSTOM_SEG + mov bx, SEG_BDA_CUSTOM mov fs, bx + ; Configuration VGA : Activer l'écriture sur les 4 plans pour le texte + mov dx, VGA_SEQUENCER ; Sequencer + mov ax, 0x0F02 ; Index 2 (Map Mask) = 0x0F (tous les plans) + out dx, ax + mov ax, .car call get_glyph_offset @@ -362,82 +374,85 @@ vga_putc: mov cl, [fs:PTR_GFX + gfx.cur_shift] mov bx, GFX_OFFSET - mov .cpt, 4 - + mov .cpt, 8 .row_loop: + push di + mov al, byte[es:di] + + xor ax,ax + mov al, [cs:si] + inc si + + ; convert al -> AX aligned with "cl" + mov ah,al + xor al,al + shr ax,cl + xchg ah,al + ; ----- ALIGN_BYTE + ; gestion du fond de texte test ch, 00000010b ; transparent background ? - jz .skip_attribut ; oui + jnz .draw_text_only ; oui - test ch, 00000001b ; background blanc ? - je .bkg_black + ; --- Dessin du Fond (Opaque) --- + mov bx, 0xFF00 ; Masque de 8 pixels pleins + push cx + shr bx, cl ; Aligner le masque de fond + pop cx + xchg bl, bh - ; background = white - mov ax, 0xFF00 - shr ax, cl - xchg al, ah - or [es:di], ax - or [es:di+bx], ax - jmp .skip_attribut + test ch, 00000001b ; Couleur texte (pour déduire le fond) + jnz .bg_black ; Si texte blanc, fond noir - .bkg_black: ; OK - ; background = black - mov ax, 0xFF00 - shr ax, cl - xchg al, ah - not ax - and [es:di], ax - and [es:di+bx], ax + ; Fond Blanc (OR) + or [es:di], bx ; Écrit sur 2 octets (di et di+1) + jmp .draw_text_only + .bg_black: + not bx ; Inverser pour faire un masque AND + and [es:di], bx - .skip_attribut: - ; ligne "paire" du gylphe - xor ax, ax - mov al, [cs:si] - inc si - ALIGN_BYTE - mov dx, ax + .draw_text_only: + ; --- Dessin du Texte --- + test ch, 00000001b ; Bit 0: 1=White, 0=Black + jz .text_black - ; ligne "impaire" du gylphe - mov al, [cs:si] - inc si - ALIGN_BYTE - xchg ax, dx + ; Texte Blanc (OR) + or [es:di], ax + jmp .next_row - test ch,00000001b - jz .black_text + .text_black: + ; Texte Noir (AND NOT) + not ax + and [es:di], ax - ; white text - not ax - not dx - and [es:di], ax - and [es:di+bx], dx + .next_row: + pop di ; Récupérer le DI du début de ligne + add di, 80 ; Passer à la ligne VRAM suivante (linéaire) + ; dec .cpt + jnz .row_loop - jmp .next - .black_text: - or [es:di], ax - or [es:di+bx], dx + ; Mise à jour des variables de position + add word [fs:PTR_GFX + gfx.cur_x], 8 + ; Recalculer l'offset pour le prochain caractère (gère le changement d'octet) + mov cx, [fs:PTR_GFX + gfx.cur_x] + mov dx, [fs:PTR_GFX + gfx.cur_y] + call vga_calc_addr + mov [fs:PTR_GFX + gfx.cur_offset], di + ; Note: calc_addr doit mettre le résultat dans DI ou BX selon ton usage - .next: - ; add di,CGA_STRIDE - - dec .cpt - jnz .row_loop - - ; Avancer curseur d'un caractère (8 pixels) - inc word [fs:PTR_GFX + gfx.cur_offset] - add word [fs:PTR_GFX + gfx.cur_x], 8 - - call vga_mouse_show ; Restauration souris - - pop es - pop fs - popa - leave - ret + call vga_mouse_show + pop es + pop fs + popa + leave + ret %undef .car %undef .cpt +junk: + + ; ; write string from [DS:SI] to screen ; @@ -461,6 +476,7 @@ vga_write: je .done push ax call vga_putc + pop ax jmp .loops .done: @@ -515,7 +531,7 @@ vga_putpixel: out dx, ax ; 4. Écriture (Nécessite une lecture préalable pour charger les Latches) - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO 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 @@ -549,7 +565,7 @@ vga_mouse_hide: pusha ; Sauvegarder TOUS les registres 32-bits push ds - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax ; Décrémenter le compteur @@ -577,7 +593,7 @@ vga_mouse_show: pusha push ds - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax ; Incrémenter le compteur @@ -609,7 +625,7 @@ vga_mouse_cursor_move: push es ; BDA Data Segment - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax cmp byte [PTR_MOUSE + mouse.cur_counter], 0 @@ -637,7 +653,7 @@ vga_cursor_savebg: jne .done push es - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax ; Calculer l'adresse de départ (y * 80 + x / 8) @@ -689,14 +705,14 @@ vga_cursor_restorebg: je .done push es - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax mov di, [PTR_MOUSE + mouse.cur_addr_start] lea si, [PTR_MOUSE + mouse.bkg_buffer] ; Sécurité : S'assurer que ES pointe bien vers la vidéo pour le restore - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax ; Sécurité : Réinitialiser le contrôleur graphique pour l'écriture CPU brute @@ -767,9 +783,9 @@ vga_cursor_draw: ; Note: pushad sauvegarde déjà tous les registres généraux (EAX...EDI) cld ; Sécurité : Direction avant - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax - mov ax, VIDEO_SEG + mov ax, SEG_VIDEO mov es, ax ; --- CLIPPING VERTICAL --- diff --git a/src/drivers/mouse_ps2.asm b/src/drivers/mouse_ps2.asm index 38e2a9f..9b3c9ab 100644 --- a/src/drivers/mouse_ps2.asm +++ b/src/drivers/mouse_ps2.asm @@ -43,7 +43,7 @@ ; ; ------------------------------------------------------------ mouse_reset: - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov fs,ax ; effacer les variables du drivers @@ -154,7 +154,7 @@ mouse_init: ; ; ------------------------------------------------------------ mouse_detect_packet_len: - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov fs,ax mov byte [fs:PTR_MOUSE + mouse.packetlen], 3 @@ -284,7 +284,7 @@ isr_mouse_handler: push ds ; use BDA segment - mov ax,BDA_CUSTOM_SEG + mov ax,SEG_BDA_CUSTOM mov ds,ax ; lire un octet depuis le contrôleur et le stocker dans le buffer diff --git a/src/drivers/textmode.asm b/src/drivers/textmode.asm index 5a29244..a8c92de 100644 --- a/src/drivers/textmode.asm +++ b/src/drivers/textmode.asm @@ -23,10 +23,10 @@ ; ; text mod functions -; +; ; -vid_seg dw VIDEO_SEG +vid_seg dw SEG_VIDEO cursor_ofs dw 0 txt_attr db VIDEO_ATTR @@ -118,11 +118,11 @@ txtmode_newline: jb .set xor ax, ax ; si dépasse, revient en haut (simple) .set: - + mov cx, 160 ; cursor_ofs = ligne * 160 mul cx ; DX:AX = AX*CX ; ici AX suffit mov [cursor_ofs], ax - + pop dx pop ax ret diff --git a/src/gui/lib-logic.asm b/src/gui/lib-logic.asm index fff44eb..2c7e05d 100644 --- a/src/gui/lib-logic.asm +++ b/src/gui/lib-logic.asm @@ -21,7 +21,7 @@ gui_process_all: ; Charger l'état de la souris pour toute la passe push ds - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax mov bl, [PTR_MOUSE + mouse.status] pop ds @@ -85,7 +85,7 @@ gui_update_logic: push ds push gs - mov ax, BDA_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax mov ax, BDA_GUI_WIDGET mov gs, ax @@ -435,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_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax mov ax, [PTR_MOUSE + mouse.x] pop ds @@ -463,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_CUSTOM_SEG + mov ax, SEG_BDA_CUSTOM mov ds, ax mov ax, [PTR_MOUSE + mouse.y] pop ds