home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / SLOWRUNS.ZIP / SLOWSRC.ZIP / MAGIC3.C < prev    next >
C/C++ Source or Header  |  1997-06-30  |  37KB  |  1,323 lines

  1.  
  2. // I N C L U D E S ///////////////////////////////////////////////////////////
  3.  
  4. #include <io.h>
  5. #include <conio.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <dos.h>
  9. #include <bios.h>
  10. #include <fcntl.h>
  11. #include <memory.h>
  12. #include <malloc.h>
  13. #include <math.h>
  14. #include <string.h>
  15.  
  16. #include "magic3.h"   // the header file for this module
  17.  
  18. // G L O B A L S //////////////////////////////////////////////////////////////
  19.  
  20. unsigned char far *video_buffer = (unsigned char far *)0xA0000000L;
  21. unsigned char far *rom_char_set = (unsigned char far *)0xF000FA6EL;
  22.  
  23. // F U N C T I O N S /////////////////////////////////////////////////////////
  24.  
  25. void Print_Char(int xc,int yc,char c,int color,int transparent)
  26. {
  27. // this function is used to print a character on the screen. It uses the
  28. // internal 8x8 character set to do this. Note that each character is
  29. // 8 bytes where each byte represents the 8 pixels that make up the row
  30. // of pixels
  31.  
  32. int offset,               // offset into video memory
  33.          x,               // loop variable
  34.          y;               // loop variable
  35.  
  36. unsigned char far *work_char; // pointer to character being printed
  37.  
  38. unsigned char bit_mask;       // bitmask used to extract proper bit
  39.  
  40. // compute starting offset in rom character lookup table
  41. // multiple the character by 8 and add the result to the starting address
  42. // of the ROM character set
  43.  
  44. work_char = rom_char_set + c * ROM_CHAR_HEIGHT;
  45.  
  46. // compute offset of character in video buffer, use shifting to multiply
  47.  
  48. offset = (yc << 8) + (yc << 6) + xc;
  49.  
  50. // draw the character row by row
  51.  
  52. for (y=0; y<ROM_CHAR_HEIGHT; y++)
  53.     {
  54.     // reset bit mask
  55.  
  56.     bit_mask = 0x80;
  57.  
  58.      // draw each pixel of this row
  59.  
  60.     for (x=0; x<ROM_CHAR_WIDTH; x++)
  61.         {
  62.         // test for transparent pixel i.e. 0, if not transparent then draw
  63.  
  64.         if ((*work_char & bit_mask))
  65.              video_buffer[offset+x] = (unsigned char)color;
  66.  
  67.         else
  68.         if (!transparent)               // takes care of transparency
  69.             video_buffer[offset+x] = 0; // make black part opaque
  70.  
  71.         // shift bit mask
  72.  
  73.           bit_mask = (bit_mask>>1);
  74.  
  75.         } // end for x
  76.  
  77.     // move to next line in video buffer and in rom character data area
  78.  
  79.     offset      += MODE13_WIDTH;
  80.     work_char++;
  81.  
  82.     } // end for y
  83.  
  84. } // end Print_Char
  85.  
  86. //////////////////////////////////////////////////////////////////////////////
  87.  
  88. void Print_String(int x,int y,int color, char *string,int transparent)
  89. {
  90. // this function prints an entire string on the screen with fixed spacing
  91. // between each character by calling the Print_Char() function
  92.  
  93.  int index,   // loop index
  94.      length;  // length of string
  95.  
  96. // compute length of string
  97.  
  98. length = strlen(string);
  99.  
  100. // print the string a character at a time
  101.  
  102. for (index=0; index<length; index++)
  103.       Print_Char(x+(index<<3),y,string[index],color,transparent);
  104.  
  105. } // end Print_String
  106.  
  107. void Print_Char_Mode_Y(int xc,int yc,char c,int color,int transparent)
  108. {
  109. // this function is used to print a character on the screen. It uses the
  110. // internal 8x8 character set to do this. Note that each character is
  111. // 8 bytes where each byte represents the 8 pixels that make up the row
  112. // of pixels
  113.  
  114. // This function cuts down on OUTS by 'unrolling the loop' and printing
  115. // a character every FOURTH row at a time.
  116.  
  117. // It was one of my first attempts to print in MODE Y, and at the time
  118. // I didn't realize I was only cutting half the OUTS per character, only
  119. // HALVING the OUTS per line of text.
  120.  
  121.     int offset,             // offset into video memory
  122.         offset2,
  123.         x,                   // loop variable
  124.         y;                   // loop variable
  125.  
  126.     unsigned char far *work_char;     // pointer to character being printed
  127.  
  128.     unsigned char bit_mask;           // bitmask used to extract proper bit
  129.  
  130.     // compute starting offset in rom character lookup table
  131.     // multiple the character by 8 and add the result to the starting address
  132.     // of the ROM character set
  133.  
  134.     work_char = rom_char_set + c * ROM_CHAR_HEIGHT;
  135.  
  136.     // compute offset of character in video buffer, use shifting to multiply
  137.  
  138.     offset2 = (yc << 6) + (yc << 4);
  139.  
  140.     offset = (yc << 6) + (yc << 4) + (xc>>2);
  141.  
  142.     // draw the character row by row
  143.  
  144.     _asm
  145.     {
  146.         mov dx,SEQUENCER          // address the sequencer
  147.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  148.         mov cl,BYTE PTR xc         // extract lower byte from x
  149.         and cl,03h                // extract the plane number = x MOD 4
  150.         mov ah,1                  // a "1" selects the plane in the plane enable
  151.         shl ah,cl                 // shift the "1" bit proper number of times
  152.         out dx,ax                 // do it baby!
  153.     } // end asm
  154.  
  155.     for (y=0; y<ROM_CHAR_HEIGHT; y++)
  156.     {
  157.         // reset bit mask
  158.  
  159.         bit_mask = 0x80;
  160.  
  161.          // draw each pixel of this row
  162.  
  163.         for (x=0; x<ROM_CHAR_WIDTH; x+=4)
  164.         {
  165.             // test for transparent pixel i.e. 0, if not transparent then draw
  166.  
  167.  
  168.             if ((*work_char & bit_mask))
  169.                  video_buffer[offset+(x>>2)] = (unsigned char)color;
  170.  
  171.             else
  172.             if (!transparent)               // takes care of transparency
  173.                 video_buffer[offset+(x>>2)] = 0; // make black part opaque
  174.  
  175.             // shift bit mask
  176.  
  177.               bit_mask = (bit_mask>>4);
  178.  
  179.         } // end for x
  180.  
  181.         // move to next line in video buffer and in rom character data area
  182.  
  183.         offset      += MODE_Y_WIDTH;
  184.         work_char++;
  185.  
  186.     } // end for y
  187.  
  188.     xc++;
  189.  
  190.     work_char = rom_char_set + c * ROM_CHAR_HEIGHT;
  191.  
  192.     offset = offset2 + (xc>>2);
  193.  
  194.     _asm
  195.     {
  196.         mov dx,SEQUENCER          // address the sequencer
  197.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  198.         mov cl,BYTE PTR xc         // extract lower byte from x
  199.         and cl,03h                // extract the plane number = x MOD 4
  200.         mov ah,1                  // a "1" selects the plane in the plane enable
  201.         shl ah,cl                 // shift the "1" bit proper number of times
  202.         out dx,ax                 // do it baby!
  203.     } // end asm
  204.  
  205.     for (y=0; y<ROM_CHAR_HEIGHT; y++)
  206.     {
  207.         // reset bit mask
  208.  
  209.         bit_mask = 0x80;
  210.         bit_mask = (bit_mask>>1);
  211.  
  212.          // draw each pixel of this row
  213.  
  214.         for (x=1; x<ROM_CHAR_WIDTH; x+=4)
  215.         {
  216.             // test for transparent pixel i.e. 0, if not transparent then draw
  217.  
  218.  
  219.             if ((*work_char & bit_mask))
  220.                  video_buffer[offset+(x>>2)] = (unsigned char)color;
  221.  
  222.             else
  223.             if (!transparent)               // takes care of transparency
  224.                 video_buffer[offset+(x>>2)] = 0; // make black part opaque
  225.  
  226.             // shift bit mask
  227.  
  228.               bit_mask = (bit_mask>>4);
  229.  
  230.         } // end for x
  231.  
  232.         // move to next line in video buffer and in rom character data area
  233.  
  234.         offset      += MODE_Y_WIDTH;
  235.         work_char++;
  236.  
  237.     } // end for y
  238.  
  239.     xc++;
  240.  
  241.     work_char = rom_char_set + c * ROM_CHAR_HEIGHT;
  242.  
  243.  
  244.     offset = offset2 + (xc>>2);
  245.  
  246.     _asm
  247.     {
  248.         mov dx,SEQUENCER          // address the sequencer
  249.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  250.         mov cl,BYTE PTR xc         // extract lower byte from x
  251.         and cl,03h                // extract the plane number = x MOD 4
  252.         mov ah,1                  // a "1" selects the plane in the plane enable
  253.         shl ah,cl                 // shift the "1" bit proper number of times
  254.         out dx,ax                 // do it baby!
  255.     } // end asm
  256.  
  257.     for (y=0; y<ROM_CHAR_HEIGHT; y++)
  258.     {
  259.         // reset bit mask
  260.  
  261.         bit_mask = 0x80;
  262.         bit_mask = (bit_mask>>2);
  263.  
  264.          // draw each pixel of this row
  265.  
  266.         for (x=2; x<ROM_CHAR_WIDTH; x+=4)
  267.         {
  268.             // test for transparent pixel i.e. 0, if not transparent then draw
  269.  
  270.  
  271.             if ((*work_char & bit_mask))
  272.                  video_buffer[offset+(x>>2)] = (unsigned char)color;
  273.  
  274.             else
  275.             if (!transparent)               // takes care of transparency
  276.                 video_buffer[offset+(x>>2)] = 0; // make black part opaque
  277.  
  278.             // shift bit mask
  279.  
  280.               bit_mask = (bit_mask>>4);
  281.  
  282.         } // end for x
  283.  
  284.         // move to next line in video buffer and in rom character data area
  285.  
  286.         offset      += MODE_Y_WIDTH;
  287.         work_char++;
  288.  
  289.     } // end for y
  290.  
  291.     xc++;
  292.  
  293.     work_char = rom_char_set + c * ROM_CHAR_HEIGHT;
  294.  
  295.     offset = offset2 + (xc>>2);
  296.  
  297.     _asm
  298.     {
  299.         mov dx,SEQUENCER          // address the sequencer
  300.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  301.         mov cl,BYTE PTR xc         // extract lower byte from x
  302.         and cl,03h                // extract the plane number = x MOD 4
  303.         mov ah,1                  // a "1" selects the plane in the plane enable
  304.         shl ah,cl                 // shift the "1" bit proper number of times
  305.         out dx,ax                 // do it baby!
  306.     } // end asm
  307.  
  308.     for (y=0; y<ROM_CHAR_HEIGHT; y++)
  309.     {
  310.         // reset bit mask
  311.  
  312.         bit_mask = 0x80;
  313.         bit_mask = (bit_mask>>3);
  314.  
  315.          // draw each pixel of this row
  316.  
  317.         for (x=3; x<ROM_CHAR_WIDTH; x+=4)
  318.         {
  319.             // test for transparent pixel i.e. 0, if not transparent then draw
  320.  
  321.  
  322.             if ((*work_char & bit_mask))
  323.                  video_buffer[offset+(x>>2)] = (unsigned char)color;
  324.  
  325.             else
  326.             if (!transparent)               // takes care of transparency
  327.                 video_buffer[offset+(x>>2)] = 0; // make black part opaque
  328.  
  329.             // shift bit mask
  330.  
  331.               bit_mask = (bit_mask>>4);
  332.  
  333.         } // end for x
  334.  
  335.         // move to next line in video buffer and in rom character data area
  336.  
  337.         offset      += MODE_Y_WIDTH;
  338.         work_char++;
  339.  
  340.     } // end for y
  341.  
  342. } // end Print_Char_Mode_Y
  343.  
  344. //////////////////////////////////////////////////////////////////////////////
  345.  
  346. void Print_String_Mode_Y(int x,int y,int color, char *string,int transparent)
  347. {
  348. // this MODE Y function prints an entire string on the screen with fixed
  349. // spacing between each character by calling the Print_Char_Mode_Y() function
  350.  
  351.  int index,   // loop index
  352.      length;  // length of string
  353.  
  354. // compute length of string
  355.  
  356. length = strlen(string);
  357.  
  358. // print the string a character at a time
  359.  
  360. for (index=0; index<length; index++)
  361.       Print_Char_Mode_Y(x+(index<<3),y,string[index],color,transparent);
  362.  
  363. } // end Print_String_Mode_Y
  364.  
  365. ///////////////////////////////////////////////////////////////////////////////
  366.  
  367. void Write_Pixel(int x,int y,int color)
  368. {
  369.  
  370. // plots the pixel in the desired color a little quicker using binary shifting
  371. // to accomplish the multiplications
  372.  
  373. // use the fact that 320*y = 256*y + 64*y = y<<8 + y<<6
  374.  
  375. video_buffer[((y<<8) + (y<<6)) + x] = (unsigned char )color;
  376.  
  377. } // end Write_Pixel
  378.  
  379. ///////////////////////////////////////////////////////////////////////////////
  380.  
  381. int Read_Pixel(int x,int y)
  382. {
  383. // this function read a pixel from the screen buffer
  384.  
  385.  
  386. // use the fact that 320*y = 256*y + 64*y = y<<8 + y<<6
  387.  
  388. return((int)(video_buffer[((y<<8) + (y<<6)) + x]));
  389.  
  390. } // end Read_Pixel
  391.  
  392. //////////////////////////////////////////////////////////////////////////////
  393.  
  394. void Set_Graphics_Mode(int mode)
  395. {
  396.  
  397. // use the video interrupt 10h and the C interrupt function to set
  398. // the video mode
  399.  
  400. union REGS inregs,outregs;
  401.  
  402. inregs.h.ah = 0;                    // set video mode sub-function
  403. inregs.h.al = (unsigned char)mode;  // video mode to change to
  404.  
  405. int86(0x10, &inregs, &outregs);
  406.  
  407. } // end Set_Graphics_Mode
  408.  
  409. /////////////////////////////////////////////////////////////////////////////
  410.  
  411. void Time_Delay(int clicks)
  412. {
  413. // this function uses the internal timer to wait a specified number of "clicks"
  414. // the actual amount of real time is the number of clicks * (time per click)
  415. // usually the time per click is set to 1/18th of a second or 55ms
  416.  
  417. long far *clock = (long far *)0x0000046CL; // address of timer
  418.  
  419. long start_time; // starting time
  420.  
  421. // get current time
  422.  
  423. start_time = *clock;
  424.  
  425. // when the current time minus the starting time >= the requested delay then
  426. // the function can exit
  427.  
  428. while(labs(*clock - start_time) < (long)clicks){}
  429.  
  430. } // end Time_Delay
  431.  
  432. ////////////////////////////////////////////////////////////////////////////////
  433.  
  434. void Line_H(int x1,int x2,int y,int color)
  435. {
  436. // draw a horizontal line using the memset function
  437. // this function does not do clipping hence x1,x2 and y must all be within
  438. // the bounds of the screen
  439.  
  440. int temp; // used for temporary storage during endpoint swap
  441.  
  442. // sort x1 and x2, so that x2 > x1
  443.  
  444. if (x1>x2)
  445.    {
  446.    temp = x1;
  447.    x1   = x2;
  448.    x2   = temp;
  449.    } // end swap
  450.  
  451. // draw the row of pixels
  452.  
  453. _fmemset((char far *)(video_buffer + ((y<<8) + (y<<6)) + x1),
  454.          (unsigned char)color,x2-x1+1);
  455.  
  456. } // end Line_H
  457.  
  458. //////////////////////////////////////////////////////////////////////////////
  459.  
  460. void Line_V(int y1,int y2,int x,int color)
  461. {
  462. // draw a vertical line, note that a memset function can no longer be
  463. // used since the pixel addresses are no longer contiguous in memory
  464. // note that the end points of the line must be on the screen
  465.  
  466. unsigned char far *start_offset; // starting memory offset of line
  467.  
  468. int index, // loop index
  469.     temp;  // used for temporary storage during swap
  470.  
  471. // make sure y2 > y1
  472.  
  473. if (y1>y2)
  474.    {
  475.    temp = y1;
  476.    y1   = y2;
  477.    y2   = temp;
  478.    } // end swap
  479.  
  480. // compute starting position
  481.  
  482. start_offset = video_buffer + ((y1<<8) + (y1<<6)) + x;
  483.  
  484. for (index=0; index<=y2-y1; index++)
  485.     {
  486.     // set the pixel
  487.  
  488.     *start_offset = (unsigned char)color;
  489.  
  490.     // move downward to next line
  491.  
  492.     start_offset+=320;
  493.  
  494.     } // end for index
  495.  
  496. } // end Line_V
  497.  
  498. ///////////////////////////////////////////////////////////////////////////////
  499.  
  500. void Line_H_Mode_Y(int x1,int x2,int y,int color)
  501. {
  502. // draw a horizontal line using the memset function
  503. // this function does not do clipping hence x1,x2 and y must all be within
  504. // the bounds of the screen
  505.  
  506. int index;
  507. int temp; // used for temporary storage during endpoint swap
  508.  
  509. // draw the row of pixels
  510.     _asm
  511.     {
  512.         mov dx,SEQUENCER          // address the sequencer
  513.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  514.         mov cl,BYTE PTR x1     // extract lower byte from index
  515.         and cl,03h                // extract the plane number = index MOD 4
  516.         mov ah,1                  // a "1" selects the plane in the plane enable
  517.         shl ah,cl                 // shift the "1" bit proper number of times
  518.         out dx,ax                 // do it baby!
  519.     } // end asm
  520.  
  521.     for (index = x1; index <= x2; index+=4)
  522.     {
  523.  
  524.  
  525.         _fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
  526.                  (unsigned char)color,1);
  527.  
  528.     }
  529.  
  530.     x1++;
  531.  
  532.     _asm
  533.     {
  534.         mov dx,SEQUENCER          // address the sequencer
  535.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  536.         mov cl,BYTE PTR x1     // extract lower byte from index
  537.         and cl,03h                // extract the plane number = index MOD 4
  538.         mov ah,1                  // a "1" selects the plane in the plane enable
  539.         shl ah,cl                 // shift the "1" bit proper number of times
  540.         out dx,ax                 // do it baby!
  541.     } // end asm
  542.  
  543.     for (index = x1; index <= x2; index+=4)
  544.     {
  545.  
  546.  
  547.         _fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
  548.                  (unsigned char)color,1);
  549.  
  550.     }
  551.  
  552.     x1++;
  553.  
  554.     _asm
  555.     {
  556.         mov dx,SEQUENCER          // address the sequencer
  557.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  558.         mov cl,BYTE PTR x1     // extract lower byte from index
  559.         and cl,03h                // extract the plane number = index MOD 4
  560.         mov ah,1                  // a "1" selects the plane in the plane enable
  561.         shl ah,cl                 // shift the "1" bit proper number of times
  562.         out dx,ax                 // do it baby!
  563.     } // end asm
  564.  
  565.     for (index = x1; index <= x2; index+=4)
  566.     {
  567.  
  568.  
  569.         _fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
  570.                  (unsigned char)color,1);
  571.  
  572.     }
  573.  
  574.     x1++;
  575.  
  576.     _asm
  577.     {
  578.         mov dx,SEQUENCER          // address the sequencer
  579.         mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  580.         mov cl,BYTE PTR x1     // extract lower byte from index
  581.         and cl,03h                // extract the plane number = index MOD 4
  582.         mov ah,1                  // a "1" selects the plane in the plane enable
  583.         shl ah,cl                 // shift the "1" bit proper number of times
  584.         out dx,ax                 // do it baby!
  585.     } // end asm
  586.  
  587.     for (index = x1; index <= x2; index+=4)
  588.     {
  589.  
  590.  
  591.         _fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
  592.                  (unsigned char)color,1);
  593.  
  594.     }
  595.  
  596. } // end Line_H_Mode_Y
  597.  
  598. //////////////////////////////////////////////////////////////////////////////
  599.  
  600. void Line_H_Mode_Z(int x1,int x2,int y,int color)
  601. {
  602. // draw a horizontal line using the memset function
  603. // this function does not do clipping hence x1,x2 and y must all be within
  604. // the bounds of the screen
  605.  
  606. int index;
  607. int temp; // used for temporary storage during endpoint swap
  608.  
  609. // sort x1 and x2, so that x2 > x1
  610.  
  611. if (x1>x2)
  612.    {
  613.    temp = x1;
  614.    x1   = x2;
  615.    x2   = temp;
  616.    } // end swap
  617.  
  618. // draw the row of pixels
  619.  
  620.    for (index = x1; index <= x2; index++)
  621.    {
  622.         _asm
  623.         {
  624.             mov dx,SEQUENCER          // address the sequencer
  625.             mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  626.             mov cl,BYTE PTR index     // extract lower byte from index
  627.             and cl,03h                // extract the plane number = index MOD 4
  628.             mov ah,1                  // a "1" selects the plane in the plane enable
  629.             shl ah,cl                 // shift the "1" bit proper number of times
  630.             out dx,ax                 // do it baby!
  631.         } // end asm
  632.  
  633.         _fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
  634.                      (unsigned char)color,1);
  635.  
  636.       }
  637. } // end Line_H_Mode_Z
  638.  
  639. //////////////////////////////////////////////////////////////////////////////
  640.  
  641. void Line_V_Mode_Y(int y1,int y2,int x,int color)
  642. {
  643. // draw a vertical line, note that a memset function can no longer be
  644. // used since the pixel addresses are no longer contiguous in memory
  645. // note that the end points of the line must be on the screen
  646.  
  647. unsigned char far *start_offset; // starting memory offset of line
  648.  
  649. int index, // loop index
  650.     temp;  // used for temporary storage during swap
  651.  
  652. // make sure y2 > y1
  653.  
  654. if (y1>y2)
  655.    {
  656.    temp = y1;
  657.    y1   = y2;
  658.    y2   = temp;
  659.    } // end swap
  660.  
  661. // compute starting position
  662.  
  663. _asm
  664. {
  665.     mov dx,SEQUENCER          // address the sequencer
  666.     mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  667.     mov cl,BYTE PTR x         // extract lower byte from index
  668.     and cl,03h                // extract the plane number = index MOD 4
  669.     mov ah,1                  // a "1" selects the plane in the plane enable
  670.     shl ah,cl                 // shift the "1" bit proper number of times
  671.     out dx,ax                 // do it baby!
  672. } // end asm
  673.  
  674. start_offset = video_buffer + ((y1<<6) + (y1<<4)) + (x>>2);
  675.  
  676. for (index=0; index<=y2-y1; index++)
  677.     {
  678.     // set the pixel
  679.  
  680.     *start_offset = (unsigned char)color;
  681.  
  682.     // move downward to next line
  683.  
  684.     start_offset+=80;
  685.  
  686.     } // end for index
  687.  
  688. } // end Line_V_Mode_Y
  689.  
  690. //////////////////////////////////////////////////////////////////////////////
  691.  
  692. void Line_V_Mode_Z(int y1,int y2,int x,int color)
  693. {
  694. // draw a vertical line, note that a memset function can no longer be
  695. // used since the pixel addresses are no longer contiguous in memory
  696. // note that the end points of the line must be on the screen
  697.  
  698. unsigned char far *start_offset; // starting memory offset of line
  699.  
  700. int index, // loop index
  701.     temp;  // used for temporary storage during swap
  702.  
  703. // make sure y2 > y1
  704.  
  705. if (y1>y2)
  706.    {
  707.    temp = y1;
  708.    y1   = y2;
  709.    y2   = temp;
  710.    } // end swap
  711.  
  712. // compute starting position
  713.  
  714. _asm
  715. {
  716.     mov dx,SEQUENCER          // address the sequencer
  717.     mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  718.     mov cl,BYTE PTR x         // extract lower byte from index
  719.     and cl,03h                // extract the plane number = index MOD 4
  720.     mov ah,1                  // a "1" selects the plane in the plane enable
  721.     shl ah,cl                 // shift the "1" bit proper number of times
  722.     out dx,ax                 // do it baby!
  723. } // end asm
  724.  
  725. start_offset = video_buffer + ((y1<<6) + (y1<<4)) + (x>>2);
  726.  
  727. for (index=0; index<=y2-y1; index++)
  728.     {
  729.     // set the pixel
  730.  
  731.     *start_offset = (unsigned char)color;
  732.  
  733.     // move downward to next line
  734.  
  735.     start_offset+=80;
  736.  
  737.     } // end for index
  738.  
  739. } // end Line_V_Mode_Z
  740.  
  741. //////////////////////////////////////////////////////////////////////////////
  742.  
  743. void Write_Color_Reg(int index, RGB_color_ptr color)
  744. {
  745.  
  746. // this function is used to write a color register with the RGB value
  747. // within "color"
  748.  
  749. // tell vga card which color register to update
  750.  
  751. outp(COLOR_REGISTER_WR, index);
  752.  
  753. // update the color register RGB triple, note the same port is used each time
  754. // the hardware will make sure each of the components is stored in the
  755. // proper location
  756.  
  757. outp(COLOR_DATA,color->red);
  758. outp(COLOR_DATA,color->green);
  759. outp(COLOR_DATA,color->blue);
  760.  
  761. } // end Write_Color_Reg
  762.  
  763. ///////////////////////////////////////////////////////////////////////////////
  764.  
  765. RGB_color_ptr Read_Color_Reg(int index, RGB_color_ptr color)
  766. {
  767.  
  768. // this function reads the RGB triple out of a palette register and places it
  769. // into "color"
  770.  
  771. // tell vga card which register to read
  772.  
  773. outp(COLOR_REGISTER_RD, index);
  774.  
  775. // now extract the data
  776.  
  777. color->red   = (unsigned char)inp(COLOR_DATA);
  778. color->green = (unsigned char)inp(COLOR_DATA);
  779. color->blue  = (unsigned char)inp(COLOR_DATA);
  780.  
  781. // return a pointer to color so that the function can be used as an RVALUE
  782.  
  783. return(color);
  784.  
  785. } // end Read_Color_Reg
  786.  
  787. ///////////////////////////////////////////////////////////////////////////////
  788.  
  789. void Read_Palette(int start_reg,int end_reg, RGB_palette_ptr the_palette)
  790. {
  791. // this function will read the palette registers in the range start_reg to
  792. // end_reg and save them into the appropriate positions in colors
  793.  
  794. int index; // used for looping
  795.  
  796. RGB_color color;
  797.  
  798. // read all the registers
  799.  
  800. for (index=start_reg; index<=end_reg; index++)
  801.     {
  802.     // read the color register
  803.  
  804.     Read_Color_Reg(index,(RGB_color_ptr)&color);
  805.  
  806.     // save it in database
  807.  
  808.     the_palette->colors[index].red   = color.red;
  809.     the_palette->colors[index].green = color.green;
  810.     the_palette->colors[index].blue  = color.blue;
  811.  
  812.     } // end for index
  813.  
  814. // save the interval of registers that were saved
  815.  
  816. the_palette->start_reg = start_reg;
  817. the_palette->end_reg   = end_reg;
  818.  
  819. } // end Read_Palette
  820.  
  821. ///////////////////////////////////////////////////////////////////////////////
  822.  
  823. void Write_Palette(int start_reg,int end_reg, RGB_palette_ptr the_palette)
  824. {
  825. // this function will write to the color registers using the data in the
  826. // sen palette structure
  827.  
  828. int index; // used for looping
  829.  
  830. // write all the registers
  831.  
  832. for (index=start_reg; index<=end_reg; index++)
  833.     {
  834.     // write the color registers using the data from the sent palette
  835.  
  836.     Write_Color_Reg(index,(RGB_color_ptr)&(the_palette->colors[index]));
  837.  
  838.     } // end for index
  839.  
  840. } // end Write_Palette
  841.  
  842. ///////////////////////////////////////////////////////////////////////////////
  843.  
  844. void Draw_Rectangle(int x1,int y1,int x2,int y2,int color)
  845. {
  846. // this function will draw a rectangle from (x1,y1) - (x2,y2)
  847. // it is assumed that each endpoint is within the screen boundaries
  848. // and (x1,y1) is the upper left hand corner and (x2,y2) is the lower
  849. // right hand corner
  850.  
  851. unsigned char far *start_offset;   // starting memory offset of first row
  852.  
  853. int width;   // width of rectangle
  854.  
  855. // compute starting offset of first row
  856.  
  857. start_offset = video_buffer + ((y1<<8) + (y1<<6)) + x1;
  858.  
  859. // compute width of rectangle
  860.  
  861. width  = 1 + x2 - x1; // the "1" to reflect the true width in pixels
  862.  
  863. // draw the rectangle row by row
  864.  
  865. while(y1++<=y2)
  866.      {
  867.      // draw the line
  868.  
  869.      _fmemset((char far *)start_offset,(unsigned char)color,width);
  870.  
  871.      // move the memory pointer to the next line
  872.  
  873.      start_offset+=320;
  874.  
  875.      } // end while
  876.  
  877. } // end Draw_Rectangle
  878.  
  879. ////////////////////////////////////////////////////////////////////////////////
  880.  
  881. void Fill_Screen(int color)
  882. {
  883. // this function will fill the entire screen with the sent color
  884.  
  885. // use the inline assembler for speed
  886.  
  887. _asm    {
  888.  
  889.     les di,video_buffer   // point es:di to video buffer
  890.  
  891.     mov al,BYTE PTR color // move the color into al and ah
  892.  
  893.     mov ah,al             // replicate color into ah
  894.  
  895.     mov cx,320*200/2      // number of words to fill(using word is faster than bytes)
  896.  
  897.     rep stosw             // move the color into the video buffer really fast!
  898.  
  899.     } // end inline asm
  900.  
  901. } // end Fill_Screen
  902.  
  903. //////////////////////////////////////////////////////////////////////////////
  904.  
  905. void Fill_Screen_Z(int color)
  906. {
  907. // this function will fill the mode Z video buffer with the sent color
  908.  
  909. // use the inline assembler for speed
  910.  
  911. _asm   {
  912.     mov dx,SEQUENCER          // address the sequencer
  913.     mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  914.     mov ah,0fh                // enable all four planes
  915.     out dx,ax                 // do it baby!
  916.     les di,video_buffer   // point es:di to video buffer
  917.     mov al,BYTE PTR color // move the color into al and ah
  918.     mov ah,al             // replicate color into ah
  919.     mov cx,320*400/8      // number of words to fill(using word is faster than bytes)
  920.     rep stosw             // move the color into the video buffer really fast!
  921.     } // end inline asm
  922.  
  923. } // end Fill_Screen_Z
  924.  
  925. ///////////////////////////////////////////////////////////////////////////////
  926.  
  927. void Write_Pixel_Z(int x,int y,int color)
  928. {
  929.  
  930. // this function will write a pixel to screen in mode Z
  931.  
  932. // first select the proper color plane use inline for speed
  933. // if we used C then there would be a function call and about 10-15 more
  934. // instructions!
  935.  
  936. _asm   {
  937.     mov dx,SEQUENCER          // address the sequencer
  938.     mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  939.     mov cl,BYTE PTR x         // extract lower byte from x
  940.     and cl,03h                // extract the plane number = x MOD 4
  941.     mov ah,1                  // a "1" selects the plane in the plane enable
  942.     shl ah,cl                 // shift the "1" bit proper number of times
  943.     out dx,ax                 // do it baby!
  944.     } // end asm
  945.  
  946. // write the pixel, offset = (y*320+x)/4
  947.  
  948. video_buffer[(y<<6)+(y<<4)+(x>>2)] = (unsigned char )color;
  949.  
  950. } // end Write_Pixel_Z
  951.  
  952. ///////////////////////////////////////////////////////////////////////////////
  953.  
  954. void Set_Mode_Z(void)
  955. {
  956. // this function will set the video mode to 320x400x256
  957.  
  958. int data;  // used to store data
  959. unsigned char far *zpage1 = (unsigned char far *)0xA0000000L;
  960. unsigned char far *zpage2 = (unsigned char far *)0xA0008000L;
  961.  
  962. // set system to mode 13h and use it as a foundation to base 320x400 mode on
  963.  
  964. _asm   {
  965.     mov ax,0013h  // ah=function number 00(set graphics mode), al=13h
  966.     int 10h       // video interrupt 10h
  967.    } // end asm
  968.  
  969. // make changes to the crt controller first
  970.  
  971. // set number of scanlines to 1
  972.  
  973. outp(CRT_CONTROLLER,CRT_MAX_SCANLINE);
  974. data=inp(CRT_CONTROLLER+1);
  975. outp(CRT_CONTROLLER+1,RESET_BITS(data,0x0f));
  976.  
  977. // use byte addressing instead of word
  978.  
  979. outp(CRT_CONTROLLER,CRT_ADDR_MODE);
  980. data=inp(CRT_CONTROLLER+1);
  981. outp(CRT_CONTROLLER+1,RESET_BITS(data,0x40));
  982.  
  983. // second register that needs to reflect byte addressing
  984.  
  985. outp(CRT_CONTROLLER,CRT_MODE_CONTROL);
  986. data=inp(CRT_CONTROLLER+1);
  987. outp(CRT_CONTROLLER+1,SET_BITS(data,0x40));
  988.  
  989. // make changes to graphics controller
  990.  
  991. // set addressing to not use odd/even memory writes
  992.  
  993. outp(GFX_CONTROLLER,GFX_WRITE_MODE);
  994. data=inp(GFX_CONTROLLER+1);
  995. outp(GFX_CONTROLLER+1,RESET_BITS(data,0x10));
  996.  
  997. // don't chain the memory maps together
  998.  
  999. outp(GFX_CONTROLLER,GFX_MISC);
  1000. data=inp(GFX_CONTROLLER+1);
  1001. outp(GFX_CONTROLLER+1,RESET_BITS(data,0x02));
  1002.  
  1003. // make changes to sequencer
  1004.  
  1005. // again we must select no chaining and no odd/even memory addressing
  1006.  
  1007. outp(SEQUENCER,SEQ_MEMORY_MODE);
  1008. data =inp(SEQUENCER+1);
  1009. data = RESET_BITS(data,0x08);
  1010. data = SET_BITS(data,0x04);
  1011. outp(SEQUENCER+1,data);
  1012.  
  1013. // now clear the screen
  1014.  
  1015. outp(SEQUENCER,SEQ_PLANE_ENABLE);
  1016. outp(SEQUENCER+1,0x0f);
  1017.  
  1018. // clear the screen, remember it is 320x400, but that is divided into four
  1019. // planes, hence we need only to clear 32k out since there will ne four planes
  1020. // each being cleared in parallel for a total of 4*32k or 128 = 320x400
  1021. // note: "k" in this example means 1000 not 1024
  1022.  
  1023. // clear BOTH pages...
  1024.  
  1025. _asm   {
  1026.  
  1027.     les di,zpage1             // point es:di to video buffer, same address for mode Z
  1028.     xor ax,ax             // move a zero into al and ah
  1029.     mov cx,320*400/8      // number of words to fill(using word is faster than bytes)
  1030.     rep stosw             // move the color into the video buffer really fast!
  1031.  
  1032.     } // end inline asm
  1033.  
  1034. _asm   {
  1035.  
  1036.     les di,zpage2         // point es:di to video buffer, same addre for mode Z
  1037.     xor ax,ax             // move a zero into al and ah
  1038.     mov cx,320*400/8      // number of words to fill(using word is faster than bytes)
  1039.     rep stosw             // move the color into the video buffer really fast!
  1040.  
  1041.     } // end inline asm
  1042.  
  1043. } // end Set_Mode_Z
  1044.  
  1045. // MODE_Y_STUFF...
  1046.  
  1047. void Fill_Screen_Y(int color)
  1048. {
  1049. // this function will fill the mode Z video buffer with the sent color
  1050.  
  1051. // use the inline assembler for speed
  1052.  
  1053. _asm   {
  1054.     mov dx,SEQUENCER          // address the sequencer
  1055.     mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  1056.     mov ah,0fh                // enable all four planes
  1057.     out dx,ax                 // do it baby!
  1058.     les di,video_buffer   // point es:di to video buffer
  1059.     mov al,BYTE PTR color // move the color into al and ah
  1060.     mov ah,al             // replicate color into ah
  1061.     mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  1062.     rep stosw             // move the color into the video buffer really fast!
  1063.     } // end inline asm
  1064.  
  1065. } // end Fill_Screen_Y
  1066.  
  1067. ///////////////////////////////////////////////////////////////////////////////
  1068.  
  1069. void Write_Pixel_Y(int x,int y,int color)
  1070. {
  1071.  
  1072. // this function will write a pixel to screen in mode Z
  1073.  
  1074. // first select the proper color plane use inline for speed
  1075. // if we used C then there would be a function call and about 10-15 more
  1076. // instructions!
  1077.  
  1078. _asm   {
  1079.     mov dx,SEQUENCER          // address the sequencer
  1080.     mov al,SEQ_PLANE_ENABLE   // select the plane enable register
  1081.     mov cl,BYTE PTR x         // extract lower byte from x
  1082.     and cl,03h                // extract the plane number = x MOD 4
  1083.     mov ah,1                  // a "1" selects the plane in the plane enable
  1084.     shl ah,cl                 // shift the "1" bit proper number of times
  1085.     out dx,ax                 // do it baby!
  1086.     } // end asm
  1087.  
  1088. // write the pixel, offset = (y*320+x)/4
  1089.  
  1090. video_buffer[(y<<6)+(y<<4)+(x>>2)] = (unsigned char )color;
  1091.  
  1092. } // end Write_Pixel_Y
  1093.  
  1094. ///////////////////////////////////////////////////////////////////////////////
  1095.  
  1096. void Set_Mode_Y(void)
  1097. {
  1098. // this function will set the video mode to 320x400x256
  1099.  
  1100. int data;  // used to store data
  1101.  
  1102. // set system to mode 13h and use it as a foundation to base 320x400 mode on
  1103.  
  1104. _asm   {
  1105.     mov ax,0013h  // ah=function number 00(set graphics mode), al=13h
  1106.     int 10h       // video interrupt 10h
  1107.    } // end asm
  1108.  
  1109. // make changes to the crt controller first
  1110.  
  1111. // set number of scanlines to 1
  1112.  
  1113. //outp(CRT_CONTROLLER,CRT_MAX_SCANLINE);
  1114. //data=inp(CRT_CONTROLLER+1);
  1115. //outp(CRT_CONTROLLER+1,RESET_BITS(data,0x0f));
  1116.  
  1117. // use byte addressing instead of word
  1118.  
  1119. outp(CRT_CONTROLLER,CRT_ADDR_MODE);
  1120. data=inp(CRT_CONTROLLER+1);
  1121. outp(CRT_CONTROLLER+1,RESET_BITS(data,0x40));
  1122.  
  1123. // second register that needs to reflect byte addressing
  1124.  
  1125. outp(CRT_CONTROLLER,CRT_MODE_CONTROL);
  1126. data=inp(CRT_CONTROLLER+1);
  1127. outp(CRT_CONTROLLER+1,SET_BITS(data,0x40));
  1128.  
  1129. // make changes to graphics controller
  1130.  
  1131. // set addressing to not use odd/even memory writes
  1132.  
  1133. outp(GFX_CONTROLLER,GFX_WRITE_MODE);
  1134. data=inp(GFX_CONTROLLER+1);
  1135. outp(GFX_CONTROLLER+1,RESET_BITS(data,0x10));
  1136.  
  1137. // don't chain the memory maps together
  1138.  
  1139. outp(GFX_CONTROLLER,GFX_MISC);
  1140. data=inp(GFX_CONTROLLER+1);
  1141. outp(GFX_CONTROLLER+1,RESET_BITS(data,0x02));
  1142.  
  1143. // make changes to sequencer
  1144.  
  1145. // again we must select no chaining and no odd/even memory addressing
  1146.  
  1147. outp(SEQUENCER,SEQ_MEMORY_MODE);
  1148. data =inp(SEQUENCER+1);
  1149. data = RESET_BITS(data,0x08);
  1150. data = SET_BITS(data,0x04);
  1151. outp(SEQUENCER+1,data);
  1152.  
  1153. // now clear the screen
  1154.  
  1155. outp(SEQUENCER,SEQ_PLANE_ENABLE);
  1156. outp(SEQUENCER+1,0x0f);
  1157.  
  1158. // clear the screen, remember it is 320x200, but that is divided into four
  1159. // planes, hence we need only to clear 16k out since there will be four planes
  1160. // each being cleared in parallel for a total of 4*16k or 64 = 320x200
  1161. // note: "k" in this example means 1000 not 1024
  1162.  
  1163. _asm   {
  1164.  
  1165.     les di,video_buffer   // point es:di to video buffer, same addre for mode Z
  1166.     xor ax,ax             // move a zero into al and ah
  1167.     mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  1168.     rep stosw             // move the color into the video buffer really fast!
  1169.  
  1170.     } // end inline asm
  1171.  
  1172. } // end Set_Mode_Y
  1173.  
  1174. void Set_Mode_X(void)
  1175. {
  1176. // this function will set the video mode to 320x400x256
  1177.  
  1178. unsigned char data,index,Vert_End;
  1179.  
  1180. // set system to mode 13h and use it as a foundation to base 320x400 mode on
  1181.  
  1182. _asm   {
  1183.     mov ax,0013h  // ah=function number 00(set graphics mode), al=13h
  1184.     int 10h       // video interrupt 10h
  1185.    } // end asm
  1186.  
  1187. // make changes to sequencer
  1188.  
  1189. // again we must select no chaining and no odd/even memory addressing
  1190.  
  1191. outp(SEQUENCER,SEQ_MEMORY_MODE);
  1192. outp(SEQUENCER+1,0x06);
  1193.  
  1194. // Preparing to reset Dot_Clock
  1195.  
  1196. outp(SEQUENCER,0);
  1197. outp(SEQUENCER+1,0x01);
  1198.  
  1199. outp(MISC_OUTPUT_REG,0xE3);
  1200.  
  1201. outp(SEQUENCER,0);
  1202. outp(SEQUENCER+1,0x03);
  1203.  
  1204. // remove write protect
  1205.  
  1206. outp(CRTC_INDEX_REG, VERT_RETRACE_END_INDEX);
  1207. Vert_End = inp(CRTC_INDEX_REG+1);
  1208. Vert_End &= 0x7F; // clear high bit
  1209. outp(CRTC_INDEX_REG+1, Vert_End);
  1210.  
  1211. // alter CRTC registers
  1212.  
  1213. outp(CRTC_INDEX_REG, VERT_TOTAL_INDEX);
  1214. outp(CRTC_INDEX_REG+1, 0x0D);
  1215.  
  1216. outp(CRTC_INDEX_REG, OVERFLOW_INDEX);
  1217. outp(CRTC_INDEX_REG+1, 0x3E);
  1218.  
  1219. outp(CRTC_INDEX_REG, MAX_SCAN_LINE_INDEX);
  1220. outp(CRTC_INDEX_REG+1, 0x41);
  1221.  
  1222. outp(CRTC_INDEX_REG, VERT_RETRACE_START_INDEX);
  1223. outp(CRTC_INDEX_REG+1, 0xEA);
  1224.  
  1225. outp(CRTC_INDEX_REG, VERT_RETRACE_END_INDEX);
  1226. outp(CRTC_INDEX_REG+1, 0xAC);
  1227.  
  1228. outp(CRTC_INDEX_REG, VERT_DISPLAY_END_INDEX);
  1229. outp(CRTC_INDEX_REG+1, 0xDF);
  1230.  
  1231. outp(CRTC_INDEX_REG, UNDERLINE_LOCATION_INDEX);
  1232. outp(CRTC_INDEX_REG+1, 0x00);
  1233.  
  1234. outp(CRTC_INDEX_REG, START_VERT_BLANK_INDEX);
  1235. outp(CRTC_INDEX_REG+1, 0xE7);
  1236.  
  1237. outp(CRTC_INDEX_REG, END_VERT_BLANK_INDEX);
  1238. outp(CRTC_INDEX_REG+1, 0x06);
  1239.  
  1240. outp(CRTC_INDEX_REG, MODE_CONTROL_INDEX);
  1241. outp(CRTC_INDEX_REG+1, 0xE3);
  1242.  
  1243. // now clear the screen
  1244.  
  1245. outp(SEQUENCER,SEQ_PLANE_ENABLE);
  1246. outp(SEQUENCER+1,0x0f);
  1247.  
  1248. // clear the screen, remember it is 320x200, but that is divided into four
  1249. // planes, hence we need only to clear 16k out since there will be four planes
  1250. // each being cleared in parallel for a total of 4*16k or 64 = 320x200
  1251. // note: "k" in this example means 1000 not 1024
  1252.  
  1253. _asm   {
  1254.  
  1255.     les di,video_buffer   // point es:di to video buffer, same addre for mode Z
  1256.     xor ax,ax             // move a zero into al and ah
  1257.     mov cx,320*200/8      // number of words to fill(using word is faster than bytes)
  1258.     rep stosw             // move the color into the video buffer really fast!
  1259.  
  1260.     } // end inline asm
  1261.  
  1262. } // end Set_Mode_Y
  1263.  
  1264. // The following functions are purely HIGH-JACKED CODE.
  1265.  
  1266. void Wait_Vertical_Retrace_End(void)
  1267. {
  1268.     unsigned char InputStatus1;
  1269.  
  1270.     /* make sure we aren't in display state (= not retrace) */
  1271.     do {
  1272.         InputStatus1 = inp(VGA_INPUT_STATUS_1);
  1273.     } while (!(InputStatus1 & VR_BIT));
  1274.  
  1275.     /* wait for retrace to end */
  1276.     do {
  1277.         InputStatus1 = inp(VGA_INPUT_STATUS_1);
  1278.     } while (InputStatus1 & VR_BIT);
  1279. }
  1280.  
  1281. /*
  1282.     Function: WaitDisplayMode
  1283.     Description:
  1284.         If the VGA is currently in display mode, the function returns
  1285.         immediately, else it waits until diplay mode is entered.
  1286. */
  1287. void Wait_Display_Mode(void)
  1288. {
  1289.     unsigned char InputStatus1;
  1290.  
  1291.     /* wait for retrace to end and display mode to start */
  1292.     do {
  1293.         InputStatus1 = inp(VGA_INPUT_STATUS_1);
  1294.     } while (InputStatus1 & DISPLAY_ENABLE);
  1295. }
  1296.  
  1297. /*
  1298.     Function: WaitRetraceMode
  1299.     Description:
  1300.         If the VGA is currently in retrace mode, the function returns
  1301.         immediately, else it waits until retrace mode is entered.
  1302. */
  1303. void Wait_Retrace_Mode(void)
  1304. {
  1305.     unsigned char InputStatus1;
  1306.  
  1307.     /* wait for display mode to end and retrace to start */
  1308.     do {
  1309.         InputStatus1 = inp(VGA_INPUT_STATUS_1);
  1310.     } while (!(InputStatus1 & VR_BIT));
  1311. }
  1312.  
  1313. /*
  1314.     Function: VerticalRetraceOccuring
  1315.     Description:
  1316.         Returns the current state of the VGA vertical retrace.  If
  1317.         retrace is occuring, the function returns TRUE.
  1318. */
  1319. int Vertical_Retrace_Occuring(void)
  1320. {
  1321.     return (inp(VGA_INPUT_STATUS_1) & VR_BIT) >> 3;
  1322. }
  1323.