---- na VGA ----
Jakákoliv barva se dá složit z poměrů tří základních barev:
červené (Red), zelené (Green) a modré (Blue) - ve zkratce RGB.
Bílá barva vznikne jestliže jsou všechny složky plně naplněny, černá
když všechny chybí, fialová stejným zastoupením červené a modré a
vynecháním zelené.... Takhle by se dalo pokračovat do nekonečna. Na
adaptéru VGA je každá složka 6-bitová - tzn. že může nabívat hodnot
od 0 do 63. Počet kombinací barev je tedy 64x64x64=262144 barev.
Pixel je ale jen 8-bitový, takže může být najednou zobrazeno
256 barev z 262144 možných kombinací (samozřejmě v některých módech
můžete zobrazit i víc barev). Teď pár pojmů a názvů:
CLUT (Color Look Up Table) - tabulka s 256 18-bitovými (na zpracování
každé barvy stačí 3*6 bitů=18) údaji
REGISTRY ČÍSLICOVĚ ANALOGOVÉHO PŘEVODNÍKU:
PEL Address (write mode) - R/W - port 3C8h - používá se k zápisu
pozice v CLUT (jaká barva se má nastavovat)
PEL Address (read mode) - WO - port 3C7h - používá se k zápisu
pozice v CLUT, když z ní chceme číst jednotlivé složky RGB (od jaké
barvy se bude číst)
DAC State - RO - port 3C7h - čtení pozice v PEL
PEL Data - R/W - port 3C9h - čtení/zápis jednotlivých složek -RGB
PEL Mask - R/W - port 3C6h - vnitřně maskuje všechny R, G a B -
zápisem 0 na tento port se dá rychle ztmavit obrazovka.
R/W - čtení i zápis
RO - jen čtení
WO - jen zápis
Po každém vstupu na port 3C9h se automaticky pozice v CLUT zvýší o
jedna. Jak nastavit jednu barvu z palety? Mohlo by to vypadat
takhle:
procedure setrgb(barva,r,g,b:byte); assembler;
asm
mov al,[barva] {al <- barva }
mov dx,3c8h {dx <- 3c8h }
out dx,al {port[3c8h] <- al}
inc dx {dx <- dx+1 }
mov al,[r] {al <- r }
out dx,al {port[3c9h] <- al}
mov al,[g] {al <- g }
out dx,al {port[3c9h] <- al}
mov al,[b] {al <- b }
out dx {port[3c9h] <- al}
end;
Ta je vhodná na nastavení jedné barvy, pokud nastavujete celou
paletu, nebo souvislý blok palety, dá se využít (zneužít)
automatického nastavování Dac write index registru - po 3. outu na
port 3C9h se obsah 3C8h zvýší o jedničku a můžete si vesele dál
zapisovat po sobě jdoucí složky RGBRGBRGB... anižbyste se před každou
barvou zdržovali se zápisem na 3C8h.
type paleta:array[1..768] of byte; {256*3}
var pal:paleta;
procedure setpal(pal:paleta);
var i:word;
begin
port[3c8]:=0;
for i:=1 to 768 do port[3c9]:=pal[i];
end;
begin
pal[1]:=63;
. {naplneni promene pal}
.
setpal(pal); {a nastaveni palety na pal}
...
end;
- Pokud programujete např. v Pascalu nemusíte používat assembler -
můžete rovnou psát na porty. Je dobré udělat si typ paleta se kterým
se potom dobře pracuje. Zjišťování aktuální paletky se dělá stejně,
jen s tím rozdílem že se k zápisu od jaké barvy se bude číst se
používá port 3C7h. - Tady je př.:
procedure getpal(var pal:paleta);
var i:word;
begin
port[3c7]:=0;
for i:=1 to 768 do pal[i]:=port[3c9];
end;
procedure getrgb(barva:byte; var r,g,b:byte);
begin
port[3c7]:=barva;
r:=port[3c9];
g:=port[3c9];
b:=port[3c9];
end;
• Fade-in
• Fade-out
• Fade-up
• Fade-to-pal
• Fade-to-gray
• Fade-from-gray
Fade je např. použit ve Výhni při "rozsvěcování" a "zhasínámí"
obrázků a textu - pomocí něho lze docílit např. plynulý přechod mezi
2 různými obrázky - první nejdříve plynule ztmavne do černa
a druhý se plynule rozsvítí - je to celkem efektní a hlavně příjemné
na oči. Není na tom nic těžkého, jde o to že se postupně snižuje
(zvyšuje) jas barev (u Fade-in a Fade-out). Tady máte procedůrky:
procedure fadein(pal:paleta); {zesvetleni z cerna do pal}
var i,j:word;
begin
port[3c8]:=0;
for j:=0 to 63 do
begin
retrace; {cekani na paprsek - viz poznamka}
for i:=1 to 768 do
port[3c9]:=pal[i]*j div 63; {nastavovani jasu kazde slozky}
end;
end;
procedure fadeout(pal:paleta); {ztmaveni z pal do cerna}
var i,j:word;
begin
port[3c8]:=0;
for j:=63 downto 0 do {tady je jediny rozdil - misto zesvetleni}
begin {se ztmavuje}
retrace;
for i:=1 to 768 do port[3c9]:=pal[i]*j div 63;
end;
end;
DŮLEŽITÁ POZNÁMKA: Paleta by se měla nastavovat v dobu kdy není žádná
informace posílána na DAC - jinak se na obrazovce objeví "sněžení"
před každým nastavováním palety se tedy musí počkat až paprsek dojede
dolu a vrací se - pak tento efekt nevzniká. Čekání na paprsek:
procedure retrace; assembler;
asm
mov dx,3dah {dx <- 3dah }
@1:in al,dx {al <- port[3dah] }
test al,8 {testuje bit 8 v al }
jz @1 {jestli je 0 tak skoc na @1}
@2:in al,dx {al <- port[3dah] }
test al,8 {tesuje bit 8 v al }
jnz @2 {jestli je 0 tak skoc na @2}
end;
Další problém je jestli se celá paleta stačí naplnit než se paprsek
vrátí. Na 8086 nikdy, na 286 málokdy, na 386 většinou ano a na 486 už
vždycky.
1/2
výheň