Topic : The VGA Training Program
Author : Grant Smith
Page : << Previous 3  Next >>
Go to page :


in the
number of the color you want to change into port $3c8 [0x03C8], then enter the
values of red, green and blue respectively into port $3c9 [0x03C9]. Because
you are all so lazy I have written the procedure for you ;-)

[Pascal]

Procedure Pal(ColorNo : Byte; R,G,B : Byte);
  { This sets the Red, Green and Blue values of a certain color }
Begin
   Port[$3c8] := ColorNo;
   Port[$3c9] := R;
   Port[$3c9] := G;
   Port[$3c9] := B;
End;

[C++]

void Pal(unsigned char ColorNo, unsigned char R,
unsigned char G,       unsigned char B) {

  outp (0x03C8,ColorNo); // here is the pallette color I want to set
  outp (0x03C9,R);
  outp (0x03C9,G);
  outp (0x03C9,B);

}


Asphyxia doesn't use the above pallete procedures, we use assembler versions,
which will be given to PEOPLE WHO RESPOND TO THIS TRAINER SERIES (HINT,
HINT)




  How do I stop the "fuzz" that appears on my screen when I change the
        pallette?

If you have used the pallette before, you will have noticed that there is
quite a bit of "fuzz" on the screen when you change it. The way we counter
this is as follows : There is an elctron beam on your monitor that is
constantly updating your screen from top to bottom. As it gets to the
bottom of the screen, it takes a while for it to get back up to the top of
the screen to start updating the screen again.

The period where it moves from the bottom to the top is called the Verticle
Retrace. During the verticle retrace you may change the pallette without
affecting what is on the screen.

What we do is that we wait until a verticle retrace has started by calling a
certain procedure; this means that everything we do now will only be shown
after the verticle retrace, so we can do all sorts of strange and unusual
things to the screen during this retrace and only the results will be shown
when the retrace is finished. This is way cool, as it means that when we
change the pallette, the fuzz doesn't appear on the screen, only the result
(the changed pallette), is seen after the retrace! Neat, huh? ;-) I have put
the purely assembler WaitRetrace routine in the sample code that follows this
message. Use it wisely, my son.

NOTE : WaitRetrace can be a great help to your coding ... code that fits
       into one retrace will mean that the demo will run at the same
       speed no matter what your computer speed (unless you are doing a lot
       during the WaitRetrace and the computer is slooooow). Note that in
       the following sample program and in our SilkyDemo, the thing will run
       at the same speed whether turbo is on or off.




  How do I black out the screen using the pallette?

This is basic : just set the Red, Green and Blue values of all colors to
zero intensity, like so :

[Pascal]

Procedure Blackout;
  { This procedure blackens the screen by setting the pallette values of
    all the colors to zero. }
VAR loop1:integer;
BEGIN
  WaitRetrace;
  For loop1:=0 to 255 do
    Pal (loop1,0,0,0);
END;

[C++]

void Blackout() {

  WaitRetrace();
  for (int loop1=0;loop1<256;loop1++)
    Pal (loop1,0,0,0);

}



  How do I fade in a screen?

Okay, this can be VERY effective. What you must first do is grab the
pallette into a variable, like so :

   [Pascal]   VAR Pall := Array [0.255,1..3] of BYTE;
   [C++]      unsigned char Pall[256][3];


0 to 255 is for the 256 colors in MCGA mode, 1 to 3 is red, green and blue
intensity values;

[Pascal]

Procedure GrabPallette;
VAR loop1:integer;
BEGIN
  For loop1:=0 to 255 do
    Getpal (loop1,pall[loop1,1],pall[loop1,2],pall[loop1,3]);
END;

[C++]

void GrabPallette() {

  for(int loop1=0;loop1<256;loop1++)
    GetPal(loop1,Pall2[loop1][0],Pall2[loop1][1],Pall2[loop1][2]);

}


