vga lines WIP
This commit is contained in:
parent
4d95401339
commit
d2fb28b29c
3 changed files with 974 additions and 411 deletions
111
src/boot-vga.asm
111
src/boot-vga.asm
|
|
@ -60,7 +60,7 @@ section .text
|
||||||
%include "./common/debug_txt.asm"
|
%include "./common/debug_txt.asm"
|
||||||
|
|
||||||
; GUI
|
; GUI
|
||||||
; %include "./gui/lib-api.asm"
|
%include "./gui/lib-api.asm"
|
||||||
|
|
||||||
; --- Données texte ---
|
; --- Données texte ---
|
||||||
str_quit db "Quitter", 0
|
str_quit db "Quitter", 0
|
||||||
|
|
@ -106,9 +106,11 @@ entrycode:
|
||||||
call mouse_init
|
call mouse_init
|
||||||
GFX MOUSE_SHOW
|
GFX MOUSE_SHOW
|
||||||
|
|
||||||
|
|
||||||
|
call main_testing
|
||||||
.loops:
|
.loops:
|
||||||
call main_loop
|
hlt
|
||||||
jmp .loops
|
;jmp .loops
|
||||||
|
|
||||||
; --- Callbacks (Fonctions appelées par le moteur) ---
|
; --- Callbacks (Fonctions appelées par le moteur) ---
|
||||||
on_click_quit:
|
on_click_quit:
|
||||||
|
|
@ -119,44 +121,99 @@ on_click_quit:
|
||||||
on_click_hello:
|
on_click_hello:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
main_loop:
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
main_testing:
|
||||||
|
GFX LINE,10,10,10,67, 15
|
||||||
|
ret
|
||||||
|
|
||||||
%define .oldval word [bp-2]
|
%define .oldval word [bp-2]
|
||||||
%define .my_slider word [bp-4]
|
%define .my_slider word [bp-4]
|
||||||
%define .value word [bp-6]
|
%define .value word [bp-6]
|
||||||
|
main_loop:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
sub sp, 6
|
sub sp, 6
|
||||||
|
|
||||||
push cs
|
push cs
|
||||||
pop ds
|
pop ds
|
||||||
|
|
||||||
GFX TXT_MODE, GFX_TXT_WHITE
|
DEBUG 1
|
||||||
GFX GOTOXY, 10,50
|
ISADBG ISA_LEFT, 1
|
||||||
GFX WRITE, cs, str_hello
|
|
||||||
|
|
||||||
|
|
||||||
; Init du système GUI
|
; Init du système GUI
|
||||||
; call gui_init_system
|
call gui_init_system
|
||||||
|
DEBUG 2
|
||||||
|
ISADBG ISA_LEFT, 2
|
||||||
|
|
||||||
|
; --- CRÉATION DYNAMIQUE DES BOUTONS ---
|
||||||
|
|
||||||
|
; Créer Bouton 1 "QUITTER"
|
||||||
|
GUI OBJ_CREATE, OBJ_TYPE_BUTTON_ROUNDED, 10, 10, 80, 16
|
||||||
|
GUI OBJ_SET_TEXT, ax, cs, str_quit
|
||||||
|
; Créer Bouton 2 "HELLO"
|
||||||
|
GUI OBJ_CREATE, OBJ_TYPE_BUTTON_ROUNDED, 100, 50, 80, 16
|
||||||
|
GUI OBJ_SET_TEXT, ax, cs, str_hello
|
||||||
|
|
||||||
|
; Créer 3 checkbox "option"
|
||||||
|
GUI OBJ_CREATE, OBJ_TYPE_CHECKBOX, 200, 50, 100, 15
|
||||||
|
GUI OBJ_SET_TEXT, ax, cs, str_option1
|
||||||
|
|
||||||
|
GUI OBJ_CREATE, OBJ_TYPE_CHECKBOX, 200, 50+16, 100, 15
|
||||||
|
GUI OBJ_SET_TEXT, ax, cs, str_option2
|
||||||
|
|
||||||
|
GUI OBJ_CREATE, OBJ_TYPE_CHECKBOX, 200, 50+16*2, 100, 15
|
||||||
|
GUI OBJ_SET_TEXT, ax, cs, str_option3
|
||||||
|
|
||||||
|
DEBUG 3
|
||||||
|
ISADBG ISA_LEFT, 3
|
||||||
|
|
||||||
|
; Créer Slider (Drag)
|
||||||
|
GUI OBJ_CREATE, OBJ_TYPE_SLIDER, 10, 100, 150, 12
|
||||||
|
GUI OBJ_SET_MODE, ax, SLIDER_HORIZONTAL
|
||||||
|
GUI OBJ_SLIDER_SET_ATTR, ax, 10, 140, 10, 15
|
||||||
|
|
||||||
|
GUI OBJ_CREATE, OBJ_TYPE_SLIDER, 400, 10, 16, 150
|
||||||
|
mov .my_slider, ax
|
||||||
|
|
||||||
|
GUI OBJ_SET_MODE, .my_slider, SLIDER_VERTICAL
|
||||||
|
GUI OBJ_SLIDER_SET_ATTR, .my_slider, 0, 31, 0, 12
|
||||||
|
|
||||||
|
mov .oldval, 0x1256
|
||||||
|
mov .value, 0xFADE
|
||||||
|
|
||||||
|
DEBUG 4
|
||||||
|
ISADBG ISA_LEFT, 4
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
; call gui_process_all
|
call gui_process_all
|
||||||
|
GUI OBJ_GET_VAL, .my_slider
|
||||||
|
mov .value, ax
|
||||||
|
|
||||||
; mov dh, 1
|
cmp ax,.oldval
|
||||||
; mov dl, 10
|
je .loop
|
||||||
; call scr_gotoxy
|
|
||||||
;
|
; debug
|
||||||
; mov ax, SEG_BDA_CUSTOM
|
mov .oldval, ax
|
||||||
; mov fs, ax
|
GFX RECTANGLE_FILL,0,148,50,166, PATTERN_WHITE
|
||||||
; mov ax, word [fs:PTR_MOUSE + mouse.x]
|
GFX GOTOXY, 8, 150
|
||||||
; call scr_puthex16
|
|
||||||
;
|
mov ax, .value
|
||||||
; mov al, ' '
|
call print_word_hex
|
||||||
; call scr_putc
|
; end debug
|
||||||
;
|
|
||||||
; mov ax, word [fs:PTR_MOUSE + mouse.y]
|
; change palette...
|
||||||
; call scr_puthex16
|
;and ax, 0x00FF
|
||||||
|
;mov bh, 0x00
|
||||||
|
;mov bl, al
|
||||||
|
;mov ah, 0x0b
|
||||||
|
;mov al, 0x00
|
||||||
|
;int 0x10
|
||||||
|
|
||||||
|
mov dx, CRTC_COLOR_DATA
|
||||||
|
and ax, 0x001F
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
nop
|
|
||||||
jmp .loop
|
jmp .loop
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
|
||||||
|
|
@ -72,10 +72,11 @@ endstruc
|
||||||
struc gfx
|
struc gfx
|
||||||
.cur_x resw 1 ; x,y en pixel
|
.cur_x resw 1 ; x,y en pixel
|
||||||
.cur_y resw 1
|
.cur_y resw 1
|
||||||
|
.cur_mode resw 1 ; mode text
|
||||||
.cur_offset resw 1 ; offset calculé pour le prochain caractère
|
.cur_offset resw 1 ; offset calculé pour le prochain caractère
|
||||||
.cur_line_ofs resw 1 ; "interligne" +2000h ou -2000h
|
.cur_line_ofs resw 1 ; "interligne" +2000h ou -2000h
|
||||||
.cur_shift resb 1 ; x&7 (0..7)
|
.cur_shift resb 1 ; x&7 (0..7)
|
||||||
.cur_mode resb 1 ;
|
|
||||||
endstruc
|
endstruc
|
||||||
|
|
||||||
; -----------------------------------------------------------------------------------
|
; -----------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -32,14 +32,18 @@
|
||||||
;
|
;
|
||||||
; bit : descr
|
; bit : descr
|
||||||
; 0..3 : text color : 0=black .. 15=white
|
; 0..3 : text color : 0=black .. 15=white
|
||||||
; 4 : transparent : 1=apply background attribut
|
; 4..7 : background color
|
||||||
; 5..7 : free
|
; 8..D : unused
|
||||||
; 8..F : background color (si bit 4 = 1)
|
; E : text transparent
|
||||||
|
; F : background transparent
|
||||||
;
|
;
|
||||||
%define GFX_TXT_WHITE_TRANSPARENT 000001111b
|
%define GFX_TXT_WHITE_TRANSPARENT 0x0F
|
||||||
%define GFX_TXT_BLACK_TRANSPARENT 000000000b
|
%define GFX_TXT_BLACK_TRANSPARENT 0x00
|
||||||
%define GFX_TXT_WHITE 111110000b
|
%define GFX_TXT_WHITE 0xF0
|
||||||
%define GFX_TXT_BLACK 100001111b
|
%define GFX_TXT_BLACK 0x0F
|
||||||
|
|
||||||
|
%define GFX_TXT_TRANSPARENT_BKG 0x8000
|
||||||
|
%define GFX_TXT_TRANSPARENT_TEXT 0x4000
|
||||||
|
|
||||||
%macro GFX 1-*
|
%macro GFX 1-*
|
||||||
; %1 est l'index de la fonction
|
; %1 est l'index de la fonction
|
||||||
|
|
@ -97,10 +101,10 @@ graph_driver:
|
||||||
dw vga_set_writemode ; mode texte
|
dw vga_set_writemode ; mode texte
|
||||||
dw vga_putc ; dessin d'un caractère
|
dw vga_putc ; dessin d'un caractère
|
||||||
dw vga_write ; dessin d'une chaine de caractère
|
dw vga_write ; dessin d'une chaine de caractère
|
||||||
dw vga_none ; dessin d'une ligne (Bresenham) avec décision horizontale/verticale
|
dw vga_line ; dessin d'une ligne (Bresenham) avec décision horizontale/verticale
|
||||||
dw vga_none ; dessin d'un rectangle
|
dw vga_draw_rect ; dessin d'un rectangle
|
||||||
dw vga_none ; dessin d'un rectangle plein
|
dw vga_none ; dessin d'un rectangle plein
|
||||||
dw vga_none ; dessin d'un rectangle arrondi
|
dw vga_draw_rounded_frame ; dessin d'un rectangle arrondi
|
||||||
dw vga_mouse_hide ; cache la souris
|
dw vga_mouse_hide ; cache la souris
|
||||||
dw vga_mouse_show ; montre la souris
|
dw vga_mouse_show ; montre la souris
|
||||||
dw vga_mouse_cursor_move ; déplacement du curseur
|
dw vga_mouse_cursor_move ; déplacement du curseur
|
||||||
|
|
@ -323,7 +327,7 @@ vga_set_charpos:
|
||||||
%undef .y
|
%undef .y
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; cga_putc_unalign (car)
|
; vga_putc_unalign (car)
|
||||||
; - x non aligné (x&7 != 0)
|
; - x non aligné (x&7 != 0)
|
||||||
; - écrit sur 2 bytes (di et di+1) dans chaque banque
|
; - écrit sur 2 bytes (di et di+1) dans chaque banque
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
|
|
@ -333,113 +337,138 @@ vga_set_charpos:
|
||||||
vga_putc:
|
vga_putc:
|
||||||
push bp
|
push bp
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
; --- Définition des variables locales ---
|
sub sp, 4 ; .cpt [bp-2], .glyph_row [bp-4]
|
||||||
%define .cpt word [bp-2]
|
%define .cpt word [bp-2]
|
||||||
sub sp, 2 ; 1 word variable locale
|
%define .glyph_row word [bp-4]
|
||||||
|
|
||||||
pusha
|
pusha
|
||||||
|
push gs ; VRAM segment
|
||||||
push fs
|
push fs
|
||||||
push es
|
push es
|
||||||
|
|
||||||
call vga_mouse_hide ; Protection souris
|
call vga_mouse_hide ; Protection souris
|
||||||
|
|
||||||
|
; --- CONFIGURATION VGA ---
|
||||||
mov dx, EGAVGA_CONTROLLER
|
mov dx, EGAVGA_CONTROLLER
|
||||||
; Forcer le mode de remplacement (écrase la VRAM avec la donnée CPU)
|
mov ax, 0x0205 ; Mode 2
|
||||||
mov ax, 0x0205 ; Index 5 (Mode) : Mode 2
|
out dx, ax
|
||||||
|
mov ax, 0x0003 ; Function REPLACE
|
||||||
|
out dx, ax
|
||||||
|
mov dx, VGA_SEQUENCER
|
||||||
|
mov ax, 0x0F02 ; Tous les plans
|
||||||
out dx, ax
|
out dx, ax
|
||||||
|
|
||||||
; Opération logique : REPLACE (0)
|
mov ax, SEG_VIDEO
|
||||||
; (On pourrait mettre 0x1003 pour faire du OR matériel si besoin)
|
mov gs, ax
|
||||||
mov ax, 0x0003 ; Index 3 (Data Rotate) = REPLACE
|
mov ax, SEG_BDA_CUSTOM
|
||||||
out dx, ax
|
mov fs, ax
|
||||||
|
push cs
|
||||||
; Configuration VGA : Activer l'écriture sur les 4 plans pour le texte
|
pop ds
|
||||||
mov dx, VGA_SEQUENCER ; Sequencer
|
|
||||||
mov ax, 0x0F02 ; Index 2 (Map Mask) = 0x0F (tous les plans)
|
|
||||||
out dx, ax
|
|
||||||
|
|
||||||
mov bx, SEG_VIDEO
|
|
||||||
mov es, bx
|
|
||||||
mov bx, SEG_BDA_CUSTOM
|
|
||||||
mov fs, bx
|
|
||||||
|
|
||||||
mov ax, .car
|
mov ax, .car
|
||||||
call get_glyph_offset
|
call get_glyph_offset ; cs:si = offset font
|
||||||
|
|
||||||
; Base offset VRAM pour la scanline Y
|
|
||||||
mov di, [fs:PTR_GFX + gfx.cur_offset]
|
mov di, [fs:PTR_GFX + gfx.cur_offset]
|
||||||
mov cl, [fs:PTR_GFX + gfx.cur_shift]
|
mov cl, [fs:PTR_GFX + gfx.cur_shift]
|
||||||
mov ch, [fs:PTR_GFX + gfx.cur_mode]
|
|
||||||
mov bx, GFX_OFFSET
|
|
||||||
|
|
||||||
; On définit la couleur de texte (Ici simplifiée : bit 0 du mode)
|
; --- RÉCUPÉRATION DES COULEURS ---
|
||||||
; Si bit 0 = 1, on écrit en couleur 15 (blanc), sinon couleur 0 (noir)
|
mov ax, [fs:PTR_GFX + gfx.cur_mode]
|
||||||
mov ax,
|
mov bl, al ; BL = Couleur texte (low nibble)
|
||||||
test bl, 00000001b
|
and bl, 0x0F
|
||||||
jz .color_ok
|
mov bh, al ; BH = Couleur fond (high nibble)
|
||||||
mov bh, 0x0F ; Couleur Blanche (tous les plans à 1)
|
shr bh, 4
|
||||||
.color_ok:
|
|
||||||
|
|
||||||
mov .cpt, 8
|
mov .cpt, 8
|
||||||
mov dx, EGAVGA_CONTROLLER
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
|
||||||
.row_loop:
|
.row_loop:
|
||||||
lodsb ; AL = octet du glyphe
|
lodsb ; AL = octet glyphe
|
||||||
|
xor ah, ah
|
||||||
|
mov .glyph_row, ax ; Image 16 bits du glyphe non décalé
|
||||||
|
|
||||||
; Gestion du décalage horizontal (X non aligné sur 8)
|
; --- PASSE 1 : DESSIN DU FOND (SI OPAQUE) ---
|
||||||
xor ah, ah ; AX = 00:Glyphe
|
mov ax, [fs:PTR_GFX + gfx.cur_mode]
|
||||||
shr ax, cl ; AH:AL = Glyphe décalé sur 16 bits
|
test ax, GFX_TXT_TRANSPARENT_BKG
|
||||||
|
jnz .skip_bkg
|
||||||
|
|
||||||
; --- DESSIN DE L'OCTET 1 (DI) ---
|
mov ax, .glyph_row
|
||||||
push ax
|
not al ; Inverser le glyphe pour le fond
|
||||||
mov ah, al ; AH = partie du glyphe pour cet octet
|
ror ax, cl ; Aligner le fond sur les octets VRAM
|
||||||
mov al, 0x08 ; Index 8 : Bit Mask
|
|
||||||
out dx, ax ; On définit quels pixels seront modifiés
|
|
||||||
|
|
||||||
mov al, [es:di] ; LATCH LOAD : Aspire les 4 plans dans le GPU
|
; Octet 1 (DI)
|
||||||
mov [es:di], bh ; WRITE : Applique la couleur BH à travers le masque
|
push ax ; Sauver masque décalé (AH:AL)
|
||||||
|
mov ah, al ; Masque pour octet 1
|
||||||
|
mov al, 0x08 ; Bit Mask register
|
||||||
|
out dx, ax
|
||||||
|
mov al, [gs:di] ; LATCH LOAD (Charger le fond actuel)
|
||||||
|
mov [gs:di], bh ; WRITE Fond (BH)
|
||||||
pop ax
|
pop ax
|
||||||
|
|
||||||
; --- DESSIN DE L'OCTET 2 (DI+1) ---
|
; Octet 2 (DI+1)
|
||||||
test cl, cl ; Y a-t-il un décalage ?
|
test cl, cl
|
||||||
jz .next_line ; Non, on saute l'octet suivant
|
jz .skip_bkg
|
||||||
|
; AH contient déjà le masque pour l'octet 2
|
||||||
mov al, 0x08
|
mov al, 0x08
|
||||||
; AH contient déjà le reste du glyphe décalé
|
out dx, ax
|
||||||
out dx, ax ; Nouveau Bit Mask pour l'octet adjacent
|
mov al, [gs:di+1] ; LATCH LOAD Octet suivant
|
||||||
|
mov [gs:di+1], bh ; WRITE Fond (BH)
|
||||||
|
.skip_bkg:
|
||||||
|
|
||||||
mov al, [es:di+1] ; LATCH LOAD
|
; --- PASSE 2 : DESSIN DU TEXTE ---
|
||||||
mov [es:di+1], bh ; WRITE
|
mov ax, [fs:PTR_GFX + gfx.cur_mode]
|
||||||
|
test ax, GFX_TXT_TRANSPARENT_TEXT
|
||||||
|
jnz .next_line
|
||||||
|
|
||||||
|
mov ax, .glyph_row
|
||||||
|
ror ax, cl ; Aligner le texte sur les octets VRAM
|
||||||
|
|
||||||
|
; Octet 1 (DI)
|
||||||
|
push ax
|
||||||
|
mov ah, al
|
||||||
|
mov al, 0x08
|
||||||
|
out dx, ax
|
||||||
|
mov al, [gs:di] ; LATCH LOAD
|
||||||
|
mov [gs:di], bl ; WRITE Texte (BL)
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
; Octet 2 (DI+1)
|
||||||
|
test cl, cl
|
||||||
|
jz .next_line
|
||||||
|
mov al, 0x08
|
||||||
|
; AH contient le glyphe décalé pour l'octet 2
|
||||||
|
out dx, ax
|
||||||
|
mov al, [gs:di+1] ; LATCH LOAD
|
||||||
|
mov [gs:di+1], bl
|
||||||
|
|
||||||
.next_line:
|
.next_line:
|
||||||
add di, 80 ; Ligne suivante (640 pixels = 80 octets)
|
add di, 80 ; Ligne suivante
|
||||||
dec .cpt
|
dec .cpt
|
||||||
jnz .row_loop
|
jnz .row_loop
|
||||||
|
|
||||||
; --- NETTOYAGE (TRÈS IMPORTANT pour la souris) ---
|
; --- NETTOYAGE ---
|
||||||
mov dx, 0x3CE
|
mov dx, EGAVGA_CONTROLLER
|
||||||
mov ax, 0x0005 ; Revenir en Write Mode 0
|
mov ax, 0x0005 ; Write Mode 0
|
||||||
out dx, ax
|
out dx, ax
|
||||||
mov ax, 0xFF08 ; Bit Mask par défaut
|
mov ax, 0xFF08 ; Bit Mask = FF
|
||||||
out dx, ax
|
out dx, ax
|
||||||
|
|
||||||
; Avancer le curseur
|
; Mise à jour position
|
||||||
add word [fs:PTR_GFX + gfx.cur_x], 8
|
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 cx, [fs:PTR_GFX + gfx.cur_x]
|
||||||
mov dx, [fs:PTR_GFX + gfx.cur_y]
|
mov dx, [fs:PTR_GFX + gfx.cur_y]
|
||||||
call vga_calc_addr
|
call vga_calc_addr
|
||||||
mov [fs:PTR_GFX + gfx.cur_offset], di
|
mov [fs:PTR_GFX + gfx.cur_offset], di
|
||||||
; Note: calc_addr doit mettre le résultat dans DI ou BX selon ton usage
|
|
||||||
|
|
||||||
call vga_mouse_show
|
call vga_mouse_show
|
||||||
pop es
|
pop es
|
||||||
pop fs
|
pop fs
|
||||||
|
pop gs
|
||||||
popa
|
popa
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
%undef .car
|
; clean defs
|
||||||
%undef .cpt
|
%undef .cpt
|
||||||
|
%undef .glyph_row
|
||||||
|
|
||||||
;
|
;
|
||||||
; write string from [DS:SI] to screen
|
; write string from [DS:SI] to screen
|
||||||
|
|
@ -475,6 +504,486 @@ vga_write:
|
||||||
%undef .txt_seg
|
%undef .txt_seg
|
||||||
%undef .txt_ofs
|
%undef .txt_ofs
|
||||||
|
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
; vga_line (x1, y1, x2, y2, color)
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
%define .x1 word [bp+4]
|
||||||
|
%define .y1 word [bp+6]
|
||||||
|
%define .x2 word [bp+8]
|
||||||
|
%define .y2 word [bp+10]
|
||||||
|
%define .color byte [bp+12]
|
||||||
|
|
||||||
|
vga_line:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
pusha
|
||||||
|
|
||||||
|
call vga_mouse_hide
|
||||||
|
|
||||||
|
mov ax, .x1
|
||||||
|
mov bx, .x2
|
||||||
|
mov cx, .y1
|
||||||
|
mov dx, .y2
|
||||||
|
|
||||||
|
; Cas 1 : Ligne Verticale (x1 == x2)
|
||||||
|
cmp ax, bx
|
||||||
|
je .call_vertical
|
||||||
|
|
||||||
|
; Cas 2 : Ligne Horizontale (y1 == y2)
|
||||||
|
cmp cx, dx
|
||||||
|
je .call_horizontal
|
||||||
|
; Cas 3 : Ligne diagonale quelconque (Bresenham)
|
||||||
|
.bresenham:
|
||||||
|
; ... Algorithme classique utilisant vga_putpixel ...
|
||||||
|
|
||||||
|
.call_vertical:
|
||||||
|
push word .color
|
||||||
|
push dx ; y2
|
||||||
|
push cx ; y1
|
||||||
|
push ax ; x1
|
||||||
|
call vga_line_vertical
|
||||||
|
add sp, 8
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.call_horizontal:
|
||||||
|
push word .color
|
||||||
|
push bx ; x2
|
||||||
|
push ax ; x1
|
||||||
|
push cx ; y1
|
||||||
|
; call vga_line_horizontal
|
||||||
|
add sp, 8
|
||||||
|
; jmp .done
|
||||||
|
|
||||||
|
.done:
|
||||||
|
call vga_mouse_show
|
||||||
|
popa
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
; clean defs
|
||||||
|
%undef .x1
|
||||||
|
%undef .y1
|
||||||
|
%undef .x2
|
||||||
|
%undef .y2
|
||||||
|
%undef .color
|
||||||
|
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
; vga_line_bresenham (x1, y1, x2, y2, color)
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
%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]
|
||||||
|
vga_line_bresenham:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
sub sp, 12 ; Variables locales : dx, dy, sx, sy, err, e2
|
||||||
|
%define _dx word [bp-2]
|
||||||
|
%define _dy word [bp-4]
|
||||||
|
%define _sx word [bp-6]
|
||||||
|
%define _sy word [bp-8]
|
||||||
|
%define _err word [bp-10]
|
||||||
|
%define _e2 word [bp-12]
|
||||||
|
|
||||||
|
pusha
|
||||||
|
push es
|
||||||
|
|
||||||
|
; --- Calculs préliminaires Bresenham ---
|
||||||
|
; dx = abs(x2-x1), sx = x1<x2 ? 1 : -1
|
||||||
|
mov ax, .x2
|
||||||
|
sub ax, .x1
|
||||||
|
mov _sx, 1
|
||||||
|
jns .dx_ok
|
||||||
|
neg ax
|
||||||
|
mov _sx, -1
|
||||||
|
.dx_ok:
|
||||||
|
mov _dx, ax
|
||||||
|
|
||||||
|
; dy = -abs(y2-y1), sy = y1<y2 ? 1 : -1
|
||||||
|
mov ax, .y2
|
||||||
|
sub ax, .y1
|
||||||
|
mov _sy, 1
|
||||||
|
jns .dy_ok
|
||||||
|
neg ax
|
||||||
|
mov _sy, -1
|
||||||
|
.dy_ok:
|
||||||
|
neg ax ; dy doit être négatif
|
||||||
|
mov _dy, ax
|
||||||
|
|
||||||
|
; err = dx + dy
|
||||||
|
mov ax, _dx
|
||||||
|
add ax, _dy
|
||||||
|
mov _err, ax
|
||||||
|
|
||||||
|
; --- CONFIGURATION VGA MODE 2 ---
|
||||||
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
mov ax, 0x0205 ; Write Mode 2
|
||||||
|
out dx, ax
|
||||||
|
mov ax, 0x0003 ; Function Replace
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
mov ax, SEG_VIDEO
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
mov cx, .x1 ; Courant X
|
||||||
|
mov dx, .y1 ; Courant Y
|
||||||
|
|
||||||
|
.plot_loop:
|
||||||
|
; Calculer l'adresse et le Bit Mask pour le pixel courant
|
||||||
|
push dx
|
||||||
|
push cx
|
||||||
|
call vga_calc_addr ; DI = offset VRAM, CL = bit shift (0-7)
|
||||||
|
|
||||||
|
; Configurer le Bit Mask (Index 8)
|
||||||
|
mov ah, 0x80
|
||||||
|
shr ah, cl ; AH = Masque du pixel
|
||||||
|
mov al, 0x08
|
||||||
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
; Écriture Mode 2 (Latches + Couleur)
|
||||||
|
mov al, [es:di] ; LOAD LATCHES
|
||||||
|
mov ax, .color
|
||||||
|
mov [es:di], al ; WRITE Couleur (VGA Mode 2 utilise AL comme couleur)
|
||||||
|
|
||||||
|
pop cx
|
||||||
|
pop dx
|
||||||
|
|
||||||
|
; Vérifier si on a atteint la destination
|
||||||
|
cmp cx, .x2
|
||||||
|
jne .continue
|
||||||
|
cmp dx, .y2
|
||||||
|
je .exit_loop
|
||||||
|
|
||||||
|
.continue:
|
||||||
|
; e2 = 2 * err
|
||||||
|
mov ax, _err
|
||||||
|
shl ax, 1
|
||||||
|
mov _e2, ax
|
||||||
|
|
||||||
|
; if e2 >= dy: err += dy; x1 += sx
|
||||||
|
mov bx, _dy
|
||||||
|
cmp ax, bx
|
||||||
|
jl .skip_x
|
||||||
|
add _err, bx
|
||||||
|
add cx, _sx
|
||||||
|
.skip_x:
|
||||||
|
|
||||||
|
; if e2 <= dx: err += dx; y1 += sy
|
||||||
|
mov bx, _dx
|
||||||
|
cmp _e2, bx
|
||||||
|
jg .plot_loop
|
||||||
|
add _err, bx
|
||||||
|
add dx, _sy
|
||||||
|
jmp .plot_loop
|
||||||
|
|
||||||
|
.exit_loop:
|
||||||
|
; --- NETTOYAGE VGA ---
|
||||||
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
mov ax, 0x0005 ; Reset Mode 0
|
||||||
|
out dx, ax
|
||||||
|
mov ax, 0xFF08 ; Reset Bit Mask
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
pop es
|
||||||
|
popa
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
; clean defs
|
||||||
|
%undef .x1
|
||||||
|
%undef .y1
|
||||||
|
%undef .x2
|
||||||
|
%undef .y2
|
||||||
|
%undef .color
|
||||||
|
|
||||||
|
; vga_line_horizontal (y, x1, x2, color)
|
||||||
|
%define .y word [bp+4]
|
||||||
|
%define .x1 word [bp+6]
|
||||||
|
%define .x2 word [bp+8]
|
||||||
|
%define .color word [bp+10]
|
||||||
|
|
||||||
|
vga_line_horizontal:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
pusha
|
||||||
|
push es
|
||||||
|
|
||||||
|
; Trier x1 et x2
|
||||||
|
mov ax, .x1
|
||||||
|
mov bx, .x2
|
||||||
|
cmp ax, bx
|
||||||
|
jbe .skip_swap
|
||||||
|
xchg ax, bx
|
||||||
|
.skip_swap:
|
||||||
|
; AX = x-start, BX = x-end
|
||||||
|
|
||||||
|
; Configurer VGA Mode 0 avec Bit Mask
|
||||||
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
mov ax, 0x0005 ; Write Mode 0
|
||||||
|
out dx, ax
|
||||||
|
mov ax, 0x0003 ; Function Replace
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
; Activer Set/Reset pour la couleur
|
||||||
|
mov ax, 0x0F01 ; Enable Set/Reset
|
||||||
|
out dx, ax
|
||||||
|
mov al, 0x00 ; Index 0: Set/Reset Color
|
||||||
|
mov ah, byte .color
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
mov dx, .y
|
||||||
|
mov cx, ax ; CX = x1 pour calc_addr
|
||||||
|
call vga_calc_addr ; DI = offset, CL = shift (non utilisé ici)
|
||||||
|
|
||||||
|
mov ax, SEG_VIDEO
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
; Boucle simple pixel par pixel (optimisation octet par octet possible ici)
|
||||||
|
.pixel_loop:
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
; Utilisation du Bit Mask pour le pixel individuel (plus simple que le mode planaire manuel)
|
||||||
|
mov bx, cx
|
||||||
|
and bx, 7 ; x % 8
|
||||||
|
mov ah, 0x80
|
||||||
|
shr ah, cl ; Bit mask pour le pixel
|
||||||
|
mov al, 0x08 ; Index 8
|
||||||
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
mov al, [es:di] ; Load latches
|
||||||
|
mov [es:di], al ; Write (la couleur est dans Set/Reset)
|
||||||
|
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
|
||||||
|
inc cx
|
||||||
|
test cx, 7
|
||||||
|
jnz .no_inc_di
|
||||||
|
inc di
|
||||||
|
.no_inc_di:
|
||||||
|
cmp cx, bx
|
||||||
|
jbe .pixel_loop
|
||||||
|
|
||||||
|
; Nettoyage Set/Reset
|
||||||
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
mov ax, 0x0001
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
pop es
|
||||||
|
popa
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
; clean defs
|
||||||
|
%undef .y
|
||||||
|
%undef .x1
|
||||||
|
%undef .x2
|
||||||
|
%undef .color
|
||||||
|
|
||||||
|
; vga_line_vertical (x, y1, y2, color)
|
||||||
|
%define .x word [bp+4]
|
||||||
|
%define .y1 word [bp+6]
|
||||||
|
%define .y2 word [bp+8]
|
||||||
|
%define .color word [bp+10]
|
||||||
|
; vga_line_vertical (x, y1, y2, color)
|
||||||
|
vga_line_vertical:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
pusha
|
||||||
|
|
||||||
|
; --- Trier Y ---
|
||||||
|
mov ax, .y1
|
||||||
|
mov bx, .y2
|
||||||
|
cmp ax, bx
|
||||||
|
jbe .y_ok
|
||||||
|
xchg ax, bx
|
||||||
|
.y_ok:
|
||||||
|
; AX = Y-start, BX = Y-end
|
||||||
|
|
||||||
|
; --- Calculer le nombre de pixels (Hauteur) ---
|
||||||
|
mov cx, bx
|
||||||
|
sub cx, ax
|
||||||
|
inc cx ; CX = Nombre de lignes à tracer
|
||||||
|
|
||||||
|
; --- Calculer l'adresse initiale ---
|
||||||
|
push cx ; Sauver la hauteur
|
||||||
|
mov dx, ax ; DX = Y-start
|
||||||
|
mov cx, .x ; CX = X
|
||||||
|
call vga_calc_addr ; DI = offset VRAM, CL = bit shift
|
||||||
|
pop cx ; Restaurer la hauteur dans CX
|
||||||
|
|
||||||
|
; --- Configurer le GPU (Mode 2) ---
|
||||||
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
mov ax, 0x0205 ; Write Mode 2
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
mov ah, 0x80 ; Bit Mask : 1 pixel
|
||||||
|
shr ah, cl ; Aligner sur le X
|
||||||
|
mov al, 0x08 ; Index 8
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
mov ax, SEG_VIDEO
|
||||||
|
mov es, ax
|
||||||
|
mov al, byte .color ; AL = Couleur pour le Mode 2
|
||||||
|
|
||||||
|
.v_loop:
|
||||||
|
mov ah, [es:di] ; LATCH LOAD
|
||||||
|
mov [es:di], al ; WRITE COLOR
|
||||||
|
add di, 80 ; Scanline suivante
|
||||||
|
loop .v_loop ; Répéter CX fois
|
||||||
|
|
||||||
|
; --- Reset ---
|
||||||
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
mov ax, 0x0005 ; Mode 0
|
||||||
|
out dx, ax
|
||||||
|
mov ax, 0xFF08 ; Reset Mask
|
||||||
|
out dx, ax
|
||||||
|
|
||||||
|
popa
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
; clean defs
|
||||||
|
%undef .x
|
||||||
|
%undef .y1
|
||||||
|
%undef .y2
|
||||||
|
%undef .color
|
||||||
|
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
; vga_draw_rect
|
||||||
|
; Dessine un rectangle vide (contour)
|
||||||
|
; Entrée : x1, y1, x2, y2, color
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
; Arguments
|
||||||
|
%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] ; word pour l'alignement pile (mais on utilise byte)
|
||||||
|
vga_draw_rect:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
pusha
|
||||||
|
|
||||||
|
; 1. Ordonner X (x1 < x2)
|
||||||
|
mov ax, .x1
|
||||||
|
mov bx, .x2
|
||||||
|
cmp ax, bx
|
||||||
|
jle .x_ok
|
||||||
|
xchg ax, bx
|
||||||
|
mov .x1, ax
|
||||||
|
mov .x2, bx
|
||||||
|
.x_ok:
|
||||||
|
|
||||||
|
; 2. Ordonner Y (y1 < y2)
|
||||||
|
mov ax, .y1
|
||||||
|
mov bx, .y2
|
||||||
|
cmp ax, bx
|
||||||
|
jle .y_ok
|
||||||
|
xchg ax, bx
|
||||||
|
mov .y1, ax
|
||||||
|
mov .y2, bx
|
||||||
|
.y_ok:
|
||||||
|
|
||||||
|
call vga_mouse_hide
|
||||||
|
|
||||||
|
; 3. Dessiner les 4 lignes
|
||||||
|
; Pour éviter les pixels en double dans les coins, on peut ajuster légèrement,
|
||||||
|
; mais pour un driver simple, tracer les 4 lignes brutes est acceptable.
|
||||||
|
|
||||||
|
GFX LINE, .x1, .y1, .x2, .y1, .color
|
||||||
|
GFX LINE, .x1, .y2, .x2, .y2, .color
|
||||||
|
|
||||||
|
GFX LINE, .x1, .y1, .x1, .y2, .color
|
||||||
|
GFX LINE, .x2, .y1, .x2, .y2, .color
|
||||||
|
|
||||||
|
call vga_mouse_show
|
||||||
|
popa
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
; clean defs
|
||||||
|
%undef .x1
|
||||||
|
%undef .y1
|
||||||
|
%undef .x2
|
||||||
|
%undef .y2
|
||||||
|
%undef .color
|
||||||
|
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
; cga_draw_rounded_frame
|
||||||
|
; dessiner un cadre arrondi
|
||||||
|
; Entrée : AX=x1, BX=y1, CX=x2, DX=y2
|
||||||
|
; ------------------------------------------------------------
|
||||||
|
%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]
|
||||||
|
; Variable locale pour l'index du motif (y % 8)
|
||||||
|
%define .coord1 word [bp-2]
|
||||||
|
%define .coord2 word [bp-4]
|
||||||
|
vga_draw_rounded_frame:
|
||||||
|
push bp
|
||||||
|
mov bp, sp
|
||||||
|
sub sp, 4 ; Reserve espace pour .coord1 et .coord2
|
||||||
|
pusha
|
||||||
|
|
||||||
|
call vga_mouse_hide
|
||||||
|
|
||||||
|
; Lignes horizontales (raccourcies de 2px pour laisser place à l'arrondi)
|
||||||
|
mov ax, .x1
|
||||||
|
add ax, 2
|
||||||
|
mov .coord1, ax
|
||||||
|
mov bx, .x2
|
||||||
|
sub bx, 2
|
||||||
|
mov .coord2, bx
|
||||||
|
GFX LINE, .coord1, .y1, .coord2, .y1, .color
|
||||||
|
GFX LINE, .coord1, .y2, .coord2, .y2, .color
|
||||||
|
|
||||||
|
; Lignes verticales (raccourcies de 1px en haut et en bas)
|
||||||
|
mov cx, .y1
|
||||||
|
add cx, 2
|
||||||
|
mov .coord1, cx
|
||||||
|
mov dx, .y2
|
||||||
|
sub dx, 2
|
||||||
|
mov .coord2, dx
|
||||||
|
GFX LINE, .x1, .coord1, .x1, .coord2, .color
|
||||||
|
GFX LINE, .x2, .coord1, .x2, .coord2, .color
|
||||||
|
|
||||||
|
; Ajout des pixels de transition pour adoucir les coins (chanfrein)
|
||||||
|
mov ax, .x1
|
||||||
|
inc ax ; x1 + 1
|
||||||
|
mov bx, .y1
|
||||||
|
inc bx ; y1 + 1
|
||||||
|
GFX PUTPIXEL, ax, bx, .color ; Coin haut-gauche
|
||||||
|
|
||||||
|
mov ax, .x1
|
||||||
|
inc ax
|
||||||
|
mov bx, .y2
|
||||||
|
dec bx ; y2 - 1
|
||||||
|
GFX PUTPIXEL, ax, bx, .color ; Coin bas-gauche
|
||||||
|
|
||||||
|
mov ax, .x2
|
||||||
|
dec ax ; x2 - 1
|
||||||
|
mov bx, .y1
|
||||||
|
inc bx ; y1 + 1
|
||||||
|
GFX PUTPIXEL, ax, bx, .color ; Coin haut-droite
|
||||||
|
|
||||||
|
mov ax, .x2
|
||||||
|
dec ax
|
||||||
|
mov bx, .y2
|
||||||
|
dec bx ; y2 - 1
|
||||||
|
GFX PUTPIXEL, ax, bx, .color ; Coin bas-droite
|
||||||
|
|
||||||
|
call vga_mouse_show
|
||||||
|
|
||||||
|
popa
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
%undef .x1
|
||||||
|
%undef .y1
|
||||||
|
%undef .x2
|
||||||
|
%undef .y2
|
||||||
|
%undef .color
|
||||||
|
|
||||||
|
|
||||||
; Entrée: AX = X (0-639), BX = Y (0-479), CL = Couleur (0-15)
|
; Entrée: AX = X (0-639), BX = Y (0-479), CL = Couleur (0-15)
|
||||||
%define .x word [bp+4]
|
%define .x word [bp+4]
|
||||||
|
|
@ -484,52 +993,48 @@ vga_putpixel:
|
||||||
push bp
|
push bp
|
||||||
mov bp, sp
|
mov bp, sp
|
||||||
pusha
|
pusha
|
||||||
|
push es
|
||||||
|
|
||||||
mov bx, .y
|
; 1. Calcul de l'offset (Y * 80 + X / 8) sans IMUL
|
||||||
mov ax, .x
|
mov ax, .y
|
||||||
mov cl, .color
|
mov di, ax ; DI = Y
|
||||||
; Calcul de l'offset (Y * 80 + X/8)
|
shl di, 6 ; DI = Y * 64
|
||||||
|
shl ax, 4 ; AX = Y * 16
|
||||||
|
add di, ax ; DI = Y * 80
|
||||||
|
|
||||||
imul di, bx, 80 ; DI = Y * 80
|
mov cx, .x ; CX = X
|
||||||
mov bx, ax ; Sauvegarde X
|
mov bx, cx ; Sauvegarde X pour le masque
|
||||||
shr ax, 3 ; AX = X / 8
|
shr cx, 3 ; CX = X / 8
|
||||||
add di, ax ; DI = Offset final
|
add di, cx ; DI = Offset final
|
||||||
|
|
||||||
; Calcul du masque de bit (7 - (X % 8))
|
; 2. Configuration du contrôleur graphique (Mode d'écriture 2)
|
||||||
|
mov dx, EGAVGA_CONTROLLER
|
||||||
|
mov ax, 0205h ; Index 5 : Mode d'écriture 2
|
||||||
|
out dx, ax ; Ce mode permet d'envoyer la couleur via AL directement
|
||||||
|
|
||||||
|
; 3. Calcul du Bit Mask (7 - (X % 8))
|
||||||
and bx, 7 ; BX = X % 8
|
and bx, 7 ; BX = X % 8
|
||||||
mov ah, 80h ; Bit 7 à 1
|
mov ah, 80h ; Bit 7 à 1
|
||||||
shr ah, cl ; Décale pour pointer le bon pixel (cl = bx ici)
|
mov cl, bl ; Utilise le reste pour décaler
|
||||||
; Note: en pratique on utilise souvent une table de pré-calcul pour shr ah, bl
|
shr ah, cl ; AH = Masque du pixel
|
||||||
|
mov al, 08h ; Index 8 : Bit Mask
|
||||||
; Programmation du Graphics Controller
|
|
||||||
mov dx, EGAVGA_CONTROLLER
|
|
||||||
|
|
||||||
; Sélection du Bit Mask (Index 8)
|
|
||||||
mov al, 08h
|
|
||||||
out dx, ax ; AH contient le masque calculé
|
out dx, ax ; AH contient le masque calculé
|
||||||
|
|
||||||
; Sélection du Set/Reset (Couleur, Index 0)
|
; 4. Écriture du pixel
|
||||||
mov ax, 0000h
|
|
||||||
mov al, 00h
|
|
||||||
mov ah, cl ; Couleur
|
|
||||||
out dx, ax
|
|
||||||
|
|
||||||
; Enable Set/Reset (On active les 4 plans, Index 1)
|
|
||||||
mov ax, 0F01h
|
|
||||||
out dx, ax
|
|
||||||
|
|
||||||
; 4. Écriture (Nécessite une lecture préalable pour charger les Latches)
|
|
||||||
mov ax, SEG_VIDEO
|
mov ax, SEG_VIDEO
|
||||||
mov es, ax
|
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
|
|
||||||
|
|
||||||
; Reset des registres pour ne pas casser le reste du dessin
|
mov al, [es:di] ; LATCH LOAD : Indispensable pour préserver les autres plans
|
||||||
mov ax, 0FF08h
|
mov al, .color ; AL = Index de couleur (0-15)
|
||||||
|
mov [es:di], al ; WRITE : Le GPU applique AL là où le Bit Mask est à 1
|
||||||
|
|
||||||
|
; 5. Nettoyage minimal (Reset Mode 0)
|
||||||
|
mov ax, 0005h ; Index 5 : Mode d'écriture 0
|
||||||
out dx, ax
|
out dx, ax
|
||||||
mov ax, 0001h
|
mov ax, 0FF08h ; Index 8 : Reset Bit Mask
|
||||||
out dx, ax
|
out dx, ax
|
||||||
|
|
||||||
|
pop es
|
||||||
popa
|
popa
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue