Unit Grafika;

Interface

{ Par rutinek pro praci v modu 320x200x256 barev
  Nazvy rutin jsou snad celkem samovysvetlujici, tak radsi par slov k tomuhle
  grafickemu modu:

  Tohle je na pouzivani nejjednodussi grafickej mod. Kazdej bod zabira prave
  1 bajt ve videopameti, ktera zacina na adrese $A000:0. Vsechny body jdou
  pekne po radkach za sebou, takze [Radek:0,Sloupec:0] je na $A000:0,
  [0,1] na $A000:1, [0,2] na $A000:2, [1,0] na $A000:320. Hodnota na dany
  adrese urcuje barvu bodu, resp. ukazatel do palety barev.

  Priklad: Chci znat bod [2,3]. Adresu si spocitam jako A=320*Y+X=320*2+3=643
           Bod se nachazi na adrese $A000:643. Tam je hodnota 1. Dejme tomu,
           ze chci vedet, jak presne je dana barva slozena. Tak se kouknu do
           palety na barvu c. 1. V palete je kazda barva reprezentovana tremi
           bajty pro intenzity jednotlivych slozek (cervena, zelena, modra)
           (z kazdyho je na VGA pouzitych jen 6 bitu). Pro barvu 1 mi default
           paleta vrati hodnoty cervena=0, zelena=0, modra=63, je to teda
           cista modra. Kdybych chtel misto toho treba zlutou, tak tam hodim
           hodnoty 63,63,0, protoze zluta je tvorena cervenou a zelenou ve
           stejnem pomeru. To by samozrejme zmenilo na obrazovce vsechny body
           barvou 1 z modrych na zlute.

  Neco o michani barev:

    Z ceho jsou slozeny zakladni barvy (ty, co je mas i v textovem rezimu),
    to zjistis snadno i v Pascalu. Modra je 1, Zelena 2 a Cervena 4. Kdyz chces
    z ceho je slozena treba azurova (cyan), kouknes na jeji hodnotu. Ta je 3.
    coz se rova 1+2, coz se rovna modra+zelena ve stejnem pomeru.

    Takze pokud bych pouzil barvu (0,63,63), bude to azurova, pokud bych pou-
    zil (0,31,31), bude to taky azurova, ale tmavsi, (31,63,63) bude svetlejsi
    azurova a treba (0,31,63) bude taky azurova, ale s mensim podilem zelene,
    takze do modra.

    Pokud chces odstiny sede (nebo cernou a bilou), tak vsechny slozky maji
    stejnou intenzitu, pricemz cim ta je vetsi, tim vic se barvy blizi bile

    Nejjednodussi asi je, aby sis to vyzkousel - dam ti na to programek, kterej
    ti zobrazi vsechny mozny barvy - pro jednoduchost v textovym rezimu, ale
    v grafice to funguje stejne

  Na zaver

    Samozrejme jsem si vedom, ze tohle nejsou zdaleka efektivni rutiny. To by
    bylo potreba prepsat do assembleru a nepouzivat rutiny BIOSu (krome tech
    pro inicializaci). Vsechno se k tomu da zjitit v nejakym tom Tech Helpu.

    Mimochodem, tenhle mod je zakladem vsech moznych "x-modu", ktere maji vetsi
    rozliseni a umoznuji napr. plynuly scrolling, prepinani stranek a dalsi
    veci vhodne pro animaci.                                                 }


Procedure Inicializace320x200x256;
Procedure Inicializace80x25Text;
Procedure NastavBod(X,Y:Word;Barva:Byte);
Function  BarvaBodu(X,Y:Word):Byte;
Procedure NastavPaletu(Barva,Cervena,Zelena,Modra:Byte);
Procedure PrectiPaletu(Barva:Byte; Var Cervena,Zelena,Modra:Byte);

Implementation

Function AdresaBodu(X,Y:Word):Word;
  Begin
  AdresaBodu := 320*Y+X;
  End;

Procedure Inicializace320x200x256; Assembler;
  Asm            { Pokud bys to chtel v "cistym" Pascalu, pouzij unitu Dos, }
    MOV AX,$13   { nadefinuj si R : Registers a napis                       }
    INT $10      {   R.AX := $13;                                           }
  End;           {   Intr($10,R);                                           }

Procedure Inicializace80x25Text; Assembler;
  Asm
    MOV AX,3
    INT $10
  End;

Procedure NastavBod;
  Begin
  Mem[$A000:AdresaBodu(X,Y)] := Barva;
  End;

Function BarvaBodu;
  Begin
  BarvaBodu := Mem[$A000:AdresaBodu(X,Y)];
  End;

Procedure NastavPaletu; Assembler;
  Asm
    MOV AX,$1010
    MOV BH,0
    MOV BL,Barva
    MOV DH,Cervena
    MOV CH,Zelena
    MOV CL,Modra
    INT $10
  End;

Procedure PrectiPaletu; Assembler;
  Asm
    PUSH DS         { Tohle by slo jednodusejc pres tu nuitu Dos             }
    MOV AX,$1015    {   R.AX := $1015;                                       }
    MOV BH,0        {   R.BH := 0;                                           }
    MOV BL,Barva    {   R.BL := Barva;                                       }
    INT $10         {   INTR($10,R);                                         }
    LDS SI,Cervena  {   Cervena := R.DH                                      }
    MOV [SI],DH     {   Zelena := R.DL                                       }
    LDS SI,Zelena   {   Modra := R.CL                                        }
    MOV [SI],CH
    LDS SI,Modra
    MOV [SI],CL
    POP DS
  End;

End.