VGA Trainer Pogram (13h) Část 2.

Zdroj: SOOM.cz [ISSN 1804-7270]
Autor: Kub@z
Datum: 18.8.2004
Hodnocení/Hlasovalo: 0/0

Jak se v pascalu pracuje s režimem 320x200, 256 barev

 

Tento dokument byl vypracován podle skvělého „VGA Trainer Program by Denthor of Asphyxia“ s cílem pomoci začínajícím programátorům (v jejich mateřském jazyce).

Prohlašuji, že nejsem žádný vynikající angličtinář a ani češtinář, proto prosím o shovívavost.

Následující text je „splácán“ z překladu originálu a mých drobných úprav.

 

Vítám vás tu opět! V této části probereme PALETU. Co k čertu paleta je? Jak zjistím co to je? Jak ji nastavím? Jak setmít obrazovku za použití palety? Jak roztmít obrazovku? Proč jsou telefonní hovory tak drahé? Většinu dotazů zodpovím v této druhé části školící série pro Pascal.

 

CO JE PALETA?

 

Před několika týdny hrál můj kamarád počítačovou hru. Ve hře byly stroje s pruhy modré, která přes ně probíhala. Když byl stroj aktivován, polovina modrých pruhů zůstala stejná, zatímco druhá začala měnit barvu a planout. Zeptal se mě, jak dva pruhy stejné barvy se mohou náhle takhle měnit. Odpověď je jednoduchá: program měnil paletu. Jak víte z první části, MCGA mód má 256 barev, číslované od 0 do 255. Co možná nevíte je, že každá z těchto barev se skládá z červené, zelené, modré (základní barvy) o různých intenzitách. Intenzita může být číslo od 0 do 63. Jasně červenou bychom například dostali nastavením intenzity červené na 63, zelené intenzity na 0 a modré intenzity na 0. To znamená, že dvě barvy mohou vypadat přesně stejně, např. můžete nastavit barvu 10 na světle červenou a barvu 78 na světle červenou. Když nakreslíte obrázek používající obě tyto barvy, nikdo nebude schopen rozeznat rozdíl mezi nimi. Pouze pokud změníte jejich palety, budou schopni rozeznat rozdíl. Také změnou celé palety dostanete efekt roztmívání a stmívání. Manipulace s paletou může být docela matoucí pro některé lidi, protože barvy, které vypadají stejně, jsou ve skutečnosti zcela oddělené.

 

JAK ČÍST V HODNOTÁCH PALETY BAREV?

 

To je velice jednoduché. Pro četní hodnoty palety, vložte číslo barvy, kterou chcete, do portu $3c7 a pak popořadě přečtete hodnoty červené, zelené a modré z portu $3c9. Jednoduché, hej? Zde je procedura, která to pro vás udělá:

 

Procedure GetPal (ColorNo : byte; var R,G,B : byte);

{ Přečte hodnoty červené, zelené a modré dané barvy a vrátí vám je.}

 

Begin

            Port [$3c7] := ColorNo;

            R := Port [$3c9];

            G := Port [$3c9];

            B := Port [$3c9];

End;

 

JAK NASTAVIT HODNOTU PALETY DANÉ BARVY?

 

To je jednoduché jako 3.1415926535897932385. Co uděláte je, že vložíte číslo barvy, kterou chcete změnit, do portu $3c8, pak popořadě vložíte hodnoty červené, zelené a modré do portu $3c9, protože jste tak líní, napsal jsem tu proceduru pro vás ;-))

 

Procedure Pal (ColorNo : byte; R,G,B : byte);

{ Nastaví hodnotu palety - červenou, zelenou a modrou – pro danou barvu. }

 

Begin

            Port [$3c8] := ColorNo

            Port [$3c9] := R;

            Port [$3c9] := G;

            Port [$3c9] := B;

End;

 

Asphyxia nepoužívá výše uvedené procedury pro paletu, ale používáme verzi pro assembler.

 

JAK ODSTRANIT VADY NA OBRAZE, KTERÉ SE OBJEVUJÍ KDYŽ MĚNÍM PALETU?

 

Pokud použijete paletu, zjistíte, že se na obrazovce objevuje docela hodně vad, když ji měníte. Způsob jak tomu čelit je následující: Vaši obrazovku neustále odshora dolů obnovuje elektronový paprsek Jakmile se dostane na spodek obrazovky, chvilku mu zabere než se vrátí zpět nahoru, aby znovu obnovil obrazovku. Fáze, kdy se vrací nahoru, se nazývá Verticle Retrace (vertikální návrat). Během vertikálního návratu můžete měnit paletu bez vlivu na to, co je na obrazovce. Děláme to, že čekáme dokud nezačal vertikální návrat tím, že zavoláme určitou proceduru; to znamená, že vše co nyní uděláme bude zobrazeno až po skončení vertikálního návratu, tak můžeme dělat všechny druhy divných a neobvyklých věcí na obrazovce během vertikálního návratu a pouze výsledek bude zobrazen potom co návrat skončí. To je skvělý způsob, znamená to, že když změníme paletu, neobjeví se žádné vady jen výsledek (změněná paleta). Elegantní, hej? ;-) Dal jsem čistě assemblerovskou rutinu WaitRetrace do ukázkového kódu. Užij s rozumem můj synu!

 

