/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// TUTPROG2.CPP - VGA Trainer Program 2 (in Turbo C++ 3.0)                 //
//                                                                         //
// "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
// was limited to Pascal only in its first run.  All I have done is taken  //
// his original release, translated it to C++ and touched up a few things. //
// I take absolutely no credit for the concepts presented in this code and //
// am NOT the person to ask for help if you are having trouble.            //
//                                                                         //
// Program Notes : This program presents many new concepts, including:     //
//                 line drawing, pallette manipulation, and fading.        //
//                                                                         //
//                 If you are compiling this code command line, be sure to //
//                 use the "-ml" parameter (large memory model).           //
//                 Otherwise, the program will compile and link, but will  //
//                 lock up your system.                                    //
//                                                                         //
// Author        : Grant Smith (Denthor) - [email protected]    //
// Translator    : Christopher G. Mann   - [email protected]         //
//                                                                         //
// Last Modified : November 29, 1994                                       //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////


//               //
// INCLUDE FILES //
//               //

  #include <conio.h>
			  // getch(), clrscr()
  #include <dos.h>
			  // MK_FP, Geninterrupt()
  #include <math.h>
			  // floor(), ceil()
  #include <mem.h>
			  // memset(), movmem()
  #include <iostream.h>
			  // cout
  #include <stdlib.h>
			  // abs(), rand()


//                     //
// FUNCTION PROTOTYPES //
//                     //

  // MODE SETTING FUNCTIONS
  void SetMCGA();
  void SetText();

  // PALLETTE FUNCTIONS
  void GrabPallette();
  void GetPal (unsigned char ColorNo,  unsigned char &R,
	       unsigned char &G,       unsigned char &B);
  void Pal    (unsigned char ColorNo,  unsigned char R,
	       unsigned char G,        unsigned char B);
  void PalPlay  ();
  void Fadeup   ();
  void FadeDown ();
  void Blackout ();
  void RestorePallette();

  // SMALL UTILITY FUNCTIONS
  int  sgn  (long a);
  int  round(long a);

  // DRAWING FUNCTIONS
  void Putpixel (int x, int y, unsigned char Col);
  void Line(int a, int b, int c, int d, int col);
  void WaitRetrace();

  // MID-LEVEL (COMBINATION) FUNCTIONS
  void SetUpScreen();
  void HiddenScreenSetup();


//                              //
// GLOBAL VARIABLE DECLARATIONS //
//                              //

  // declare a pointer to the offset of VGA memory
  unsigned char *vga = (unsigned char *) MK_FP(0xA000, 0);

  // This declares the PALL variable. 0 to 255 signifies the colors of the
  // pallette, 1 to 3 signifies the Red, Green and Blue values. I am
  // going to use this as a sort of "virtual pallette", and alter it
  // as much as I want, then suddenly bang it to screen. Pall2 is used
  // to "remember" the origional pallette so that we can restore it at
  // the end of the program. */
  unsigned char Pall[256][3], Pall2[256][3];


///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//                                MAIN FUNCTION                              //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

void main() {

  clrscr();
  cout << "This program will draw lines of different colors across the\n"
       << "screen and change them only by changing their pallette values.\n"
       << "The nice thing about using the pallette is that one pallette\n"
       << "change changes the same color over the whole screen, without\n"
       << "you having to redraw it. Because I am using a WaitRetrace\n"
       << "command, turning on and off your turbo during the demonstration\n"
       << "should have no effect." << endl << endl;

  cout << "The second part of the demo blacks out the screen using the\n"
       << "pallette, fades in the screen, waits for a keypress, then fades\n"
       << "it out again. I haven''t put in any delays for the fadein/out,\n"
       << "so you will have to put them in yourself to get to the speed\n"
       << "you like. Have fun and enjoy! ;-)" << endl << endl << endl;
  cout << "Hit any key to continue ...";
  getch();

  SetMCGA();
  GrabPallette();
  SetUpScreen();

  while (!kbhit()) PalPlay();
    getch();  // once a key is pressed, be sure to clear the keyboard buffer

  Blackout();
  HiddenScreenSetup();
  Fadeup();
  getch();
  FadeDown();
  getch();

  RestorePallette();
  SetText();
  cout << "All done. This concludes the second sample program in the ASPHYXIA\n"
       << "Training series. You may reach DENTHOR under the name of GRANT\n"
       << "SMITH on the MailBox BBS, or leave a message to ASPHYXIA on the\n"
       << "ASPHYXIA BBS. Get the numbers from Roblist, or write to :\n"
       << "             Grant Smith\n"
       << "             P.O. Box 270\n"
       << "             Kloof\n"
       << "             3640\n"
       << "I hope to hear from you soon!" << endl << endl << endl;

  cout << "Hit any key to exit ...";
  getch();
}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// SetMCGA() - This function gets you into 320x200x256 mode.               //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void SetMCGA() {
  _AX = 0x0013;
  geninterrupt (0x10);
}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// SetText() - This function gets you into text mode.                      //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void SetText() {
  _AX = 0x0003;
  geninterrupt (0x10);
}


/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// GrabPallette() - This function retrieves the current pallette.          //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void GrabPallette() {

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

}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// GetPal() - This reads the values of the Red, Green, and Blue values of  //
//            a certain color.  This function uses pass-by-reference.      //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void GetPal(unsigned char ColorNo, unsigned char &R,
	    unsigned char &G,      unsigned char &B) {

  outp (0x03C7,ColorNo); // here is the pallette color I want read
  R = inp (0x03C9);
  G = inp (0x03C9);
  B = inp (0x03C9);

}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// Pal() - This sets the Red, Green, and Blue values of a certain color.   //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

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);

}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// PalPlay() - This function mucks about with our "virtual pallette", then //
//             shoves it to the screen.                                    //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void PalPlay() {

