add cga_line_xxxxx

This commit is contained in:
Frater 2026-01-29 22:05:57 +01:00
commit 2fb87be644
5 changed files with 528 additions and 246 deletions

View file

@ -42,7 +42,7 @@ The project is intentionally educational, experimental, and minimalist.
- Real-mode execution constraints - Real-mode execution constraints
- **Improve mastery of x86 assembly** - **Improve mastery of x86 assembly**
- Real-mode x86 assembly (8086-compatible) - Real-mode x86 assembly (i386+ compatible)
- Performance-oriented routines - Performance-oriented routines
- Hardware-near programming - Hardware-near programming
- Clear separation between hardware-specific drivers and core logic - Clear separation between hardware-specific drivers and core logic
@ -165,7 +165,7 @@ Le projet est volontairement **éducatif, expérimental et minimaliste**.
- Contraintes du mode réel - Contraintes du mode réel
- **Perfectionner la maîtrise de l’assembleur** - **Perfectionner la maîtrise de l’assembleur**
- Assembleur x86 en mode réel (compatible 8086) - Assembleur x86 en mode réel (i386+ compatible)
- Routines optimisées pour la performance - Routines optimisées pour la performance
- Programmation proche du matériel - Programmation proche du matériel
- Séparation claire entre cœur du BIOS et drivers matériels - Séparation claire entre cœur du BIOS et drivers matériels

View file

@ -55,29 +55,26 @@
%define BKG_TOTAL_BYTES (BKG_TOTAL_DWORDS * 4) ; 64 %define BKG_TOTAL_BYTES (BKG_TOTAL_DWORDS * 4) ; 64
struc mouse struc mouse
.buffer resb 4 ; i8042 input buffer 0..3 .buffer resb 4 ; i8042 input buffer
.idx resb 1 ; index in the buffer 4 .idx resb 1 ; index in the buffer
.packetlen resb 1 ; max buffer len (3 ou 4) 5 .packetlen resb 1 ; max buffer len (3 ou 4)
.blinker resb 1 ; .status resb 1 ; mouse status (button etc)
.wheel resb 1 ; if a packet size is 4; experimental
.status resb 1 ; mouse status (button etc) 6 .x resw 1 ;
.wheel resb 1 ; if a packet size is 4; experimental 7 .y resw 1 ;
.x resw 1 ; 8..9
.y resw 1 ; A..B
; cursor management ; cursor management
.cur_x resw 1 ; preservation des x,y du background C..D .cur_x resw 1 ; preservation des x,y du background
.cur_y resw 1 ; E..F .cur_y resw 1 ;
.cur_addr_start resw 1 ; adresse de départ de la sauvegarde 10..11 .cur_addr_start resw 1 ; adresse de départ de la sauvegarde
.cur_bank_add resw 1 ; + ou - 0x2000 12..13
.cur_drawing resb 1 ; 14 .cur_drawing resb 1 ;
.cur_visible resb 1 ; 15 .cur_visible resb 1 ;
.cur_seg resw 1 ; segment / offset of the pointer 16..17 .cur_counter resb 1 ; compteur de fois que le curseur a été caché (0 = visible, <0 = invisible)
.cur_ofs resw 1 ; 18..19 .cur_seg resw 1 ; segment / offset of the pointer
.cur_mask resb 1 ; pixels mask (bit per pixel) 1A .cur_ofs resw 1 ;
.cur_bit_ofs resb 1 ; 0..7 bits d'offset (x&7) 1B .cur_mask resb 1 ; pixels mask (bit per pixel)
.bkg_saved resb 1 ; background saved 1C .bkg_saved resb 1 ; background saved
alignb 4 ; alignement 4 bytes 1D alignb 4 ; alignement 4 bytes
.bkg_buffer resd 16 ; buffer for saved background .bkg_buffer resd 16 ; buffer for saved background
endstruc endstruc

View file

@ -203,13 +203,6 @@ endless:
mov ax, [BDA_MOUSE + mouse.y] mov ax, [BDA_MOUSE + mouse.y]
call print_word_hex call print_word_hex
mov al,' '
call cga_putc
xor ah,ah
mov al, [BDA_MOUSE + mouse.blinker]
call print_word_hex
jmp endless jmp endless