This loads the entire pallette into variable pall. Then you must blackout
the screen (see above), and draw what you want to screen without the
construction being shown. Then what you do is go throgh the pallette. For
each color, you see if the individual intensities are what they should be.
If not, you increase them by one unit until they are. Beacuse intensites
are in a range from 0 to 63, you only need do this a maximum of 64 times.

[Pascal]

Procedure Fadeup;
VAR loop1,loop2:integer;
    Tmp : Array [1..3] of byte;
      { This is temporary storage for the values of a color }
BEGIN
  For loop1:=1 to 64 do BEGIN
      { A color value for Red, green or blue is 0 to 63, so this loop only
        need be executed a maximum of 64 times }
    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]);
        { If the Red, Green or Blue values of color loop2 are less then they
          should be, increase them by one. }
      Pal (loop2,Tmp[1],Tmp[2],Tmp[3]);
        { Set the new, altered pallette color. }
    END;
  END;
END;

[C++]

void Fadeup() {

//This is temporary storage for the values of a color
unsigned char Tmp[3];

  // A color value for Red, green or blue is 0 to 63, so this loop only
  // need be executed a maximum of 64 times.
  for(int loop1=0;loop1<64;loop1++) {

    WaitRetrace();

    for(int loop2=0; loop2<256; loop2++) {
      GetPal(loop2,Tmp[0],Tmp[1],Tmp[2]);

      // If the Red, Green or Blue values of color loop2 are less then they
      // should be, increase them by one.
      if ((Tmp[0] < Pall2[loop2][0]) && (Tmp[0] < 63)) Tmp[0]++;
      if ((Tmp[1] < Pall2[loop2][1]) && (Tmp[1] < 63)) Tmp[1]++;
      if ((Tmp[2] < Pall2[loop2][2]) && (Tmp[2] < 63)) Tmp[2]++;

      // Set the new, altered pallette color.
      Pal (loop2,Tmp[0],Tmp[1],Tmp[2]);
    }
  }
}


Hey-presto! The screen fades up. You can just add in a delay before the
waitretrace if you feel it is too fast. Cool, no?

  How do I fade out a screen?

This is just like the fade in of a screen, just in the opposite direction.
What you do is you check each color intensity. If it is not yet zero, you
decrease it by one until it is. BAAASIIIC!

[Pascal]

Procedure FadeDown;
VAR loop1,loop2:integer;
    Tmp : Array [1..3] of byte;
      { This is temporary storage for the values of a color }
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]);
        { If the Red, Green or Blue values of color loop2 are not yet zero,
          then, decrease them by one. }
      Pal (loop2,Tmp[1],Tmp[2],Tmp[3]);
        { Set the new, altered pallette color. }
    END;
  END;
END;

[C++]

void FadeDown() {

// This is temporary storage for the values of a color
unsigned char Tmp[3];

  for(int loop1=0; loop1<64; loop1++) {

    WaitRetrace();

    for(int loop2=0; loop2<256; loop2++) {
      GetPal(loop2,Tmp[0],Tmp[1],Tmp[2]);

      // If the Red, Green or Blue values of color loop2 are not yet zero,
      // then, decrease them by one.
      if (Tmp[0] > 0) Tmp[0]--;
      if (Tmp[1] > 0) Tmp[1]--;
      if (Tmp[2] > 0) Tmp[2]--;

      // Set the new, altered pallette color.
      Pal(loop2,Tmp[0],Tmp[1],Tmp[2]);
    }
  }
}


Again, to slow the above down, put in a delay above the WaitRetrace. Fading
out the screen looks SO much more impressive then just clearing the screen;
it can make a world of difference in the impression your demo etc will
leave on the people viewing it. To restore the pallette, just do this :

[Pascal]

Procedure RestorePallette;
VAR loop1:integer;
BEGIN
  WaitRetrace;
  For loop1:=0 to 255 do


Page : << Previous 3  Next >>