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 cœur 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 manière 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 al,colorID ; choose color ID 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
A quoi cela peut il servir ?
Et bien à créer un dégradé sur la couleur de fond par exemple, et ce 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 "dos.h" #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); } }
Tutoriaux disponible