unsigned char Tmp[3];

  // This copies color 200 from our virtual pallette to the Tmp variable.
  _fmemmove(Tmp,Pall[200],3);

  // This moves the entire virtual pallette up one color.
  _fmemmove(Pall[2],Pall[1],199*3);

  // This copies the Tmp variable to the bottom of the virtual pallette.
  // Don't change 0: leave this always black to not change overscan color.
  _fmemmove(Pall[1],Tmp,3);

  WaitRetrace();
  for (int loop1=0;loop1<256;loop1++)
   Pal(loop1,Pall[loop1][0], Pall[loop1][1], Pall[loop1][2]);

}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// Fadeup() - This function slowly fades up the new screen                 //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

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]);
    }
  }
}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// FadeDown() - This function fades the screen out to black.               //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

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]);
    }
  }
}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// Blackout() - This function just clears the screen.                      //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void Blackout() {

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

}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// RestorePallette() - This function restores the origional pallette.      //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void RestorePallette() {

  WaitRetrace();
  for(int loop1=0; loop1<255; loop1++)
    Pal(loop1,Pall2[loop1][0],Pall2[loop1][1],Pall2[loop1][2]);

}


/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// sgn() - This function is used by Line() to determine the sign of a long //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

int sgn (long a) {

  if (a > 0) return +1;
  else if (a < 0) return -1;
  else return 0;

}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// round() - This function is used by Line() to round a long to the        //
//           nearest integer.                                              //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

int round (long a) {
  if ( (a - (int)a) < 0.5) return floor(a);
    else return ceil(a);
}


/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// Putpixel() - This puts a pixel on the screen by writing directly to     //
//              memory.                                                    //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void Putpixel (int x, int y, unsigned char Col) {

  memset(vga+(x+(y*320)),Col,1);

}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// Line() - This draws a line from a,b to c,d of color col.                //
//          This function will be explained in more detail in tut3new.zip  //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void Line(int a, int b, int c, int d, int col) {

long u,s,v,d1x,d1y,d2x,d2y,m,n;
int  i;

  u   = c-a;      // x2-x1
  v   = d-b;      // y2-y1
  d1x = sgn(u);   // d1x is the sign of u (x2-x1) (VALUE -1,0,1)
  d1y = sgn(v);   // d1y is the sign of v (y2-y1) (VALUE -1,0,1)
  d2x = sgn(u);   // d2x is the sign of u (x2-x1) (VALUE -1,0,1)
  d2y = 0;
  m   = abs(u);   // m is the distance between x1 and x2
  n   = abs(v);   // n is the distance between y1 and y2

  if (m<=n) {     // if the x distance is greater than the y distance
    d2x = 0;
    d2y = sgn(v); // d2y is the sign of v (x2-x1) (VALUE -1,0,1)
    m   = abs(v); // m is the distance between y1 and y2
    n   = abs(u); // n is the distance between x1 and x2
  }

  s = (int)(m / 2); // s is the m distance (either x or y) divided by 2

  for (i=0;i<round(m);i++) { // repeat this loop until it
			     // is = to m (y or x distance)
    Putpixel(a,b,col);       // plot a pixel at the original x1, y1
    s += n;                  // add n (dis of x or y) to s (dis of x of y)
    if (s >= m) {            // if s is >= m (distance between y1 and y2)
      s -= m;
      a += d1x;
      b += d1y;
    }
    else {
      a += d2x;
      b += d2y;
    }
  }

}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// WaitRetrace() - This waits until you are in a Verticle Retrace ...      //
// 		   this means that all screen manipulation you do only     //
//		   appears on screen in the next verticle retrace ... this //
//		   removes most of the "fuzz" that you see on the screen   //
//		   when changing the pallette. It unfortunately slows down //
//		   your program by "synching" your program with your       //
//		   monitor card ... it does mean that the program will run //
//		   at almost the same speed on different speeds of         //
//		   computers which have similar monitors.  In our          //
//		   SilkyDemo, we used a WaitRetrace, and it therefore      //
//		   runs at the same (fairly fast) speed when Turbo is on   //
//		   or off.                                                 //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void WaitRetrace() {

  _DX = 0x03DA;

  l1: asm {
	in  al,dx;
	and al,0x08;
	jnz l1;
      }

  l2: asm {
	in  al,dx;
	and al,0x08;
	jz  l2;
      }
}


/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// SetUpScreen() - This gets our screen ready by setting up the pallette   //
//                 and drawing the lines.                                  //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void SetUpScreen() {

  // Clear the entire PALL variable to zero.
  _fmemset(Pall,0,sizeof(Pall));

  // This sets colors 0 to 200 in the PALL variable to values between
  // 0 to 63. the modulus function gives you the remainder of a division,
  // ie. 105 % 10 = 5.
  for (int loop = 0; loop < 201;loop++)
    Pall[loop][0] = loop % 64;

  for (loop = 0; loop < 321; loop++) {

    // These two lines start drawing lines from the left and the right
    // hand sides of the screen, using colors 1 to 199. Look at these
    // two lines and understand them.
    Line(319,199,320-loop,0,(loop % 199) + 1);
    Line(0,0,loop,199,(loop % 199) + 1);

    // This calls the PalPlay function.
    PalPlay();
  }

}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// HiddenScreenSetup() - This function sets up the screen while it is      //
//                       blacked out, so that the user can't see what is   //
//                       happening.                                        //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

void HiddenScreenSetup() {

  for (int loop1=0; loop1<320; loop1++)
    for (int loop2=0; loop2<200; loop2++)
      Putpixel (loop1,loop2, rand());

}



Hosted by www.Geocities.ws

1