Pozn.:            WaitRetrace může být velkou pomocí pro vaše programování … kód, který se vejde do jednoho návratu, bude znamenat, že demo poběží stejnou rychlostí bez ohledu na rychlosti vašeho počítače (tedy pokud mnoho neděláte během WaitRetrace a počítač je pooomalý). Všimněte si, že v následujícím ukázkovém programu a v našem SilkyDemo, půjde vše stejně rychle ať je turbo zapnuto nebo vypnuto.

 

JAK ZAČERNIT OBRAZOVKU ZA POUŽITÍ PALETY?

 

Toto je základ: jen nastavit hodnoty červené, zelené a modré všech barev na nulovou intenzitu, stejně jako:

 

Procedure Blackout;

{ Tato procedura setmí obrazovku nastavením hodnot palety všech barev na nulu. }

Var      loop1: integer;

Begin

            WaitRetrace;

            For loop1:=0 to 255 do

                        Pal (loop1, 0,0,0);

End;

 

JAK ROZETMÍT OBRAZOVKU?

 

OK, toto může být velice efektní. První co musíte udělat je, grabnout paletu do proměnné, takto:

 

            Var Pall : array [0..255, 1..3] of byte;

 

0 až 255 je pro 256 barev v MCGA módu, 1 až 3 je hodnota intenzity červené, zelené a modré.

 

Procedure GrabPallete;

Var loop1:integer;

Begin

            For loop1:=0 to 255 do

                        GetPal (loop1, pall[loop1,1], pall[loop1,2], pall[loop1,3]);

End;

 

Tato procedura vloží celou paletu do proměnné pall. Pak musíte setmít obrazovku (viz výše) a nakreslit na obrazovku co chcete, bez možnosti vidět konstrukci na obrazovce. Pak už jen procházíte paletou. U každé barvy zjišťujete, zda-li jednotlivé intenzity jsou jak mají být. Jelikož intenzity jsou v rozmezí od 0 do 63, potřebujete to provést maximálně 64x.

 

Procedure FadeUp;

Var

            loop1,loop2:integer;

            tmp : array [1..3] of byte;   { To je pro dočasné uchování hodnot barvy}

Begin

            For loop1:=1 to 64 do

{ Hodnota pro červenou, zelenou a modrou složku barvy je 0 až 63, proto tento cyklus je třeba zavolat maximálně 64x}

Begin

                                    WaitRetrace;

                                    For loop2:=0 to 255 do

                                                Begin

                                                            Getpal (loop2, tmp[1], tmp[2], tmp[3]);

                                                            If tmp[1]<Pall[loop2,1] then inc (tmp[1]);

                                                            If tmp[2]<Pall[loop2,2] then inc (tmp[2]);

                                                            If tmp[3]<Pall[loop2,3] then inc (tmp[3]);

{ Pokud jsou hodnoty červené, zelené a modré dané barvy loop2 menší než by měly být, zvětší je o jednu}

Pal (loop2, tmp[1], tmp[2], tmp[3]);

                                                                        { Nastaví novou, upravenou paletu barvy}

End;

                        End;

End;

 

Hej-presto! Obrazovka se roztmívá. Můžete jen přidat DELAY před WaitRetrace, pokud se vám zdá, že je to moc rychlé. Skvělý, ne?

 

JAK SETMÍT OBRAZOVKU?

 

Je to skoro jako roztmívání obrazovky, jen opačným směrem. Jen kontrolujete každou intenzitu barvy. Když není nula, tak ji o jednu zmenšíte, dokud nebude. Primitivní!

 

Procedure FadeDown;

Var

            loop1,loop2:integer;

            tmp : array [1..3] of byte;   { To je pro dočasné uchování hodnot barvy}

Begin

            For loop1:=1 to 64 do

Begin

                                    WaitRetrace;

                                    For loop2:=0 to 255 do

                                                Begin

                                                            Getpal (loop2, tmp[1], tmp[2], tmp[3]);

                                                            If tmp[1]>0 then dec (tmp[1]);

                                                            If tmp[2]>0 then dec (tmp[2]);

                                                            If tmp[3]>0 then dec (tmp[3]);

{ Pokud ještě nejsou hodnoty červené, zelené a modré dané barvy loop2 nula, zmenší je o jednu}

Pal (loop2, tmp[1], tmp[2], tmp[3]);

                                                                        { Nastaví novou, upravenou paletu barvy}

End;

                        End;

End;

 

Opět, ke zpomalení výše uvedeného dejte  „DELAY“ před WaitRetrace. Stmívání obrazovky je působivější než jen vyčištění obrazovky, může velice vylepšit vaše demo atd. udržet lidi při sledování vašeho dema. K obnově palety udělejte jen toto:

 

Procedure RestorePallette;

Var      loop1 : integer;

Begin

            WaitRetrace;

            For loop1:=0 to 255 do

                        Pal (loop1, Pall[loop1,1], Pall[loop1,2], Pall[loop1,3])

End;

 

ZÁVĚREM

 

Dobře, většina z počátečních otázek je zodpovězena ;-) Následující ukázkový program je docela veliký, proto vám nejspíš chvilku zabere než si ho projdete. Manipulace s paletou byla mnoha programátorům trnem v oku po nějaký čas, nyní jsem snad ukázal, jak je to překvapivě jednoduché, když už jednou chápete základ.

 

Nashledanou příště!

            - Denthor