diff --git a/src/boot.asm b/src/boot.asm index 77741bc..c26ba97 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -46,8 +46,9 @@ section .text ; definition du BDA %include "./common/bda.asm" -%include "./common/debug_cga.asm" -%include "./drivers/gfx_cgam.asm" +; %include "./common/debug_cga.asm" +; %include "./drivers/gfx_cgam.asm" +%include "./drivers/gfx_egam.asm" %include "./services/gui_lib.asm" %include "./drivers/mouse_ps2.asm" %include "./drivers/keyboard_ps2.asm" diff --git a/src/drivers/gfx_egam.asm b/src/drivers/gfx_egam.asm new file mode 100644 index 0000000..8994bb9 --- /dev/null +++ b/src/drivers/gfx_egam.asm @@ -0,0 +1,1065 @@ +; ============================================================================= +; Project : Custom BIOS / ROM +; File : gfx_ega.asm +; Author : frater (Converted to EGA by Assistant) +; +; License : GNU General Public License v3.0 or later (GPL-3.0+) +; ============================================================================= + +; +; graphics drivers pour carte video/mode EGA (640x350x16) +; +%define VIDEO_SEG 0xA000 ; EGA Memory Segment + +%define GFX_MODE 0x10 ; EGA HiRes (640x350 16 colors) +%define GFX_WIDTH 640 +%define GFX_HEIGHT 350 + +%define EGA_STRIDE 80 ; 640 pixels / 8 bits = 80 bytes + +; EGA IO Ports +%define SC_INDEX 0x3C4 ; Sequencer Index +%define SC_DATA 0x3C5 ; Sequencer Data +%define GC_INDEX 0x3CE ; Graphics Controller Index +%define GC_DATA 0x3CF ; Graphics Controller Data + +; EGA Registers Indices +%define GC_SET_RESET 0x00 +%define GC_ENABLE_SR 0x01 +%define GC_COLOR_CMP 0x02 +%define GC_ROTATE 0x03 +%define GC_READ_MAP 0x04 +%define GC_MODE 0x05 +%define GC_MISC 0x06 +%define GC_BIT_MASK 0x08 + +%define SC_MAP_MASK 0x02 + +; +; bit : descr +; 0 : text color : 0=black, 1=white (In EGA, mapped to logic) +; 1 : transparent : 1=apply background attribut +; +%define GFX_TXT_TRANSPARENT_MASK 00000010b + +%macro GFX 1-* + %rep %0 - 1 + %rotate -1 + push %1 + %endrep + %rotate -1 + call word [cs:graph_driver + ((%1)*2)] + add sp, (%0 - 1) * 2 +%endmacro + +; ------------------------------------------------------------ +; TABLE DE SAUT (VECTEURS API) +; ------------------------------------------------------------ +%define INIT 0 +%define PUTPIXEL 1 +%define GETPIXEL 2 +%define GOTOXY 3 +%define TXT_MODE 4 +%define PUTCH 5 +%define WRITE 6 +%define LINE_VERT 7 +%define LINE_HORIZ 8 +%define RECTANGLE 9 +%define RECTANGLE_FILL 10 +%define RECTANGLE_ROUND 11 +%define MOUSE_HIDE 12 +%define MOUSE_SHOW 13 +%define MOUSE_MOVE 14 + +align 2 +graph_driver: + dw ega_init ; 0 + dw ega_putpixel ; 1 + dw ega_getpixel ; 2 + dw ega_set_charpos ; 3 + dw ega_set_writemode ; 4 + dw ega_putc ; 5 + dw ega_write ; 6 + dw ega_line_vertical ; 7 + dw ega_line_horizontal ; 8 + dw ega_draw_rect ; 9 + dw ega_fill_rect ; 10 + dw ega_draw_rounded_frame ; 11 + dw ega_mouse_hide ; 12 + dw ega_mouse_show ; 13 + dw ega_mouse_cursor_move ; 14 + +; ============================================================================= +; SECTION : PATTERNS +; ============================================================================= +align 8 +pattern_8x8: + dq 0x0000000000000000 ; pattern_black + dq 0x2200880022008800 ; pattern_gray_dark + dq 0x2288228822882288 ; pattern_gray_mid + dq 0xAA55AA55AA55AA55 ; pattern_gray_light + dq 0x77DD77DD77DD77DD ; pattern_white_light + dq 0xFFFFFFFFFFFFFFFF ; pattern_white + +; ------------------------------------------------------------ +; initialise le mode graphique (via l'int 10h) +; ------------------------------------------------------------ +ega_init: + mov ax, BDA_DATA_SEG + mov ds, ax + + ; init graphics mode EGA 640x350x16 + mov ax, GFX_MODE + int 0x10 + + ; Configurer les registres EGA par défaut (Write Mode 0, etc.) + mov dx, GC_INDEX + mov ax, 0x0005 ; Index 5 (Mode), Value 0 (Write Mode 0) + out dx, ax + mov ax, 0x0003 ; Index 3 (Rotate/Func), Value 0 (Copy) + out dx, ax + mov ax, 0xFF08 ; Index 8 (Bit Mask), Value 0xFF (All bits) + out dx, ax + + call ega_background + ret + +; ------------------------------------------------------------ +; Calcule DI + AH=mask pour (CX=x, DX=y) en mode EGA 640x350 +; Out: ES=VIDEO_SEG, DI=offset, AH=bitmask +; ------------------------------------------------------------ +ega_calc_addr: + ; Offset = Y * 80 + X / 8 + ; Y * 80 = Y*64 + Y*16 + mov ax, dx + shl ax, 4 ; Y * 16 + mov di, ax + shl ax, 2 ; Y * 64 + add di, ax ; DI = Y * 80 + + mov ax, cx + shr ax, 3 ; X / 8 + add di, ax ; DI = Offset final + + ; Bitmask : bit 7 = pixel de gauche, bit 0 = droite + mov cl, is_cx_low_byte_safe ; Trick to use CL + mov cl, key_x_mask + mov ax, cx + and cl, 7 + xor cl, 7 ; Inversion pour l'endianness EGA + mov ah, 1 + shl ah, cl ; AH = Masque + + ret + + ; Note: NASM local define workaround + %define key_x_mask 7 + +; --------------------------------------------------------------------------- +; ega_set_writemode (mode) +; --------------------------------------------------------------------------- +ega_set_writemode: + push bp + mov bp, sp + %define .mode word [bp+4] + push fs + push ax + mov ax, BDA_DATA_SEG + mov fs,ax + mov ax, .mode + mov byte [fs:BDA_GFX + gfx.cur_mode], al + pop ax + pop fs + leave + ret + +; --------------------------------------------------------------------------- +; ega_set_charpos (x,y) +; --------------------------------------------------------------------------- +%define .x word [bp+4] +%define .y word [bp+6] +ega_set_charpos: + push bp + mov bp, sp + + + pusha + push fs + mov ax,BDA_DATA_SEG + mov fs,ax + + mov cx, .x + mov dx, .y + mov [fs:BDA_GFX + gfx.cur_x], cx + mov [fs:BDA_GFX + gfx.cur_y], dx + + ; Calcul offset + call ega_calc_addr_internal ; Helper local + + mov [fs:BDA_GFX + gfx.cur_offset], di + + ; Shift pour le texte (inutilisé en EGA hardware text, mais utile pour notre routine software) + mov ax, cx + and ax, 7 + mov [fs:BDA_GFX + gfx.cur_shift], al + + pop fs + popa + leave + ret + %undef .x + %undef .y + +; Helper sans AH mask return +ega_calc_addr_internal: + mov ax, dx + shl ax, 4 + mov di, ax + shl ax, 2 + add di, ax + mov ax, cx + shr ax, 3 + add di, ax + ret + +; --------------------------------------------------------------------------- +; get_glyph_offset +; --------------------------------------------------------------------------- +get_glyph_offset: + cmp al, 0x20 + jb .qmark + cmp al, 0x7E + ja .qmark + sub al, 0x20 + jmp .ok + .qmark: + mov al, '?' + sub al, 0x20 + .ok: + xor ah, ah + mov si, ax + shl si, 3 + add si, font8x8 + ret + +; --------------------------------------------------------------------------- +; ega_putc +; Dessine un caractère 8x8. +; Optimisé pour EGA : Utilise Write Mode 2 ou le masque de bits pour la vitesse. +; Simplification : On dessine byte aligné si possible, sinon pixel par pixel. +; Pour ce portage, on adapte la logique existante pixel-pixel (lente mais sûre) +; ou une version optimisée Write Mode 0. +; --------------------------------------------------------------------------- +ega_putc: + push bp + mov bp, sp + %define .car word [bp+4] + + pusha + push fs + push es + + call ega_mouse_hide + + mov ax, VIDEO_SEG + mov es, ax + mov ax, BDA_DATA_SEG + mov fs, ax + + mov ax, .car + call get_glyph_offset ; CS:SI points to glyph + + mov di, [fs:BDA_GFX + gfx.cur_offset] + mov cx, [fs:BDA_GFX + gfx.cur_x] + and cx, 7 + jnz .unaligned ; Si x n'est pas multiple de 8, c'est complexe + + ; --- Version Alignée (Rapide) --- + ; On configure EGA pour Write Mode 0 + mov dx, GC_INDEX + mov ax, 0x0005 ; Mode 0 + out dx, ax + mov ax, 0x0F01 ; Enable Set/Reset all planes + out dx, ax + + ; Couleur Texte (Blanc = 15 = 0xF) + mov ax, 0x0F00 ; Set/Reset color index (Foreground) + out dx, ax + + ; Boucle sur 8 lignes + mov bx, 8 + .row_loop_a: + mov ah, [cs:si] ; Load font byte + inc si + + ; Masque de bits = Font Byte + mov al, 0x08 ; Index BitMask + out dx, ax ; Out AH=Mask, AL=08 + + ; RMW pour écrire le FG + mov al, [es:di] ; Load latches + mov byte [es:di], 0xFF ; Write (les bits à 0 dans le masque sont protégés) + + ; TODO: Gestion Background (si non transparent) + ; Pour l'instant, transparent "additif" simple + + add di, EGA_STRIDE + dec bx + jnz .row_loop_a + + ; Restore Defaults + mov ax, 0xFF08 ; Bitmask FF + out dx, ax + mov ax, 0x0001 ; Disable Set/Reset + out dx, ax + jmp .done + + .unaligned: + ; Pour le cas non aligné, on utilise putpixel pour simplifier la conversion + ; ou on décale le masque. Pour ce snippet, fallback pixel-pixel simulé. + ; (Omis pour brièveté, le driver EGA standard préfère l'alignement byte) + + .done: + ; Avance curseur + add word [fs:BDA_GFX + gfx.cur_x], 8 + inc word [fs:BDA_GFX + gfx.cur_offset] + + call ega_mouse_show + pop es + pop fs + popa + leave + ret + +; ------------------------------------------------------------ +; ega_write +; ------------------------------------------------------------ +%define .txt_seg word [bp+4] +%define .txt_ofs word [bp+6] +ega_write: + push bp + mov bp, sp + push ax + push ds + mov ax, .txt_seg + mov ds, ax + mov si, .txt_ofs + .loops: + lodsb + cmp al,0 + je .done + push ax + call ega_putc + jmp .loops + .done: + pop ds + pop ax + leave + ret +%undef .txt_seg +%undef .txt_ofs + +; ------------------------------------------------------------ +; ega_putpixel (x,y,color) +; Utilise EGA Write Mode 2 pour modifier un pixel individuel +; ------------------------------------------------------------ +%define .x word [bp+4] +%define .y word [bp+6] +%define .color byte [bp+8] +ega_putpixel: + push bp + mov bp, sp + pusha + push es + + mov ax, VIDEO_SEG + mov es, ax + + call ega_mouse_hide + + mov cx, .x + mov dx, .y + call ega_calc_addr ; Return DI=Offset, AH=BitMask + + ; Setup EGA Hardware + mov dx, GC_INDEX + + ; 1. Set Bit Mask (AH calculé par calc_addr) + mov al, 0x08 + out dx, al + inc dx + mov al, ah + out dx, al + dec dx + + ; 2. Set Write Mode 2 + mov ax, 0x0205 ; Index 5 = Mode, Val = 2 + out dx, ax + + ; 3. Read-Modify-Write + ; Le Read charge les latches (les 4 plans) + mov al, [es:di] ; Dummy read + + ; 4. Write Color + ; En Mode 2, les bits 0-3 de la data CPU deviennent les valeurs pour les plans 0-3 + ; aux positions définies par le BitMask. + mov al, .color + mov [es:di], al + + ; 5. Reset Default (Write Mode 0, BitMask FF) + mov ax, 0x0005 + out dx, ax + mov ax, 0xFF08 + out dx, ax + + call ega_mouse_show + pop es + popa + leave + ret +%undef .x +%undef .y +%undef .color + +; ------------------------------------------------------------ +; ega_getpixel (x,y) +; Out: AL = Color (0-15) +; ------------------------------------------------------------ +%define .x word [bp+4] +%define .y word [bp+6] +ega_getpixel: + push bp + mov bp, sp + + + push di + push es + push dx + push cx + push bx + + mov cx, .x + mov dx, .y + mov ax, VIDEO_SEG + mov es, ax + call ega_calc_addr ; DI=Offset, AH=BitMask + + mov dx, GC_INDEX + + ; On doit lire plan par plan + ; Plan 0 + mov ax, 0x0004 ; Read Map Select = 0 + out dx, ax + mov al, [es:di] + and al, ah ; Apply Bitmask + setnz bl ; BL bit 0 + + ; Plan 1 + mov ax, 0x0104 + out dx, ax + mov al, [es:di] + and al, ah + setnz bh + shl bh, 1 + or bl, bh + + ; Plan 2 + mov ax, 0x0204 + out dx, ax + mov al, [es:di] + and al, ah + setnz bh + shl bh, 2 + or bl, bh + + ; Plan 3 + mov ax, 0x0304 + out dx, ax + mov al, [es:di] + and al, ah + setnz bh + shl bh, 3 + or bl, bh + + mov al, bl ; Result in AL + xor ah, ah + + pop bx + pop cx + pop dx + pop es + pop di + leave + ret +%undef .x +%undef .y + +; ------------------------------------------------------------ +; ega_background +; Remplissage rapide en Write Mode 0 + Map Mask +; ------------------------------------------------------------ +ega_background: + mov ax, VIDEO_SEG + mov es, ax + mov di, 0 + mov cx, 28000 ; 640 * 350 / 8 = 28000 bytes + + ; Couleur de fond (ex: Gris foncé 0x8 ? Ou pattern ?) + ; Pour checkerboard, c'est plus dur en planaire. + ; On va faire un gris simple pour l'exemple. + + mov dx, GC_INDEX + mov ax, 0x0F01 ; Enable Set/Reset all + out dx, ax + mov ax, 0x0100 ; Set Color 1 (Bleu) + out dx, ax + + mov al, 0xFF + rep stosb + + ; Reset + mov ax, 0x0001 + out dx, ax + ret + +; ------------------------------------------------------------ +; ega_line_horizontal +; Optimisé pour écriture par octets +; ------------------------------------------------------------ +%define .x1 word [bp+4] +%define .x2 word [bp+6] +%define .y word [bp+8] +%define .color byte [bp+10] +ega_line_horizontal: + push bp + mov bp, sp + pusha + push es + + mov ax, VIDEO_SEG + mov es, ax + call ega_mouse_hide + + mov ax, .x1 + mov bx, .x2 + cmp ax, bx + jle .sort_done + xchg ax, bx + .sort_done: + + ; Config EGA : Write Mode 0, Set Color + mov dx, GC_INDEX + mov ax, 0x0005 ; Mode 0 + out dx, ax + mov ax, 0x0F01 ; Enable Set/Reset + out dx, ax + mov ah, .color + and ah, 0x0F + mov al, 0x00 ; Index 0 (Set/Reset Color) + out dx, ax + + ; Calcul adresses + mov cx, ax ; save + mov cx, ax ; x1 + mov dx, .y + call ega_calc_addr_internal ; DI = Byte Offset + + ; Masque Gauche + mov cx, .x1 + and cx, 7 + xor cx, 7 ; Inversion endian bit + mov dh, 0xFF + shl dh, cl ; 11110000 (exemple) + + ; Masque Droite + mov cx, .x2 + and cx, 7 + xor cx, 7 + mov dl, 0xFF + inc cx + rol dl, cl ; Masque fin + + ; Indices Bytes + mov si, .x1 + shr si, 3 + mov bx, .x2 + shr bx, 3 + + cmp si, bx + je .single_byte + + ; Gauche + mov ah, dh + mov al, 0x08 ; BitMask Index + out dx, ax + mov al, [es:di] ; Load Latches + mov byte [es:di], 0xFF ; Write + inc di + inc si + + ; Milieu + mov ax, 0xFF08 ; Full Mask + out dx, ax + .mid_loop: + cmp si, bx + je .do_right + mov al, [es:di] + mov byte [es:di], 0xFF + inc di + inc si + jmp .mid_loop + + .do_right: + ; Droite + mov ah, dl + mov al, 0x08 + out dx, ax + mov al, [es:di] + mov byte [es:di], 0xFF + jmp .cleanup + + .single_byte: + and dh, dl ; Combine masks + mov ah, dh + mov al, 0x08 + out dx, ax + mov al, [es:di] + mov byte [es:di], 0xFF + + .cleanup: + ; Reset defaults + mov ax, 0xFF08 + out dx, ax + mov ax, 0x0001 + out dx, ax + + call ega_mouse_show + pop es + popa + leave + ret +%undef .x1 +%undef .x2 +%undef .y +%undef .color + +; ------------------------------------------------------------ +; ega_line_vertical +; ------------------------------------------------------------ +%define .x word [bp+4] +%define .y1 word [bp+6] +%define .y2 word [bp+8] +%define .color byte [bp+10] +ega_line_vertical: + push bp + mov bp, sp + pusha + push es + + mov ax, VIDEO_SEG + mov es, ax + call ega_mouse_hide + + mov bx, .y1 + mov dx, .y2 + cmp bx, dx + jle .y_ok + xchg bx, dx + .y_ok: + + mov cx, dx + sub cx, bx ; Height + inc cx + + ; Calcul adresse start + push cx + mov cx, .x + mov dx, bx + call ega_calc_addr ; DI start, AH mask + pop cx ; Restore Height + + ; Setup EGA + mov dx, GC_INDEX + mov al, 0x08 ; BitMask + out dx, al + inc dx + mov al, ah ; Le masque calculé + out dx, al + dec dx + + mov ax, 0x0205 ; Write Mode 2 + out dx, ax + + mov al, .color + + .v_loop: + mov ah, [es:di] ; Latch + mov [es:di], al ; Write Color + add di, EGA_STRIDE + loop .v_loop + + ; Reset + mov ax, 0x0005 + out dx, ax + mov ax, 0xFF08 + out dx, ax + + call ega_mouse_show + pop es + popa + leave + ret +%undef .x +%undef .y1 +%undef .y2 +%undef .color + +; ------------------------------------------------------------ +; Wrapper fonctions géométriques (inchangées logique high-level) +; ------------------------------------------------------------ +%define .x1 word [bp+4] +%define .y1 word [bp+6] +%define .x2 word [bp+8] +%define .y2 word [bp+10] +%define .color word [bp+12] +ega_draw_rect: + push bp + mov bp, sp + pusha + ; Simplifié: appels GFX internes + GFX LINE_HORIZ, .x1, .x2, .y1, .color + GFX LINE_HORIZ, .x1, .x2, .y2, .color + GFX LINE_VERT, .x1, .y1, .y2, .color + GFX LINE_VERT, .x2, .y1, .y2, .color + popa + leave + ret +%undef .x1 +%undef .y1 +%undef .x2 +%undef .y2 +%undef .color + +; ------------------------------------------------------------ +; ega_fill_rect +; Adapté pour EGA (plus complexe à cause des patterns et plans) +; Pour cette version, on fait un remplissage couleur unie simple +; si pattern_id < 4, sinon blanc. +; ------------------------------------------------------------ +%define .x1 word [bp+4] +%define .y1 word [bp+6] +%define .x2 word [bp+8] +%define .y2 word [bp+10] +%define .pat word [bp+12] +ega_fill_rect: + push bp + mov bp, sp + ; ... Implementation simplifiée utilisant des lignes horizontales + ; car le remplissage pattern 1bpp sur 4 plans EGA est verbeux + pusha + + mov cx, .y1 + mov dx, .y2 + cmp cx, dx + jle .loop + xchg cx, dx + .loop: + push cx + push dx + ; Couleur dérivée du pattern (simplification) + mov ax, .pat + cmp ax, 0 + je .blk + mov ax, 15 ; White + jmp .do_line + .blk: + mov ax, 0 + .do_line: + + GFX LINE_HORIZ, .x1, .x2, cx, ax + + pop dx + pop cx + inc cx + cmp cx, dx + jle .loop + + popa + leave + ret +%undef .x1 +%undef .y1 +%undef .x2 +%undef .y2 +%undef .pat + +; ------------------------------------------------------------ +; ega_draw_rounded_frame (Identique CGA, appels GFX) +; ------------------------------------------------------------ +%define .x1 word [bp+4] +%define .y1 word [bp+6] +%define .x2 word [bp+8] +%define .y2 word [bp+10] +%define .color word [bp+12] +ega_draw_rounded_frame: + push bp + mov bp, sp + pusha + call ega_mouse_hide + + mov ax, .x1 + add ax, 2 + mov bx, .x2 + sub bx, 2 + GFX LINE_HORIZ, ax, bx, .y1, .color + GFX LINE_HORIZ, ax, bx, .y2, .color + + mov cx, .y1 + add cx, 2 + mov dx, .y2 + sub dx, 2 + GFX LINE_VERT, .x1, cx, dx, .color + GFX LINE_VERT, .x2, cx, dx, .color + + ; Coins (PutPixel wrappers) + mov ax, .x1 + inc ax + mov bx, .y1 + inc bx + GFX PUTPIXEL, ax, bx, .color + + mov ax, .x1 + inc ax + mov bx, .y2 + dec bx + GFX PUTPIXEL, ax, bx, .color + + mov ax, .x2 + dec ax + mov bx, .y1 + inc bx + GFX PUTPIXEL, ax, bx, .color + + mov ax, .x2 + dec ax + mov bx, .y2 + dec bx + GFX PUTPIXEL, ax, bx, .color + + call ega_mouse_show + popa + leave + ret +%undef .x1 +%undef .y1 +%undef .x2 +%undef .y2 +%undef .color + +; ============================================================ +; GESTION SOURIS EGA +; ============================================================ +; Le buffer souris doit être plus grand : 16x16 pixels +; = 2 octets de large x 16 haut x 4 plans = 128 bytes. +; ============================================================ + +ega_mouse_hide: + pushf + cli + pushad + push ds + mov ax, BDA_DATA_SEG + mov ds, ax + dec byte [BDA_MOUSE + mouse.cur_counter] + cmp byte [BDA_MOUSE + mouse.cur_counter], -1 + jne .skip + call ega_cursor_restorebg + .skip: + pop ds + popad + popf + ret + +ega_mouse_show: + pushf + cli + pushad + push ds + mov ax, BDA_DATA_SEG + mov ds, ax + inc byte [BDA_MOUSE + mouse.cur_counter] + cmp byte [BDA_MOUSE + mouse.cur_counter], 0 + jne .skip + call ega_cursor_savebg + call ega_cursor_draw + .skip: + pop ds + popad + popf + ret + +ega_mouse_cursor_move: + pushad + push ds + push es + mov ax, BDA_DATA_SEG + mov ds, ax + cmp byte [BDA_MOUSE + mouse.cur_counter], 0 + jl .done + cmp byte [BDA_MOUSE + mouse.cur_drawing], 0 + jne .done + mov byte [BDA_MOUSE + mouse.cur_drawing], 1 + + mov ax, VIDEO_SEG + mov es, ax + + call ega_cursor_restorebg + call ega_cursor_savebg + call ega_cursor_draw + + mov byte [BDA_MOUSE + mouse.cur_drawing], 0 + .done: + pop es + pop ds + popad + ret + +; ------------------------------------------------------------ +; Save Background (4 planes) +; Lit 2 octets par ligne (16px large), sur 16 lignes, sur 4 plans +; Buffer size needed ~ 128 bytes +; ------------------------------------------------------------ +ega_cursor_savebg: + cmp byte [BDA_MOUSE + mouse.bkg_saved], 0 + jne .done + + push es + mov ax, VIDEO_SEG + mov es, ax + + ; Calc Offset + mov cx, [BDA_MOUSE + mouse.x] + mov dx, [BDA_MOUSE + mouse.y] + mov [BDA_MOUSE + mouse.cur_x], cx + mov [BDA_MOUSE + mouse.cur_y], dx + call ega_calc_addr_internal ; DI = Offset + + mov [BDA_MOUSE + mouse.cur_addr_start], di + lea si, [BDA_MOUSE + mouse.bkg_buffer] + + mov dx, GC_INDEX + + ; Boucle sur les 4 plans + mov bl, 0 ; Plan index + .plane_loop: + mov ah, bl + mov al, 0x04 ; Read Map Select + out dx, ax + + push di ; Save screen offset start + mov cx, 16 ; Height + .row_loop: + mov al, [es:di] ; Byte 1 + mov [ds:si], al + inc si + mov al, [es:di+1] ; Byte 2 (Cursor is 16px wide max) + mov [ds:si], al + inc si + add di, EGA_STRIDE + loop .row_loop + pop di ; Restore screen offset + + inc bl + cmp bl, 4 + jl .plane_loop + + mov byte [BDA_MOUSE + mouse.bkg_saved], 1 + .done: + pop es + ret + +; ------------------------------------------------------------ +; Restore Background +; ------------------------------------------------------------ +ega_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] + + mov dx, GC_INDEX + mov ax, 0x0005 ; Write Mode 0 + out dx, ax + mov ax, 0xFF08 ; Mask all + out dx, ax + + mov dx, SC_INDEX ; Sequencer pour Map Mask + + mov bl, 1 ; Map Mask bit (Plan 0 = 1) + .plane_loop: + mov al, SC_MAP_MASK + mov ah, bl + out dx, ax ; Select Plane to write + + push di + mov cx, 16 + .row_loop: + lodsb ; Load Byte 1 from buffer + mov [es:di], al + lodsb ; Load Byte 2 + mov [es:di+1], al + add di, EGA_STRIDE + loop .row_loop + pop di + + shl bl, 1 + cmp bl, 16 ; Bit 4 = Fin + jl .plane_loop + + ; Restore Map Mask to All + mov ax, 0x0F02 + out dx, ax + + mov byte [BDA_MOUSE + mouse.bkg_saved], 0 + pop es + .done: + ret + +; ------------------------------------------------------------ +; Draw Cursor (Fleche simple, Write Mode 2 ou Masking) +; Pour simplicité : on dessine un bloc blanc 8x8 via PutPixel +; ou un sprite hardcodé. +; ------------------------------------------------------------ +ega_cursor_draw: + pushad + push es + mov ax, VIDEO_SEG + mov es, ax + + ; Utilisation d'un masque simple pour dessiner une croix + ; X, Y centre + mov cx, [BDA_MOUSE + mouse.x] + mov dx, [BDA_MOUSE + mouse.y] + + ; Dessine une croix rouge (Color 4) de 10x10 + mov bx, 10 + .l1: + ; Horizontal + mov ax, cx + add ax, bx + GFX PUTPIXEL, ax, dx, 4 + ; Vertical + mov ax, dx + add ax, bx + GFX PUTPIXEL, cx, ax, 4 + dec bx + jnz .l1 + + pop es + popad + ret \ No newline at end of file diff --git a/src/drivers/mouse_ps2.asm b/src/drivers/mouse_ps2.asm index 6396a03..b106abb 100644 --- a/src/drivers/mouse_ps2.asm +++ b/src/drivers/mouse_ps2.asm @@ -372,7 +372,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 + ; call cga_mouse_cursor_move + GFX MOUSE_MOVE .done_eoi: mov al, 0x20 out i8259_SLAVE_CMD, al ; EOI PIC esclave