home *** CD-ROM | disk | FTP | other *** search
/ Teach Yourself Game Programming in 21 Days / TYGAMES_R.ISO / source / day_03 / graph3.c < prev    next >
Text File  |  1994-05-04  |  8KB  |  316 lines

  1.  
  2. // GRAPH3.C - This is the first module in the game library
  3.  
  4. // I N C L U D E S ///////////////////////////////////////////////////////////
  5.  
  6. #include <io.h>
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <bios.h>
  12. #include <fcntl.h>
  13. #include <memory.h>
  14. #include <malloc.h>
  15. #include <math.h>
  16. #include <string.h>
  17. #include "graph3.h"
  18.  
  19. // G L O B A L S //////////////////////////////////////////////////////////////
  20.  
  21. unsigned char far *video_buffer = (char far *)0xA0000000L; // vram byte ptr
  22. unsigned int far *video_buffer_w= (int far *)0xA0000000L;  // vram word ptr
  23. unsigned char far *rom_char_set = (char far *)0xF000FA6EL; // rom characters 8x8
  24.  
  25. // F U N C T I O N S /////////////////////////////////////////////////////////
  26.  
  27. void Blit_Char(int xc,int yc,char c,int color,int trans_flag)
  28. {
  29. // this function uses the rom 8x8 character set to blit a character on the
  30. // video screen, notice the trick used to extract bits out of each character
  31. // byte that comprises a line
  32.  
  33. int offset,x,y;
  34. char far *work_char;
  35. unsigned char bit_mask = 0x80;
  36.  
  37. // compute starting offset in rom character lookup table
  38.  
  39. work_char = rom_char_set + c * CHAR_HEIGHT;
  40.  
  41. // compute offset of character in video buffer
  42.  
  43. offset = (yc << 8) + (yc << 6) + xc;
  44.  
  45. for (y=0; y<CHAR_HEIGHT; y++)
  46.     {
  47.     // reset bit mask
  48.  
  49.     bit_mask = 0x80;
  50.  
  51.     for (x=0; x<CHAR_WIDTH; x++)
  52.         {
  53.         // test for transparent pixel i.e. 0, if not transparent then draw
  54.  
  55.         if ((*work_char & bit_mask))
  56.              video_buffer[offset+x] = color;
  57.  
  58.         else if (!trans_flag)  // takes care of transparency
  59.             video_buffer[offset+x] = 0;
  60.  
  61.         // shift bit mask
  62.  
  63.         bit_mask = (bit_mask>>1);
  64.  
  65.         } // end for x
  66.  
  67.     // move to next line in video buffer and in rom character data area
  68.  
  69.     offset      += SCREEN_WIDTH;
  70.     work_char++;
  71.  
  72.     } // end for y
  73.  
  74. } // end Blit_Char
  75.  
  76. //////////////////////////////////////////////////////////////////////////////
  77.  
  78. void Blit_String(int x,int y,int color, char *string,int trans_flag)
  79. {
  80. // this function blits an entire string on the screen with fixed spacing
  81. // between each character.  it calls blit_char.
  82.  
  83. int index;
  84.  
  85. for (index=0; string[index]!=0; index++)
  86.      {
  87.  
  88.      Blit_Char(x+(index<<3),y,string[index],color,trans_flag);
  89.  
  90.      } /* end while */
  91.  
  92. } /* end Blit_String */
  93.  
  94. ///////////////////////////////////////////////////////////////////////////////
  95.  
  96. void Plot_Pixel(int x,int y,unsigned char color)
  97. {
  98.  
  99. // plots the pixel in the desired color
  100. // each row contains 320 bytes, therefore multiple Y times the row and add x
  101.  
  102. video_buffer[y*320+x] = color;
  103.  
  104. } // end Plot_Pixel
  105.  
  106. ///////////////////////////////////////////////////////////////////////////////
  107.  
  108. void Plot_Pixel_Fast(int x,int y,unsigned char color)
  109. {
  110.  
  111. // plots the pixel in the desired color a little quicker using binary shifting
  112. // to accomplish the multiplications
  113.  
  114. // use the fact that 320*y = 256*y + 64*y = y<<8 + y<<6
  115.  
  116. video_buffer[((y<<8) + (y<<6)) + x] = color;
  117.  
  118. } // end Plot_Pixel_Fast
  119.  
  120. //////////////////////////////////////////////////////////////////////////////
  121.  
  122. void Set_Video_Mode(int mode)
  123. {
  124.  
  125. // use the video interrupt 10h to set the video mode to the sent value
  126.  
  127. union REGS inregs,outregs;
  128.  
  129. inregs.h.ah = 0;                    // set video mode sub-function
  130. inregs.h.al = (unsigned char)mode;  // video mode to change to
  131.  
  132. _int86(0x10, &inregs, &outregs);
  133.  
  134. } // end Set_Video_Mode
  135.  
  136. /////////////////////////////////////////////////////////////////////////////
  137.  
  138. void Delay(int clicks)
  139. {
  140. // this function uses the internal time keeper timer i.e. the one that goes
  141. // at 18.2 clicks/sec to to a time delay.  You can find a 32 bit value of
  142. // this timer at 0000:046Ch
  143.  
  144. unsigned int far *clock = (unsigned int far *)0x0000046CL;
  145.  
  146. unsigned int now;
  147.  
  148. // get current time
  149.  
  150. now = *clock;
  151.  
  152. // wait till time has gone past current time plus the amount we eanted to
  153. // wait.  Note each click is approx. 55 milliseconds.
  154.  
  155. while(abs(*clock - now) < clicks){}
  156.  
  157. } // end Delay
  158.  
  159. ////////////////////////////////////////////////////////////////////////////////
  160.  
  161. void H_Line(int x1,int x2,int y,unsigned int color)
  162. {
  163. // draw a horizontal line useing the memset function
  164. // note x2 > x1
  165.  
  166. _fmemset((char far *)(video_buffer + ((y<<8) + (y<<6)) + x1),color,x2-x1+1);
  167.  
  168. } // end H_Line
  169.  
  170. //////////////////////////////////////////////////////////////////////////////
  171.  
  172. void V_Line(int y1,int y2,int x,unsigned int color)
  173. {
  174. // draw a vertical line, note y2 > y1
  175.  
  176. unsigned int line_offset,
  177.                     index;
  178.  
  179. // compute starting position
  180.  
  181. line_offset = ((y1<<8) + (y1<<6)) + x;
  182.  
  183. for (index=0; index<=y2-y1; index++)
  184.     {
  185.     video_buffer[line_offset] = color;
  186.  
  187.      line_offset+=320; // move to next line
  188.  
  189.     } // end for index
  190.  
  191. } // end V_Line
  192.  
  193. //////////////////////////////////////////////////////////////////////////////
  194.  
  195. void H_Line_Fast(int x1,int x2,int y,unsigned int color)
  196. {
  197. // a fast horizontal line renderer uses word writes instead of byte writes
  198. // the only problem is the endpoints of the h line must be taken into account.
  199. // test if the endpoints of the horizontal line are on word boundaries i.e.
  200. // they are envenly divisible by 2
  201. // basically, we must consider the two end points of the line separately
  202. // if we want to write words at a time or in other words two pixels at a time
  203. // note x2 > x1
  204.  
  205. unsigned int first_word,
  206.             middle_word,
  207.               last_word,
  208.             line_offset,
  209.                    index;
  210.  
  211.  
  212. // test the 1's bit of the starting x
  213.  
  214. if ( (x1 & 0x0001) )
  215.    {
  216.  
  217.    first_word = (color<<8);
  218.  
  219.    } // end if starting point is on a word boundary
  220. else
  221.    {
  222.    // replicate color in to both bytes
  223.    first_word = ((color<<8) | color);
  224.  
  225.    } // end else
  226.  
  227. // test the 1's bit of the ending x
  228.  
  229. if ( (x2 & 0x0001) )
  230.    {
  231.  
  232.    last_word = ((color<<8) | color);
  233.  
  234.    } // end if ending point is on a word boundary
  235. else
  236.    {
  237.    // place color in high byte of word only
  238.  
  239.    last_word = color;
  240.  
  241.    } // end else
  242.  
  243. // now we can draw the horizontal line two pixels at a time
  244.  
  245. line_offset = ((y<<7) + (y<<5));  // y*160, since there are 160 words/line
  246.  
  247. // compute middle color
  248.  
  249. middle_word = ((color<<8) | color);
  250.  
  251. // left endpoint
  252.  
  253. video_buffer_w[line_offset + (x1>>1)] = first_word;
  254.  
  255. // the middle of the line
  256.  
  257. for (index=(x1>>1)+1; index<(x2>>1); index++)
  258.     video_buffer_w[line_offset+index] = middle_word;
  259.  
  260. // right endpoint
  261.  
  262. video_buffer_w[line_offset + (x2>>1)] = last_word;
  263.  
  264. } // end H_Line_Fast
  265.  
  266. //////////////////////////////////////////////////////////////////////////////
  267.  
  268. void Set_Palette_Register(int index, RGB_color_ptr color)
  269. {
  270.  
  271. // this function sets a single color look up table value indexed by index
  272. // with the value in the color structure
  273.  
  274. // tell VGA card we are going to update a pallete register
  275.  
  276. _outp(PALETTE_MASK,0xff);
  277.  
  278. // tell vga card which register we will be updating
  279.  
  280. _outp(PALETTE_REGISTER_WR, index);
  281.  
  282. // now update the RGB triple, note the same port is used each time
  283.  
  284. _outp(PALETTE_DATA,color->red);
  285. _outp(PALETTE_DATA,color->green);
  286. _outp(PALETTE_DATA,color->blue);
  287.  
  288. } // end Set_Palette_Color
  289.  
  290. ///////////////////////////////////////////////////////////////////////////////
  291.  
  292. void Get_Palette_Register(int index, RGB_color_ptr color)
  293. {
  294.  
  295. // this function gets the data out of a color lookup regsiter and places it
  296. // into color
  297.  
  298. // set the palette mask register
  299.  
  300. _outp(PALETTE_MASK,0xff);
  301.  
  302. // tell vga card which register we will be reading
  303.  
  304. _outp(PALETTE_REGISTER_RD, index);
  305.  
  306. // now extract the data
  307.  
  308. color->red   = _inp(PALETTE_DATA);
  309. color->green = _inp(PALETTE_DATA);
  310. color->blue  = _inp(PALETTE_DATA);
  311.  
  312. } // end Get_Palette_Color
  313.  
  314. ///////////////////////////////////////////////////////////////////////////////
  315.  
  316.