/* Demonstracni program k druhemu dilu kursu */

      #include <dos.h>      // outportb(), inportb()
      #include <conio.h>    // gotoxy(), textcolor(), textbackground()...
      #include <stdlib.h>   // random()


      #define READ_COL   0x3C7  // port pro vyber cteni barvy
      #define WRITE_COL  0x3C8  // port pro vyber zapisu barvy
      #define RGB_COL    0x3C9  // port pro cteni/zapis barevnych slozek

      // #define PLYNULE
      // Odkomentovanim predchozi radky bude program snizovat
      // jas barevnych slozek tak, aby dosly na nulu soucasne.

      typedef struct Color {
         unsigned char R;
         unsigned char G;
         unsigned char B;
      };                          // typ pro ulozeni RGB

      unsigned char R, G, B;

      void Readkey()
      // Ceka na stisk klavesy
      // nahrazuje stejnojmennou pascalskou proceduru.
      {
        while (!kbhit())                     // cekam na klavesu
         ;
        if (getch() == 0)                    // vyberu ji z bufferu
         getch();                            // pri rozsirenem kodu
      }

      void NactiPal(Color *Pole)
      // Ulozi paletu.
      {
        int Citac;

        outportb(READ_COL, 0);               // zacinam barvou cislo 0
        for (Citac = 0; Citac <= 255; Citac++)
         // tolik je barev v palete
        {
         Pole[Citac].R = inportb(RGB_COL);
         Pole[Citac].G = inportb(RGB_COL);
         Pole[Citac].B = inportb(RGB_COL);
        }
      }

      void ObnovPal(Color *Pole)
      // Obnovi paletu.
      {
        int Citac;

        outportb(WRITE_COL, 0);                // zacinam barvou cislo 0
        for(Citac = 0; Citac <= 255; Citac++)  // tolik je barev v palete
        {
         outportb(RGB_COL, Pole[Citac].R);
         outportb(RGB_COL, Pole[Citac].G);
         outportb(RGB_COL, Pole[Citac].B);
        }
      }

      void VezmiBarvu(unsigned char Barva)
      // Nacte zadanou barvu z palety.
      {
        outportb(READ_COL, Barva);
        R = inportb(RGB_COL);
        G = inportb(RGB_COL);
        B = inportb(RGB_COL);
      }

      void UlozBarvu(unsigned char Barva)
      // Ulozi RGB do zadane barvy palety.
      {
        outportb(WRITE_COL, Barva);
        outportb(RGB_COL, R);
        outportb(RGB_COL, G);
        outportb(RGB_COL, B);
      }

      void Smeti(void)
      // Zaplni obrazovku barevnymi pismeny.
      {
        int X, Y;

        for (X = 1; X <= 80; X++)   // 80 sloupcu
         for (Y = 1; Y <= 24; Y++)  // 24 radku, pri zapisu na 25. radek
                                    // by obrazovka poskocila nahoru
         {
            gotoxy(X, Y);
            textcolor(random(255));        // nahodna barva popredi
            textbackground(random(255));   // nahodna barva pozadi
            cprintf("@");
         }
      }

      void main(void)
      {
        int Citac, Barva;
        Color Zaloha[255];                   // ulozeni palety

        clrscr();
        Smeti();                // nasypu na obrazovku barevne zavinace
        NactiPal(Zaloha);      // nejdrive uchovam puvodni paletu
        for (Citac = 1; Citac <= 63; Citac++)   // RGB jsou 0 - 63
        {
         for (Barva = 0; Barva <= 255; Barva++)  // barev je 0 - 255
         {
            VezmiBarvu(Barva);               // nactu barvu

      #ifdef PLYNULE

            if (R > 1) R -= R / (64 - Citac);
            if (G > 1) G -= G / (64 - Citac);
            if (B > 1) B -= B / (64 - Citac);

      /* Nevim jestli je to zrovna ono, ale je to viditelne jine nez
      puvodni  verze.  Ono  to  totiz neni zas tak jednoduche, protoze tam
      dochazi  k  pomerne  znacnym  zaokrouhlovacim chybam pri prevodech z
      float na integer a zpet. */

      #else

            if (R > 1) R--;        // ztlumim vsechny jeji slozky
            if (G > 1) G--;
            if (B > 1) B--;

      #endif

            UlozBarvu(Barva);  // ulozim ji zpatky
         }
         delay(20);            // cely proces trosku zpomalim
        }
        Readkey();             // obrazovka zhasnuta, cekam na klavesu
        ObnovPal(Zaloha); // obnovim puvodni paletu, aby bylo neco videt
      }


            výheň