add cga_line_xxxxx
This commit is contained in:
parent
c5124b35e3
commit
2fb87be644
5 changed files with 528 additions and 246 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
39
src/bda.asm
39
src/bda.asm
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue