Le DAC
Le moniteur doit commander l'intensité des trois faisceaux d'électrons (rouge, vert, bleu) qui vont permettre l'affichage des différentes couleurs. Cette intensité est une valeur analogique qui n’est pas présente au coeur d’une carte VGA (qui traite les intensités de façon numérique).
Le DAC possède une palette qui, à un index de couleur (choisi parmi 256), associe les proportions des trois signaux de base rouge, vert et bleu. Ces proportions peuvent être modifiées par le programmeur pour chacune des 256 couleurs. Le DAC se charge alors de traduire les proportions associées à une couleur en signaux analogiques parfaitement compréhensibles par le moniteur.
La modification des valeurs de la table se fait de maniere assez simple en spécifiant l’index de couleur a modifié sur le port 0x3C8 (PEL Address), et en injectant 3 octets (un pour chaque intensité) sur le port 0x3C9 (DAC), le DAC se chargeant de placer les valeurs dans les registres ad-hoc.
mov dx,0x3c8 ; DAC PEL address
out dx,al
mov dx,0x3c9 ; DAC
mov al,db_Red
out dx,al ; write Red level for colorID
mov al,db_Green
out dx,al ; write Green level for colorID
mov al,db_Blue
out dx,al ; write Blue level for colorID
Raster
A quoi cela peut il servir ? A créer un dégradé sur la couleur de fond, dans n’importe quel mode « couleur » de la carte VGA ; meme en mode texte... ca peut servir par exemple pour "enrichir" un menu de configuration...
#include "conio.h"
typedef unsigned char BYTE;
typedef unsigned int WORD;
// copper_maxrow is a parameter to avoid copper/raster to turn forever
// copper_error must be set to 0 to run
int copper_maxrow = 400;
BYTE copper_error = 0;
// this constant define the raster precistion (for percentage calculation)
#define PRECIS 8
/*
Draw a raster with RGB(sr,sg,sb) -> RGB(dr,dg,db) in « count » lines
0 mean 0, 255 mean 100 %
*/
void DrawRaster(BYTE st_red, BYTE st_green, BYTE st_blue, BYTE dt_red, BYTE dt_green, BYTE dt_blue, WORD count )
{
int step_percent;
char step_red, step_green, step_blue;
// Since the VGA color range is only 6 bit, we divide by 4 the byte
st_red = st_red>>2;
st_green = st_green>>2;
st_blue = st_blue>>2;
dt_red = dt_red>>2;
dt_green = dt_green>>2;
dt_blue = dt_blue>>2;
asm {
xor ah,ah // calculate Red Stepping
mov al,dt_red // endcolor - startcolor
mov bl,st_red
sub al,bl
mov step_red,al // red delta = endredcolorlevel - startredcolorlevel
xor ah,ah
mov al,dt_green // calculate Green Stepping
mov bl,st_green
sub al,bl
mov step_green,al
xor ah,ah
mov al,dt_blue // calculate Blue Stepping
mov bl,st_blue
sub al,bl
mov step_blue,al
xor cx,cx // cx = 0 (current line = 0)
mov dx,0x3DA } // wait for stable know line count (0)
w1: asm {
in al,dx
test al,0x08
jne w1 }
w2: asm {
in al,dx
test al,0x08
je w2 }
start:asm {
cli // protection overscan : Current line > max
mov bl,0x05 // error 5 : overload
cmp cx,copper_maxrow // line counter over max ?
jae eocl
cmp cx,count // raster completed ?
jae clean_eocl
inc cx // current line ++
mov dx,0x3da } // read input state
in_retrace:asm {
in al,dx // test if we are redrawing
test al,1
jne in_retrace }
in_display:asm {
in al,dx
test al,1 // wait for hbl (horizontal return)
je in_display } // new line
set_color: asm {
xor dx,dx
mov ax,cx
shl ax,PRECIS
mov bx,count
div bx
mov bx,ax // BX = percent
xor al,al // set color 0 (background)
mov dx,0x3c8
out dx,al
inc dx // mov dx,0x3c9 optimisation
xor ax,ax
mov al,step_red // get RED level
mul bl
shr ax,PRECIS // reduce precision
add al,st_red
out dx,al // set RED to dac
xor ax,ax
mov al,step_green // get GREEN level
mul bl
shr ax,PRECIS
add al,st_green
out dx,al // set GREEN to dac
xor ax,ax
mov al,step_blue // get BLUE level
mul bl
shr ax,PRECIS
add al,st_blue
out dx,al // set BLUE to dac
jmp start } // get next operand
clean_eocl: asm {
xor bl,bl // clear error operand
}
eocl:asm {
xor al,al // normally we should restore whole DAC's status
mov dx,0x3c8 // but we only reset color 0 to black
out dx,al
inc dx
out dx,al // turn to RGB 0,0,0
out dx,al
out dx,al
sti
mov copper_error, bl } // set error (if any)
}
void main()
{
unsigned char running=1;
textmode(3);
clrscr();
while (running)
{
running=(copper_error?0:1);
if (kbhit())
{
running=0;
}
// do some stuffs
printf("T h i s I s T h e T e s t");
DrawRaster(0x00, 0x00, 0x00,0xFF, 0x1F, 0xF0,200);
}
}
To be continued...