View file

@ -59,10 +59,9 @@
%define GFX_PUTPIXEL 1 %define GFX_PUTPIXEL 1
%define GFX_GETPIXEL 2 %define GFX_GETPIXEL 2
%define GFX_GOTOXY 3 %define GFX_GOTOXY 3
%define GFX_PUTCH_MODE 4 %define GFX_PUTCH 4
%define GFX_PUTCH 5 %define GFX_WRITE 5
%define GFX_WRITE 6 %define GFX_CRS_UPDATE 6
%define GFX_CRS_UPDATE 7
; ------------------------------------------------------------ ; ------------------------------------------------------------
; COMMENTAIRE SUR LA MÉTHODE D'APPEL ; COMMENTAIRE SUR LA MÉTHODE D'APPEL
@ -80,14 +79,16 @@
; ------------------------------------------------------------ ; ------------------------------------------------------------
graph_driver: graph_driver:
dw cga_init dw cga_init ; init de la carte graphique
dw cga_putpixel dw cga_putpixel ; dessin d'un pixel
dw cga_getpixel dw cga_getpixel ; lecture d'un pixel
dw cga_set_charpos dw cga_set_charpos ; gotoxy
dw cga_none dw cga_putc ; dessin d'un caractère
dw cga_putc dw cga_write ; dessin d'une chaine de caractère
dw cga_write dw cga_mouse_cursor_move ; déplacement du curseur
dw cga_cursor_move dw cga_line_vertical ; dessin d'une ligne verticale
; jmp gfx_fill_rect ; Remplissage rectangle (Nouveau) ; jmp gfx_fill_rect ; Remplissage rectangle (Nouveau)
; jmp gfx_invert_rect ; Offset +12: Inversion (Nouveau pour Menus) ; jmp gfx_invert_rect ; Offset +12: Inversion (Nouveau pour Menus)
; jmp gfx_draw_hline ; Offset +15: Ligne horizontale rapide (Nouveau) ; jmp gfx_draw_hline ; Offset +15: Ligne horizontale rapide (Nouveau)
@ -137,6 +138,7 @@ cga_init:
call cga_background call cga_background
ret ret
; dummy functions
cga_none: cga_none:
ret ret
@ -161,7 +163,7 @@ cga_calc_addr:
test dl, 1 test dl, 1
jz .even jz .even
add di, CGA_ODD_BANK add di, CGA_ODD_BANK
.even: .even:
; masque bit = 0x80 >> (x&7) ; masque bit = 0x80 >> (x&7)
push cx push cx
and cl, 7 and cl, 7
@ -179,47 +181,47 @@ cga_calc_addr:
; - stocke aussi shift = x&7 ; - stocke aussi shift = x&7
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
cga_set_charpos: cga_set_charpos:
pusha pusha
push fs push fs
mov ax,BDA_DATA_SEG mov ax,BDA_DATA_SEG
mov fs,ax mov fs,ax
; store x,y en pixel ; store x,y en pixel
mov [fs:BDA_GFX + gfx.cur_x], cx mov [fs:BDA_GFX + gfx.cur_x], cx
mov [fs:BDA_GFX + gfx.cur_y], dx mov [fs:BDA_GFX + gfx.cur_y], dx
mov ax, cx mov ax, cx
and ax, 0x07 and ax, 0x07
mov [fs:BDA_GFX + gfx.cur_shift], al mov [fs:BDA_GFX + gfx.cur_shift], al
; calcul de l'offset de la position 'x,y': ; calcul de l'offset de la position 'x,y':
; si 'y' est paire, DI < 0x2000 & add = 0x2000 ; si 'y' est paire, DI < 0x2000 & add = 0x2000
; si 'y' est impaire, DI> 0x2000 & add = -0x2000 ; si 'y' est impaire, DI> 0x2000 & add = -0x2000
; DI = (y>>1)*80 + (x>>3) + (y&1)* ; DI = (y>>1)*80 + (x>>3) + (y&1)*
mov ax, dx mov ax, dx
shr ax, 1 shr ax, 1
mov bx, ax ; bx = dx>>1 mov bx, ax ; bx = dx>>1
shl bx, 4 ; bx = bx * 16 shl bx, 4 ; bx = bx * 16
shl ax, 6 ; ax = ax * 64 shl ax, 6 ; ax = ax * 64
add bx, ax add bx, ax
mov ax, cx mov ax, cx
shr ax, 3 ; ax = x/8 shr ax, 3 ; ax = x/8
add bx, ax add bx, ax
mov ax, CGA_ODD_BANK mov ax, CGA_ODD_BANK
test dl, 1 test dl, 1
jz .even jz .even
add bx, ax add bx, ax
neg ax neg ax
add ax, CGA_STRIDE add ax, CGA_STRIDE
.even: .even:
mov [fs:BDA_GFX + gfx.cur_line_ofs], ax mov [fs:BDA_GFX + gfx.cur_line_ofs], ax
mov [fs:BDA_GFX + gfx.cur_offset], bx mov [fs:BDA_GFX + gfx.cur_offset], bx
pop fs pop fs
popa popa
ret ret
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; get_glyph_offset ; get_glyph_offset
@ -227,21 +229,23 @@ cga_set_charpos:
; Out: CS:SI -> 8 bytes ; Out: CS:SI -> 8 bytes
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
get_glyph_offset: get_glyph_offset:
cmp al, 0x20 cmp al, 0x20
jb .qmark ; al < 20h (' ' jb .qmark ; al < 20h (' '
cmp al, 0x7E cmp al, 0x7E
ja .qmark ; al > 7Eh ('~') ja .qmark ; al > 7Eh ('~')
sub al, 0x20 sub al, 0x20
jmp .ok jmp .ok
.qmark:
mov al, '?' .qmark:
sub al, 0x20 mov al, '?'
.ok: sub al, 0x20
xor ah, ah
mov si, ax .ok:
shl si, 3 xor ah, ah
add si, font8x8 mov si, ax
ret shl si, 3
add si, font8x8
ret
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; cga_putc_unalign ; cga_putc_unalign
@ -269,7 +273,8 @@ cga_putc:
mov ch, [fs:BDA_GFX + gfx.cur_mode] mov ch, [fs:BDA_GFX + gfx.cur_mode]
mov cl, [fs:BDA_GFX + gfx.cur_shift] mov cl, [fs:BDA_GFX + gfx.cur_shift]
mov bp,4 mov bp,4
.row_loop:
.row_loop:
; gestion du fond de texte ; gestion du fond de texte
test ch, 00000010b ; transparent background ? test ch, 00000010b ; transparent background ?
jz .skip_attribut ; oui jz .skip_attribut ; oui
@ -285,7 +290,7 @@ cga_putc:
or [es:di+bx], ax or [es:di+bx], ax
jmp .skip_attribut jmp .skip_attribut
.bkg_black: ; OK .bkg_black: ; OK
; background = black ; background = black
mov ax, 0xFF00 mov ax, 0xFF00
shr ax, cl shr ax, cl
@ -294,7 +299,7 @@ cga_putc:
and [es:di], ax and [es:di], ax
and [es:di+bx], ax and [es:di+bx], ax
.skip_attribut: .skip_attribut:
; ligne "paire" du gylphe ; ligne "paire" du gylphe
xor ax, ax xor ax, ax
mov al, [cs:si] mov al, [cs:si]
@ -319,11 +324,11 @@ cga_putc:
jmp .next jmp .next
.black_text: .black_text:
or [es:di], ax or [es:di], ax
or [es:di+bx], dx or [es:di+bx], dx
.next: .next:
add di,CGA_STRIDE add di,CGA_STRIDE
dec bp dec bp
@ -344,14 +349,14 @@ cga_putc:
cga_write: cga_write:
push ax push ax
.loops: .loops:
lodsb lodsb
cmp al,0 cmp al,0
je .done je .done
call cga_putc call cga_putc
jmp .loops jmp .loops
.done:
.done:
pop ax pop ax
ret ret
@ -364,21 +369,22 @@ cga_write:
; BL = color (0=black, !=0=white) ; BL = color (0=black, !=0=white)
; ------------------------------------------------------------ ; ------------------------------------------------------------
cga_local_putpixel: cga_local_putpixel:
call cga_calc_addr call cga_calc_addr
; write ; write
cmp bl, 0 cmp bl, 0
je .clear je .clear
.set:
or byte [es:di], ah
jmp .done
.clear: .set:
not ah or byte [es:di], ah
and byte [es:di], ah jmp .done
.done: .clear:
ret not ah
and byte [es:di], ah
.done:
ret
; ------------------------------------------------------------ ; ------------------------------------------------------------
; Dessine un pixel, accès VRAM direct. ; Dessine un pixel, accès VRAM direct.
@ -388,75 +394,64 @@ cga_local_putpixel:
; BL = color (0=black, !=0=white) ; BL = color (0=black, !=0=white)
; ------------------------------------------------------------ ; ------------------------------------------------------------
cga_putpixel: cga_putpixel:
push ax push ax
push di push di
push es push es
mov ax, VIDEO_SEG
mov es,ax
call cga_calc_addr
mov ax, VIDEO_SEG ; write
mov es,ax cmp bl, 0
call cga_calc_addr je .clear
; write .set:
cmp bl, 0 or byte [es:di], ah
je .clear jmp .done
.set:
or byte [es:di], ah
jmp .done
.clear: .clear:
not ah not ah
and byte [es:di], ah and byte [es:di], ah
.done: .done:
pop es pop es
pop di pop di
pop ax pop ax
ret ret
; ------------------------------------------------------------ ; ------------------------------------------------------------
; Lit un pixel (CX=x, DX=y) ; Lit un pixel (CX=x, DX=y)
; Out: AL=0/1 ; Out: AL=0/1
; ------------------------------------------------------------ ; ------------------------------------------------------------
cga_getpixel: cga_getpixel:
push di push di
push es push es
call cga_calc_addr call cga_calc_addr
mov al, [es:di] mov al, [es:di]
and al, ah and al, ah
setnz al setnz al
pop es pop es
pop di pop di
ret ret
; ------------------------------------------------------------ ; ------------------------------------------------------------
; Dessine un background "check-board", accès VRAM direct. ; Dessine un background "check-board", accès VRAM direct.
; ;
; ------------------------------------------------------------ ; ------------------------------------------------------------
cga_background: cga_background:
mov ax,VIDEO_SEG mov ax,VIDEO_SEG
mov es,ax mov es,ax
mov di,0x0000 mov di,0x0000
mov eax,0xaaaaaaaa mov eax,0xaaaaaaaa
mov cx,0x800 mov cx,0x800
rep stosd rep stosd
mov di,0x2000 mov di,0x2000
mov eax,0x55555555 mov eax,0x55555555
mov cx,0x800 ; 640/8/4 mov cx,0x800 ; 640/8/4
rep stosd rep stosd
ret ret
; ------------------------------------------------------------
; Calcule les infos de l'alignement du curseur, basé sur cx=X
; il est important que DS pointe sur le BDA_MOUSE_SEG
; Out: BDA_CURSOR_BITOFF, BDA_CURSOR_BYTES
; ------------------------------------------------------------
cga_cursor_calc_align:
mov al, cl
and al, 7 ; offset = x&7
mov byte [BDA_MOUSE + mouse.cur_bit_ofs], al
ret
; ------------------------------------------------------------ ; ------------------------------------------------------------
; Dessine un pixel, en [ES:DI] accès VRAM direct. ; Dessine un pixel, en [ES:DI] accès VRAM direct.
@ -466,63 +461,355 @@ cga_cursor_calc_align:
; BL = color (0=black, !=0=white) ; BL = color (0=black, !=0=white)
; ------------------------------------------------------------ ; ------------------------------------------------------------
cga_putpixel_fast: cga_putpixel_fast:
cmp bl, 0 cmp bl, 0
je .clear je .clear
.set:
or byte [es:di], ah .set:
jmp .done or byte [es:di], ah
.clear: jmp .done
not ah
and byte [es:di], ah .clear:
.done: not ah
ret and byte [es:di], ah
.done:
ret
; ------------------------------------------------------------ ; ------------------------------------------------------------
; Lit un pixel, en [ES:DI] accès VRAM direct. ; Lit un pixel, en [ES:DI] accès VRAM direct.
; ;
; ------------------------------------------------------------ ; ------------------------------------------------------------
cga_getpixel_fast: cga_getpixel_fast:
mov al, [es:di] mov al, [es:di]
and al, ah and al, ah
setnz al setnz al
ret ret
cga_cursor_move: ; ------------------------------------------------------------
push ax ; cga_line_vertical
push ds ; Dessine une ligne de (AX, BX) à (AX, DX) cl: color
push es ; ------------------------------------------------------------
cga_line_vertical:
pusha
push es
; move Data Segment ; Setup ES = Video Segment (0xB800)
mov ax, BDA_DATA_SEG mov si, VIDEO_SEG
mov ds, ax mov es, si
cmp byte [BDA_MOUSE + mouse.cur_visible], 0 call cga_mouse_hide
je .done
cmp byte [BDA_MOUSE + mouse.cur_drawing],0 ; Ordonner Y (BX < DX)
jne .done cmp bx, dx
mov byte [BDA_MOUSE + mouse.cur_drawing],1 jle .y_sorted
xchg bx, dx
.y_sorted:
mov ax, VIDEO_SEG ; Calculer l'adresse du premier point (X, Y_Start)
mov es, ax push dx ; Sauve Y_Fin
push cx ; Sauve Couleur
call cga_cursor_restorebg mov cx, ax ; CX = X (pour cga_calc_addr)
mov dx, bx ; DX = Y_Start (pour cga_calc_addr)
call cga_calc_addr ; Return: DI=Offset, AH=BitMask (ex: 00100000)
call cga_cursor_savebg pop cx ; Récup Couleur
pop dx ; Récup Y_Fin (dans DX)
call cga_cursor_draw ; Préparer le masque inverse pour le cas "Noir" (AND)
mov byte [BDA_MOUSE + mouse.cur_drawing],0 mov al, ah ; AL = Masque (00100000)
.done: not al ; AL = ~Masque (11011111)
pop es
pop ds
pop ax
ret
; ----------------------------------------------- ; BX sert maintenant de compteur courant, on a Y_Fin dans DX
; cga_cursor_savebg_32 ; Utilisons BP comme compteur de hauteur.
; Sauve 16 lignes (3 bytes/ligne) sous le curseur.
; Stocke 16 DWORDs: chaque DWORD contient (b0|b1<<8|b2<<16) dans les 24 bits bas. sub dx, bx ; DX = Hauteur - 1 (delta)
; ----------------------------------------------- inc dx ; DX = Nombre de pixels à dessiner
.v_loop:
cmp cl, 0
jz .draw_black
.draw_white:
or byte [es:di], ah ; Allumer le bit
jmp .next_line
.draw_black:
and byte [es:di], al ; Eteindre le bit
.next_line:
; --- Logique Next Line CGA (Optimisée) ---
xor di, 0x2000 ; Flip banque (Pair <-> Impair)
test di, 0x2000 ; Si on est passé à 0x2000 (Impair), on a juste descendu de 1 ligne visuelle
jnz .skip_add ; C'est bon.
add di, 80 ; Si on revient à 0x0000 (Pair), on doit avancer de 80 octets
.skip_add:
dec dx
jnz .v_loop
call cga_mouse_show
pop es
popa
ret
; ------------------------------------------------------------
; cga_line_horizontal
; Dessine une ligne de (AX, DX) à (BX, DX) CL: color
; ------------------------------------------------------------
cga_line_horizontal:
pusha
push es
call cga_mouse_hide
mov si, VIDEO_SEG
mov es, si
; 1. Ordonner X (AX < BX)
cmp ax, bx
jle .x_sorted
xchg ax, bx
.x_sorted:
; Calculer l'adresse de départ
; On a besoin de l'adresse de l'octet de AX.
push cx ; Sauve Couleur
push bx ; Sauve X_Fin
mov cx, ax ; CX = X_Start
; DX est déjà Y
call cga_calc_addr ; DI = Offset du premier byte
; AH = Masque du bit précis (pas utile pour le remplissage, on recalculera)
pop bx ; Récup X_Fin
pop cx ; Récup Couleur (CL)
; --- ANALYSE DES OCTETS ---
; Start Byte Index = AX >> 3
; End Byte Index = BX >> 3
mov si, ax ; SI = X_Start
shr si, 3 ; Byte index start
mov bp, bx ; BP = X_Fin
shr bp, 3 ; Byte index end
; Cas spécial : Tout tient dans le même octet ?
cmp si, bp
je .single_byte
; ============================================
; CAS MULTI-BYTE
; ============================================
; --- 1. Gérer l'octet de GAUCHE (Start) ---
; On doit dessiner du bit (AX&7) jusqu'au bit 0 (droite de l'octet)
; Masque = 0xFF >> (AX & 7)
push cx ; Save couleur
mov cx, ax
and cx, 7 ; X % 8
mov al, 0xFF
shr al, cl ; AL = Masque Gauche (ex: si X%8=2, 00111111)
pop cx ; Restore couleur
call .apply_mask_at_di ; Applique AL sur [ES:DI] selon CL
inc di ; Octet suivant
inc si ; Index suivant
; --- 2. Gérer le MILIEU (Full Bytes) ---
; Tant que SI < BP, on remplit tout l'octet
jmp .check_middle
.loop_middle:
cmp cl, 0
jz .middle_black
mov byte [es:di], 0xFF ; Blanc total
jmp .middle_next
.middle_black:
mov byte [es:di], 0x00 ; Noir total
.middle_next:
inc di
inc si
.check_middle:
cmp si, bp
jl .loop_middle ; Continue tant qu'on n'est pas au dernier octet
; Gérer l'octet de DROITE (End) ---
; On doit dessiner du bit 7 jusqu'au bit (BX&7)
; Masque = ~(0xFF >> ((BX & 7) + 1))
; Ex: Si Fin%8 = 0 (1 pixel), shift 1 -> 01111111, NOT -> 10000000. Correct.
push cx
mov cx, bx
and cx, 7
inc cx ; Nb de pixels à garder à gauche
mov al, 0xFF
shr al, cl ; Masque des pixels à IGNORER (droite)
not al ; Masque des pixels à DESSINER (gauche)
pop cx
call .apply_mask_at_di
jmp .done
; ============================================
; CAS SINGLE BYTE (Début et Fin dans le même octet)
; ============================================
.single_byte:
; Masque Start = 0xFF >> (AX & 7)
push cx
mov cx, ax
and cx, 7
mov ah, 0xFF
shr ah, cl ; AH = Masque départ (ex: 00011111)
; Masque End (Pixels à garder jusqu'à BX)
; On veut garder les pixels de 7 jusqu'à BX&7
; Astuce: Masque Combiné = MasqueStart AND MasqueEnd
mov cx, bx
and cx, 7
inc cx
mov al, 0xFF
shr al, cl
not al ; AL = Masque Fin (ex: 11110000)
and al, ah ; Intersection des deux masques
pop cx
call .apply_mask_at_di
jmp .done
; --- Helper interne : Applique le masque AL à l'adresse DI selon couleur CL ---
.apply_mask_at_di:
cmp cl, 0
jz .apply_black
or [es:di], al ; Blanc: OR Masque
ret
.apply_black:
not al ; Noir: AND ~Masque
and [es:di], al
ret
.done:
call cga_mouse_show
pop es
popa
ret
;
; ------------------------------------------------------------
; GESTION DU CURSEUR
; ------------------------------------------------------------
;
; ------------------------------------------------------------
; gère la demande d'effacement du curseur souris
;
; ------------------------------------------------------------
cga_mouse_hide:
pushf ; Sauver l'état des flags (interrupts)
cli ; Désactiver les interruptions (CRITIQUE)
push ax
push ds
mov ax, BDA_DATA_SEG
mov ds, ax
; Décrémenter le compteur
dec byte [BDA_MOUSE + mouse.cur_counter]
; Vérifier si on vient juste de passer en mode caché (c-à-d on est à -1)
cmp byte [BDA_MOUSE + mouse.cur_counter], -1
jne .skip_restore ; Si on est à -2, -3... elle est déjà cachée
; C'est la transition Visible -> Caché : On efface le curseur
call cga_cursor_restorebg
; On marque qu'on ne dessine plus
mov byte [BDA_MOUSE + mouse.bkg_saved], 0
.skip_restore:
pop ds
pop ax
popf ; Restaure les interruptions (STI si elles étaient là)
ret
; ------------------------------------------------------------
; gère la demande d'affichage du curseur souris
;
; ------------------------------------------------------------
cga_mouse_show:
pushf
cli
push ax
push ds
mov ax, BDA_DATA_SEG
mov ds, ax
; Incrémenter le compteur
inc byte [BDA_MOUSE + mouse.cur_counter]
; Vérifier si on est revenu à 0 (Visible)
cmp byte [BDA_MOUSE + mouse.cur_counter], 0
jne .skip_draw ; Si on est encore à -1, -2... on reste caché
; C'est la transition Caché -> Visible : On affiche le curseur
; IMPORTANT : On sauve le fond ACTUEL (qui a peut-être changé pendant le hide)
call cga_cursor_savebg
call cga_cursor_draw
.skip_draw:
pop ds
pop ax
popf
ret
; ------------------------------------------------------------
; gère le déplacement du curseur souris
;
; ------------------------------------------------------------
cga_mouse_cursor_move:
push ax
push ds
push es
; move Data Segment
mov ax, BDA_DATA_SEG
mov ds, ax
cmp byte [BDA_MOUSE + mouse.cur_counter], 0
jl .done ; Si < 0, on ne dessine rien !
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 cga_cursor_restorebg
call cga_cursor_savebg
call cga_cursor_draw
mov byte [BDA_MOUSE + mouse.cur_drawing],0
.done:
pop es
pop ds
pop ax
ret
; ------------------------------------------------------------
; cga_cursor_savebg
; Sauve 16 lignes (4 bytes/ligne) sous le curseur.
; Stocke 16 DWORDs: chaque DWORD contient les 4 bytes de la ligne
; ------------------------------------------------------------
cga_cursor_savebg: cga_cursor_savebg:
cmp byte [BDA_MOUSE + mouse.bkg_saved], 0 ; le buffer n'a pas encore été restauré cmp byte [BDA_MOUSE + mouse.bkg_saved], 0 ; le buffer n'a pas encore été restauré
jne .done jne .done
@ -542,7 +829,8 @@ cga_cursor_savebg:
lea si, [BDA_MOUSE + mouse.bkg_buffer] lea si, [BDA_MOUSE + mouse.bkg_buffer]
mov cx,16 mov cx,16
.row_loop:
.row_loop:
; ---- ligne bank courant ---- ; ---- ligne bank courant ----
mov eax, [es:di] ; lit b0 b1 b2 b3 mov eax, [es:di] ; lit b0 b1 b2 b3
mov [ds:si], eax ; stocke 4 bytes (le byte haut sera 0) mov [ds:si], eax ; stocke 4 bytes (le byte haut sera 0)
@ -552,17 +840,17 @@ cga_cursor_savebg:
test di, 0x2000 test di, 0x2000
jnz .next_line jnz .next_line
add di, CGA_STRIDE ; avance de 2 lignes dans bank courant add di, CGA_STRIDE ; avance de 2 lignes dans bank courant
.next_line:
.next_line:
loop .row_loop loop .row_loop
.done:
.done:
ret ret
; ----------------------------------------------- ; ------------------------------------------------------------
; cga_cursor_restorebg_32 ; cga_cursor_restorebg
; Restaure 16 lignes sauvegardées. ; Restaure 16 lignes sauvegardées.
; Pour ne pas écraser le 4e byte voisin: ; ------------------------------------------------------------
; dst = (dst & 0xFF000000) | (saved & 0x00FFFFFF)
; -----------------------------------------------
cga_cursor_restorebg: cga_cursor_restorebg:
cmp byte [BDA_MOUSE + mouse.bkg_saved], 0 cmp byte [BDA_MOUSE + mouse.bkg_saved], 0
je .done je .done
@ -573,7 +861,8 @@ cga_cursor_restorebg:
mov di, [BDA_MOUSE + mouse.cur_addr_start] mov di, [BDA_MOUSE + mouse.cur_addr_start]
lea si, [BDA_MOUSE + mouse.bkg_buffer] lea si, [BDA_MOUSE + mouse.bkg_buffer]
mov cx, 16 mov cx, 16
.row_loop:
.row_loop:
; ---- ligne bank courant ---- ; ---- ligne bank courant ----
mov eax, [ds:si] ; saved (32 bits) mov eax, [ds:si] ; saved (32 bits)
mov [es:di], eax ; restore line mov [es:di], eax ; restore line
@ -583,10 +872,11 @@ cga_cursor_restorebg:
test di, 0x2000 test di, 0x2000
jnz .next_line jnz .next_line
add di, CGA_STRIDE ; avance de 2 lignes dans bank courant add di, CGA_STRIDE ; avance de 2 lignes dans bank courant
.next_line:
.next_line:
loop .row_loop loop .row_loop
.done: .done:
ret ret
; ============================================================ ; ============================================================
@ -618,7 +908,8 @@ cga_cursor_draw:
jbe .y_ok ; y<= 200-16 jbe .y_ok ; y<= 200-16
mov bp, ax mov bp, ax
.y_ok:
.y_ok:
; On calcule si les 4 octets vont dépasser la ligne (80 octets) ; On calcule si les 4 octets vont dépasser la ligne (80 octets)
; X est en bits (0-639). X >> 3 donne l'octet de départ (0-79). ; X est en bits (0-639). X >> 3 donne l'octet de départ (0-79).
; Si StartByte >= 77, on déborde. ; Si StartByte >= 77, on déborde.
@ -639,15 +930,17 @@ cga_cursor_draw:
jne .check_78 jne .check_78
mov esi, 0x000000FF mov esi, 0x000000FF
jmp .mask_ready jmp .mask_ready
.check_78:
.check_78:
cmp cx, 78 cmp cx, 78
jne .check_79 jne .check_79
mov esi, 0x0000FFFF mov esi, 0x0000FFFF
jmp .mask_ready jmp .mask_ready
.check_79:
.check_79:
mov esi, 0x00FFFFFF ; Cas extrême (bord droit) mov esi, 0x00FFFFFF ; Cas extrême (bord droit)
.mask_ready: .mask_ready:
; On sauvegarde ce masque pour l'utiliser dans la boucle ; On sauvegarde ce masque pour l'utiliser dans la boucle
; On utilise la pile pour libérer les registres ; On utilise la pile pour libérer les registres
push esi ; [ESP] contient maintenant le masque push esi ; [ESP] contient maintenant le masque
@ -667,10 +960,11 @@ cga_cursor_draw:
test cx, 1 test cx, 1
jz .setup_done jz .setup_done
neg ax ; banque -1 neg ax ; banque -1
.setup_done:
.setup_done:
mov cx, ax mov cx, ax
.row_loop: .row_loop:
; --- CONSTRUCTION DES MASQUES (EAX/EBX) --- ; --- CONSTRUCTION DES MASQUES (EAX/EBX) ---
push cx ; préserver la banque "suivante" push cx ; préserver la banque "suivante"
mov cl, [BDA_MOUSE + mouse.x] mov cl, [BDA_MOUSE + mouse.x]
@ -712,14 +1006,15 @@ cga_cursor_draw:
jz .next_line jz .next_line
add di,80 add di,80
.next_line: .next_line:
neg cx ; prochaine banque = -banque neg cx ; prochaine banque = -banque
add si, 2 ; Prochaine ligne du sprite add si, 2 ; Prochaine ligne du sprite
dec bp dec bp
jnz .row_loop jnz .row_loop
pop esi pop esi
.exit_total:
.exit_total:
pop es pop es
pop ds pop ds
popad popad

View file

@ -66,9 +66,6 @@ mouse_reset:
; experiemntal ; experiemntal
mov byte [fs:BDA_MOUSE + mouse.wheel],0 mov byte [fs:BDA_MOUSE + mouse.wheel],0
; debug
mov byte [fs:BDA_MOUSE + mouse.blinker],0
ret ret
; ------------------------------------------------------------ ; ------------------------------------------------------------
@ -368,7 +365,7 @@ isr_mouse_handler:
.done: .done:
; update la position du curseur sur l'écran ; update la position du curseur sur l'écran
; en ce moment c'est commented out (debug) ; en ce moment c'est commented out (debug)
call cga_cursor_move call cga_mouse_cursor_move
.done_eoi: .done_eoi:
mov al, 0x20 mov al, 0x20
out i8259_SLAVE_CMD, al ; EOI PIC esclave out i8259_SLAVE_CMD, al ; EOI PIC esclave