home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / C / TGE129D / TGE.C < prev    next >
C/C++ Source or Header  |  1993-08-28  |  27KB  |  1,284 lines

  1. /*****************************************************************************
  2. *       The Graphics Engine version 1.29ßD                                   *
  3. *                                                                            *
  4. *       The Graphics Engine code and documentation are Copyright (c) 1993    *
  5. *       by Matthew Hildebrand.                                               *
  6. *                                                                            *
  7. *       Unauthorised usage or modification of any or all of The Graphics     *
  8. *       Engine is strictly prohibited.                                       *
  9. *****************************************************************************/
  10.  
  11. #include <alloc.h>
  12. #include <dos.h>
  13. #include <stdlib.h>
  14. #include "tge.h"
  15.  
  16. static unsigned char far* near inPixelAddr(int x, int y);
  17. static unsigned char far* near outPixelAddr(int x, int y);
  18. static void near set4Pixels(int x, int y, int xc, int yc, unsigned colour);
  19. static void near fill4Pixels(int x, int y, int xc, int yc, unsigned colour);
  20.  
  21.  
  22. /******
  23. ******* High-level routines to be used if they aren't in a driver.
  24. ******/
  25.  
  26.  
  27. /***
  28. **** deInitGraphics
  29. ***/
  30. void TGE_deInitGraphics(void)
  31. {
  32.   _AX = 0x0003;
  33.   geninterrupt(0x10);
  34. }
  35.  
  36.  
  37. /***
  38. **** setPaletteReg
  39. ***/
  40. void TGE_setPaletteReg(unsigned palReg, unsigned char red, unsigned char
  41.     blue, unsigned char green)
  42. {
  43.   unsigned char r, g, b;
  44.  
  45.   r = red >> 2;                /* translate 8-bit to 6-bit */
  46.   if ((red&3) >= 2)            /* round up if necessary */
  47.     r++;
  48.   if (r > 63)                /* ensure in range 0..63 */
  49.     r = 63;
  50.  
  51.   g = green >> 2;
  52.   if ((green&3) >= 2)
  53.     g++;
  54.   if (g > 63)
  55.     g = 63;
  56.  
  57.   b = blue >> 2;
  58.   if ((blue&3) >= 2)
  59.     b++;
  60.   if (b > 63)
  61.     b = 63;
  62.  
  63.   _AX = 0x1010;                /* set up registers */
  64.   _BX = palReg;
  65.   _DH = r;
  66.   _CH = g;
  67.   _CL = b;
  68.   geninterrupt(0x10);            /* call the video BIOS */
  69. }
  70.  
  71.  
  72. /***
  73. **** getPaletteReg
  74. ***/
  75. void TGE_getPaletteReg(unsigned palReg, unsigned char *red, unsigned char
  76.     *blue, unsigned char *green)
  77. {
  78.   unsigned char r, g, b;
  79.  
  80.   _AX = 0x1015;                /* set up registers */
  81.   _BX = palReg;
  82.   geninterrupt(0x10);            /* call the video BIOS */
  83.   r = _DH;
  84.   g = _CH;
  85.   b = _CL;
  86.  
  87.   *red = r << 2;            /* translate 6-bit to 8-bit */
  88.   *green = g << 2;            /* and store new values */
  89.   *blue = b << 2;
  90. }
  91.  
  92.  
  93. #ifdef __BORLANDC__
  94.   #pragma option -h
  95. #endif
  96.  
  97. /***
  98. **** setBlockPalette
  99. ***/
  100. void TGE_setBlockPalette(unsigned firstReg, unsigned lastReg, void far *data)
  101. {
  102.   register unsigned count;
  103.   unsigned char r, g, b;
  104.   unsigned char huge *p;
  105.  
  106.   p = (unsigned char*) data;        /* initialize pointer */
  107.  
  108.   for (count=firstReg; count<=lastReg; count++)    /* main loop */
  109.   {
  110.     r = *p >> 2;            /* translate 8-bit to 6-bit */
  111.     if ((*p&3) >= 2)            /* round up if necessary */
  112.       r++;
  113.     if (r > 63)                /* ensure in range 0..63 */
  114.       r = 63;
  115.     p++;                     /* update pointer */
  116.  
  117.     g = *p >> 2;
  118.     if ((*p&3) >= 2)
  119.       g++;
  120.     if (g > 63)
  121.       g = 63;
  122.     p++;
  123.  
  124.     b = *p >> 2;
  125.     if ((*p&3) >= 2)
  126.       b++;
  127.     if (b > 63)
  128.       b = 63;
  129.     p++;
  130.  
  131.     _AX = 0x1010;            /* set up registers */
  132.     _BX = count;
  133.     _DH = r;
  134.     _CH = g;
  135.     _CL = b;
  136.     geninterrupt(0x10);            /* call the video BIOS */
  137.   }
  138. }
  139.  
  140.  
  141. /***
  142. **** getBlockPalette
  143. ***/
  144. void TGE_getBlockPalette(unsigned firstReg, unsigned lastReg, void far *data)
  145. {
  146.   register unsigned count;
  147.   unsigned char r, g, b;
  148.   unsigned char huge *p;
  149.  
  150.   p = (unsigned char*) data;        /* initialize pointer */
  151.  
  152.   for (count=firstReg; count<=lastReg; count++)    /* main loop */
  153.   {
  154.     _AX = 0x1015;            /* set up registers */
  155.     _BX = count;
  156.     geninterrupt(0x10);            /* call the video BIOS */
  157.     r = _DH;
  158.     g = _CH;
  159.     b = _CL;
  160.  
  161.     *p = r << 2;            /* translate 6-bit to 8-bit */
  162.     p++;                /* and store values */
  163.     *p = g << 2;
  164.     p++;
  165.     *p = b << 2;
  166.     p++;
  167.   }
  168. }
  169.  
  170.  
  171. /***
  172. **** colourCloseTo
  173. ***/
  174. static unsigned char palette[768];
  175.  
  176. unsigned TGE_colourCloseTo(unsigned char red, unsigned char green, unsigned
  177.     char blue)
  178. {
  179.   register int count;
  180.   int redDif, greenDif, blueDif, curDif, bestDif=1000, curNet, bestNet=1000;
  181.   unsigned bestColour;
  182.  
  183.   TGEsys->_getBlockPalette(0, 255, palette);    /* get the palette */
  184.  
  185.   for (count=255; count>=0; count--)
  186.   {
  187.     redDif = red - palette[3*count];       /* calculate greatest difference */
  188.     greenDif = green - palette[3*count+1];
  189.     blueDif = blue - palette[3*count+2];
  190.     curNet = redDif + greenDif + blueDif;
  191.     if (redDif < 0)
  192.       redDif = -redDif;
  193.     if (greenDif < 0)
  194.       greenDif = -greenDif;
  195.     if (blueDif < 0)
  196.       blueDif = -blueDif;
  197.     curDif = max(max(redDif,greenDif), blueDif);
  198.  
  199.     if (!curDif)            /* if same colour, return */
  200.     {
  201.       bestColour = count;
  202.       break;
  203.     }
  204.     if (curDif < bestDif)        /* if better colour, set bestColour */
  205.     {
  206.       if (curNet <= bestNet)
  207.       {
  208.         bestDif = curDif;
  209.         bestColour = count;
  210.       }
  211.     }
  212.   }
  213.  
  214.   return (bestColour);
  215. }
  216.  
  217.  
  218. /***
  219. **** colourCloseToX
  220. ***/
  221. unsigned TGE_colourCloseToX(unsigned char red, unsigned char green, unsigned
  222.     char blue, unsigned colourExclude)
  223. {
  224.   register int count;
  225.   int redDif, greenDif, blueDif, curDif, bestDif=1000, curNet, bestNet=1000;
  226.   unsigned bestColour;
  227.  
  228.   TGEsys->_getBlockPalette(0, 255, palette);    /* get the palette */
  229.  
  230.   for (count=255; count>=0; count--)
  231.   {
  232.     if (count != colourExclude)
  233.     {
  234.       redDif = red - palette[3*count];  /* calculate greatest difference */
  235.       greenDif = green - palette[3*count+1];
  236.       blueDif = blue - palette[3*count+2];
  237.       curNet = redDif + greenDif + blueDif;
  238.       if (redDif < 0)
  239.     redDif = -redDif;
  240.       if (greenDif < 0)
  241.     greenDif = -greenDif;
  242.       if (blueDif < 0)
  243.     blueDif = -blueDif;
  244.       curDif = max(max(redDif,greenDif), blueDif);
  245.  
  246.       if (!curDif)            /* if same colour, return */
  247.       {
  248.     bestColour = count;
  249.     break;
  250.       }
  251.       if (curDif < bestDif)        /* if better colour, set bestColour */
  252.       {
  253.     if (curNet <= bestNet)
  254.     {
  255.       bestDif = curDif;
  256.       bestColour = count;
  257.     }
  258.       }
  259.     }
  260.   }
  261.  
  262.   return (bestColour);
  263. }
  264.  
  265.  
  266. /***
  267. **** imageSize
  268. ***/
  269. unsigned long TGE_imageSize(int ulx, int uly, int lrx, int lry)
  270. {
  271.   unsigned long size;
  272.   int temp;
  273.  
  274.   if (lrx < ulx)            /* swap coordinates if necessary */
  275.   {
  276.     temp = ulx;
  277.     lrx = ulx;
  278.     lrx = temp;
  279.   }
  280.   if (lry < uly)
  281.   {
  282.     temp = uly;
  283.     lry = uly;
  284.     lry = temp;
  285.   }
  286.  
  287.   if (ulx < VIEWPORTULX)        /* ensure coords are in bounds */
  288.     ulx = VIEWPORTULX;
  289.   else if (ulx > VIEWPORTLRX)
  290.     ulx = VIEWPORTLRX;
  291.  
  292.   if (uly < VIEWPORTULY)
  293.     uly = VIEWPORTULY;
  294.   else if (uly > VIEWPORTLRY)
  295.     uly = VIEWPORTLRY;
  296.  
  297.   if (lrx < VIEWPORTULX)
  298.     lrx = VIEWPORTULX;
  299.   else if (lrx > VIEWPORTLRX)
  300.     lrx = VIEWPORTLRX;
  301.  
  302.   if (lry < VIEWPORTULY)
  303.     lry = VIEWPORTULY;
  304.   else if (lry > VIEWPORTLRY)
  305.     lry = VIEWPORTLRY;
  306.  
  307.   size = (unsigned long)(lrx-ulx+1);
  308.   size *= (unsigned long)(lry-uly+1);
  309.  
  310.   return (size+4);            /* +4 for dimension information */
  311. }
  312.  
  313.  
  314. /***
  315. **** imageSizeDim
  316. ***/
  317. unsigned long TGE_imageSizeDim(unsigned wide, unsigned deep)
  318. {
  319.   unsigned long size;
  320.  
  321.   size = wide;
  322.   size *= deep;
  323.  
  324.   return (size+4);            /* +4 for dimension information */
  325. }
  326.  
  327.  
  328. #ifdef __BORLANDC__
  329.   #pragma option -h-
  330. #endif
  331.  
  332. /***
  333. **** putImage
  334. ***/
  335. void huge TGE_putImage(int x, int y, void far *image)
  336. {
  337.   register unsigned ycount;
  338.   int wide, deep;
  339.   register unsigned srcAdd = 0;
  340.   unsigned char huge *p = (unsigned char *)image;
  341.  
  342.   wide = ((unsigned*)image)[0];        /* get image dimensions */
  343.   deep = ((unsigned*)image)[1];
  344.   p += 4;                /* point to start of image data */
  345.  
  346.   if (y < VIEWPORTULY)            /* clip y coordinate */
  347.   {
  348.     if (y+deep >= VIEWPORTULY)
  349.     {
  350.       p += wide * abs(VIEWPORTULY-y);    /* skip any offscreen rows */
  351.       deep -= abs(VIEWPORTULY-y);    /* update image depth */
  352.       y = VIEWPORTULY;            /* new y coordinate */
  353.     }
  354.     else
  355.       return;
  356.   }
  357.   else if (y > VIEWPORTLRY)
  358.     return;
  359.   if (y+deep > VIEWPORTLRY)
  360.     deep = VIEWPORTLRY-y + 1;
  361.  
  362.   if (x < VIEWPORTULX)            /* clip x coordinate */
  363.   {
  364.     if (x+wide >= VIEWPORTULX)
  365.     {
  366.       srcAdd += abs(VIEWPORTULX-x);
  367.       p += abs(VIEWPORTULX-x);
  368.       wide -= abs(VIEWPORTULX-x);
  369.       x = VIEWPORTULX;
  370.     }
  371.     else
  372.       return;
  373.   }
  374.   else if (x > VIEWPORTLRX)
  375.     return;
  376.   if (x+wide > VIEWPORTLRX)
  377.   {
  378.     srcAdd += wide-1 - (VIEWPORTLRX-x);
  379.     wide = VIEWPORTLRX-x + 1;
  380.   }
  381.  
  382.   if (wide && deep)            /* quit if image is 0x0 pixels */
  383.   {
  384.     srcAdd += wide;
  385.     for (ycount=0; ycount<deep; ycount++)
  386.     {
  387.       TGEsys->_putLine(y+ycount, x, wide, (void*)p);
  388.       p += srcAdd;
  389.     }
  390.   }
  391. }
  392.  
  393.  
  394. /***
  395. **** putImageInv
  396. ***/
  397. void huge TGE_putImageInv(int x, int y, void far *image)
  398. {
  399.   register unsigned ycount;
  400.   int wide, deep;
  401.   register unsigned srcAdd = 0;
  402.   unsigned char huge *p = (unsigned char *)image;
  403.  
  404.   wide = ((unsigned*)image)[0];        /* get image dimensions */
  405.   deep = ((unsigned*)image)[1];
  406.   p += 4;                /* point to start of image data */
  407.  
  408.   if (y < OUTVIEWPORTULY)        /* clip y coordinate */
  409.   {
  410.     if (y+deep > OUTVIEWPORTULY)
  411.     {
  412.       p += wide * abs(OUTVIEWPORTULY-y);/* skip any offscreen rows */
  413.       deep -= abs(OUTVIEWPORTULY-y);    /* update image depth */
  414.       y = OUTVIEWPORTULY;        /* new y coordinate */
  415.     }
  416.     else
  417.       return;
  418.   }
  419.   else if (y > OUTVIEWPORTLRY)
  420.     return;
  421.   if (y+deep > OUTVIEWPORTLRY)
  422.     deep = OUTVIEWPORTLRY-y + 1;
  423.  
  424.   if (x < OUTVIEWPORTULX)        /* clip x coordinate */
  425.   {
  426.     if (x+wide > OUTVIEWPORTULX)
  427.     {
  428.       srcAdd += abs(OUTVIEWPORTULX-x);
  429.       p += abs(OUTVIEWPORTULX-x);
  430.       wide -= abs(OUTVIEWPORTULX-x);
  431.       x = OUTVIEWPORTULX;
  432.     }
  433.     else
  434.       return;
  435.   }
  436.   else if (x > OUTVIEWPORTLRX)
  437.     return;
  438.   if (x+wide > OUTVIEWPORTLRX)
  439.   {
  440.     srcAdd += wide-1 - (OUTVIEWPORTLRX-x);
  441.     wide = OUTVIEWPORTLRX-x + 1;
  442.   }
  443.  
  444.   if (wide && deep)               /* quit if offscreen */
  445.   {
  446.     srcAdd += wide;
  447.     for (ycount=0; ycount<deep; ycount++)
  448.     {
  449.       TGEsys->_putLineInv(y+ycount, x, wide, (void*)p);
  450.       p += srcAdd;
  451.     }
  452.   }
  453. }
  454.  
  455.  
  456. /***
  457. **** getImage
  458. ***/
  459. void huge TGE_getImage(int ulx, int uly, int lrx, int lry, void far *image)
  460. {
  461.   register int ycount, wide, deep;
  462.   int temp;
  463.   unsigned char huge *p = (unsigned char*)image;
  464.  
  465.   if (lrx < ulx)            /* swap coordinates if necessary */
  466.   {
  467.     temp = ulx;
  468.     lrx = ulx;
  469.     lrx = temp;
  470.   }
  471.   if (lry < uly)
  472.   {
  473.     temp = uly;
  474.     lry = uly;
  475.     lry = temp;
  476.   }
  477.  
  478.   if (ulx < INVIEWPORTULX)        /* ensure coords are in bounds */
  479.     ulx = INVIEWPORTULX;
  480.   else if (ulx > INVIEWPORTLRX)
  481.     ulx = INVIEWPORTLRX;
  482.  
  483.   if (uly < INVIEWPORTULY)
  484.     uly = INVIEWPORTULY;
  485.   else if (uly > INVIEWPORTLRY)
  486.     uly = INVIEWPORTLRY;
  487.  
  488.   if (lrx < INVIEWPORTULX)
  489.     lrx = INVIEWPORTULX;
  490.   else if (lrx > INVIEWPORTLRX)
  491.     lrx = INVIEWPORTLRX;
  492.  
  493.   if (lry < INVIEWPORTULY)
  494.     lry = INVIEWPORTULY;
  495.   else if (lry > INVIEWPORTLRY)
  496.     lry = INVIEWPORTLRY;
  497.  
  498.   ((unsigned *)image)[0] = wide = lrx-ulx+1;
  499.   ((unsigned *)image)[1] = deep = lry-uly+1;
  500.   p += 4;
  501.  
  502.   if (wide>0 && deep>0)
  503.   {
  504.     for (ycount=uly; ycount<=lry; ycount++)
  505.     {
  506.       TGEsys->_getLine(ycount, ulx, wide, (void*)p);
  507.       p += wide;
  508.     }
  509.   }
  510. }
  511.  
  512.  
  513. /***
  514. **** putLine
  515. ***/
  516. void TGE_putLine(int lineNum, int xOff, int lineLen, void far *buf)
  517. {
  518.   register unsigned count, y;
  519.  
  520.   for (count=0,y=lineNum; count<lineLen; count++)    /* draw the line */
  521.     TGEsys->_putPixel(xOff+count, y, *((unsigned char huge*)buf+count));
  522. }
  523.  
  524.  
  525. /***
  526. **** putLineInv
  527. ***/
  528. void TGE_putLineInv(int lineNum, int xOff, int lineLen, void far *buf)
  529. {
  530.   register unsigned count, y;
  531.   unsigned char huge *p = (unsigned char huge*) buf;
  532.  
  533.   for (count=0,y=lineNum; count<lineLen; count++)    /* draw the line */
  534.   {
  535.     if (*p)
  536.       TGEsys->_putPixel(xOff+count, y, *p);
  537.     p++;
  538.   }
  539. }
  540.  
  541.  
  542. /***
  543. **** getLine
  544. ***/
  545. void TGE_getLine(int lineNum, int xOff, int lineLen, void far *buf)
  546. {
  547.   register unsigned count, y;
  548.  
  549.   for (count=0,y=lineNum; count<lineLen; count++)          /* draw the line */
  550.     *((unsigned char huge*)buf+count) = TGEsys->_getPixel(xOff+count, y);
  551. }
  552.  
  553.  
  554. /***
  555. **** putPixel
  556. ***/
  557. void TGE_putPixel_scr_copy(int x, int y, unsigned colour)
  558. {
  559.   _AH = 0x0C;
  560.   _AL = (unsigned char)colour;
  561.   _BH = 0;
  562.   _CX = x;
  563.   _DX = y;
  564.   geninterrupt(0x10);
  565. }
  566.  
  567. void TGE_putPixel_scr_and(int x, int y, unsigned colour)
  568. {
  569.   _AH = 0x0D;                /* get the pixel */
  570.   _BH = 0;
  571.   _CX = x;
  572.   _DX = y;
  573.   geninterrupt(0x10);
  574.  
  575.   _AH = 0x0C;                /* set the ANDed pixel */
  576.   _AL &= (unsigned char)colour;
  577.   _BH = 0;
  578.   _CX = x;
  579.   _DX = y;
  580.   geninterrupt(0x10);
  581. }
  582.  
  583. void TGE_putPixel_scr_not(int x, int y, unsigned colour)
  584. {
  585.   _AH = 0x0C;                /* set the NOTed pixel */
  586.   _AL = ~(unsigned char)colour;
  587.   _BH = 0;
  588.   _CX = x;
  589.   _DX = y;
  590.   geninterrupt(0x10);
  591. }
  592.  
  593. void TGE_putPixel_scr_or(int x, int y, unsigned colour)
  594. {
  595.   _AH = 0x0D;                /* get the pixel */
  596.   _BH = 0;
  597.   _CX = x;
  598.   _DX = y;
  599.   geninterrupt(0x10);
  600.  
  601.   _AH = 0x0C;                /* set the ORed pixel */
  602.   _AL |= (unsigned char)colour;
  603.   _BH = 0;
  604.   _CX = x;
  605.   _DX = y;
  606.   geninterrupt(0x10);
  607. }
  608.  
  609. void TGE_putPixel_scr_xor(int x, int y, unsigned colour)
  610. {
  611.   _AH = 0x0D;                /* get the pixel */
  612.   _BH = 0;
  613.   _CX = x;
  614.   _DX = y;
  615.   geninterrupt(0x10);
  616.  
  617.   _AH = 0x0C;                /* set the XORed pixel */
  618.   _AL ^= (unsigned char)colour;
  619.   _BH = 0;
  620.   _CX = x;
  621.   _DX = y;
  622.   geninterrupt(0x10);
  623. }
  624.  
  625. void TGE_putPixel_mem_copy(int x, int y, unsigned colour)
  626. {
  627.   *(outPixelAddr(x,y)) = (unsigned char)colour;     /* write the pixel */
  628. }
  629.  
  630. void TGE_putPixel_mem_and(int x, int y, unsigned colour)
  631. {
  632.   *(outPixelAddr(x,y)) &= (unsigned char)colour; /* write the pixel */
  633. }
  634.  
  635. void TGE_putPixel_mem_not(int x, int y, unsigned colour)
  636. {
  637.   *(outPixelAddr(x,y)) = ~(unsigned char)colour; /* write the pixel */
  638. }
  639.  
  640. void TGE_putPixel_mem_or(int x, int y, unsigned colour)
  641. {
  642.   *(outPixelAddr(x,y)) |= (unsigned char)colour; /* write the pixel */
  643. }
  644.  
  645. void TGE_putPixel_mem_xor(int x, int y, unsigned colour)
  646. {
  647.   *(outPixelAddr(x,y)) ^= (unsigned char)colour; /* write the pixel */
  648. }
  649.  
  650.  
  651. /***
  652. **** getPixel
  653. ***/
  654. unsigned TGE_getPixel_scr(int x, int y)
  655. {
  656.   _AH = 0x0D;
  657.   _BH = 0;
  658.   _CX = x;
  659.   _DX = y;
  660.   geninterrupt(0x10);
  661.  
  662.   _AH = 0;
  663.   return (_AX);
  664. }
  665.  
  666. unsigned TGE_getPixel_mem(int x, int y)
  667. {
  668.   return ((unsigned) *(inPixelAddr(x,y)));
  669. }
  670.  
  671.  
  672. /***
  673. **** line
  674. ***/
  675. void TGE_line(int x1, int y1, int x2, int y2, unsigned colour)
  676. {
  677.   register int t, distance;
  678.   int xerr=0, yerr=0, deltax, deltay;
  679.   int incx, incy;
  680.  
  681.   deltax = x2 - x1;            /* compute both distances */
  682.   deltay = y2 - y1;
  683.  
  684.   if (deltax > 0)            /* compute increments */
  685.     incx = 1;
  686.   else if (deltax == 0)
  687.     incx = 0;
  688.   else
  689.     incx = -1;
  690.  
  691.   if (deltay > 0)
  692.     incy = 1;
  693.   else if (deltay == 0)
  694.     incy = 0;
  695.   else
  696.     incy = -1;
  697.  
  698.   deltax = abs(deltax);            /* determine greater distance */
  699.   deltay = abs(deltay);
  700.   if (deltax > deltay)
  701.     distance = deltax;
  702.   else
  703.     distance = deltay;
  704.  
  705.   for (t=0; t<=distance+1; t++)        /* draw the line */
  706.   {
  707.     TGEsys->_putPixel(x1, y1, colour);
  708.     xerr += deltax;
  709.     yerr += deltay;
  710.     if (xerr > distance)
  711.     {
  712.       xerr -= distance;
  713.       x1 += incx;
  714.     }
  715.     if (yerr > distance)
  716.     {
  717.       yerr -= distance;
  718.       y1 += incy;
  719.     }
  720.   }
  721. }
  722.  
  723.  
  724. /***
  725. **** horizLine
  726. ***/
  727. void TGE_horizLine(int y, int x1, int x2, unsigned colour)
  728. {
  729.   register unsigned count, max;
  730.  
  731.   for (count=x1,max=x2; count<=max; count++)    /* draw the line */
  732.     TGEsys->_putPixel(count, y, colour);
  733. }
  734.  
  735.  
  736. /***
  737. **** vertLine
  738. ***/
  739. void TGE_vertLine(int x, int y1, int y2, unsigned colour)
  740. {
  741.   register unsigned count, max;
  742.  
  743.   for (count=y1,max=y2; count<=max; count++)    /* draw the line */
  744.     TGEsys->_putPixel(x, count, colour);
  745. }
  746.  
  747.  
  748. /***
  749. **** drawRect
  750. ***/
  751. void TGE_drawRect(int ulx, int uly, int lrx, int lry, unsigned colour)
  752. {
  753.   register int ulxTemp, lrxTemp, temp;
  754.  
  755.   if (ulx > lrx)            /* swap coords if necessary */
  756.   {
  757.     temp = ulx;
  758.     ulx = lrx;
  759.     lrx = temp;
  760.   }
  761.   if (uly > lry)
  762.   {
  763.     temp = uly;
  764.     uly = lry;
  765.     lry = temp;
  766.   }
  767.  
  768.   if (ulx<=VIEWPORTLRX && uly<=VIEWPORTLRY && lrx>=VIEWPORTULX &&
  769.     lry>=VIEWPORTULY)
  770.   {
  771.     ulxTemp = ulx+1>=VIEWPORTULX ? ulx+1 : VIEWPORTULX;
  772.     lrxTemp = lrx-1<=VIEWPORTLRX ? lrx-1 : VIEWPORTLRX;
  773.  
  774.     /* Draw horizontal lines if necessary */
  775.     if (lrxTemp-ulxTemp > 1)
  776.     {
  777.       if (uly >= VIEWPORTULY)
  778.     TGEsys->_horizLine(uly, ulxTemp, lrxTemp, colour);    /* top */
  779.       if (lry <= VIEWPORTLRY)
  780.     TGEsys->_horizLine(lry, ulxTemp, lrxTemp, colour);    /* bottom */
  781.     }
  782.  
  783.     /* Clip y coordinates */
  784.     if (uly < VIEWPORTULY)
  785.       uly = VIEWPORTULY;
  786.     if (lry > VIEWPORTLRY)
  787.       lry = VIEWPORTLRY;
  788.  
  789.     /* Draw vertical lines if necessary */
  790.     if (ulx >= VIEWPORTULX)
  791.       TGEsys->_vertLine(ulx, uly, lry, colour);            /* left */
  792.     if (lrx <= VIEWPORTLRX)
  793.       TGEsys->_vertLine(lrx, uly, lry, colour);            /* right */
  794.   }
  795. }
  796.  
  797.  
  798. /***
  799. **** filledRect
  800. ***/
  801. void TGE_filledRect(int ulx, int uly, int lrx, int lry, unsigned
  802.     colour)
  803. {
  804.   register unsigned count, max;
  805.   int temp;
  806.  
  807.   if (ulx > lrx)            /* swap coords if necessary */
  808.   {
  809.     temp = ulx;
  810.     ulx = lrx;
  811.     lrx = temp;
  812.   }
  813.   if (uly > lry)
  814.   {
  815.     temp = uly;
  816.     uly = lry;
  817.     lry = temp;
  818.   }
  819.  
  820.   max = lry;
  821.   for (count=uly; count<=max; count++)
  822.     TGEsys->_fillLine(count, ulx, lrx, colour);
  823. }
  824.  
  825.  
  826. /***
  827. **** clearGraphics
  828. ***/
  829. void TGE_clearGraphics(unsigned colour)
  830. {
  831.   TGEsys->_filledRect(0, 0, MAXX, MAXY, colour);
  832. }
  833.  
  834.  
  835. /***
  836. **** ellipse
  837. ***/
  838. void TGE_ellipse(int xc, int yc, int wide, int deep, unsigned colour)
  839. {
  840.   int x, y;
  841.   long a, b;
  842.   long Asquared, TwoAsquared;
  843.   long Bsquared, TwoBsquared;
  844.   long d, dx, dy;
  845.  
  846.   wide /= 2;
  847.   deep /= 2;
  848.  
  849.   x = 0;                /* initialize variables */
  850.   y = deep;
  851.   a = wide;
  852.   b = deep;
  853.   Asquared = a * a;
  854.   TwoAsquared = 2 * Asquared;
  855.   Bsquared = b * b;
  856.   TwoBsquared = 2 * Bsquared;
  857.  
  858.   d = Bsquared - Asquared*b + Asquared/4L;
  859.   dx = 0;
  860.   dy = TwoAsquared * b;
  861.  
  862.   while (dx < dy)
  863.   {
  864.     set4Pixels(x, y, xc, yc, colour);
  865.  
  866.     if (d > 0L)
  867.     {
  868.       y--;
  869.       dy -= TwoAsquared;
  870.       d -= dy;
  871.     }
  872.  
  873.     x++;
  874.     dx += TwoBsquared;
  875.     d += Bsquared + dx;
  876.   }
  877.  
  878.   d += (3L*(Asquared-Bsquared)/2L - (dx+dy)) / 2L;
  879.  
  880.   while (y >= 0)
  881.   {
  882.     set4Pixels(x, y, xc, yc, colour);
  883.  
  884.     if (d < 0L)
  885.     {
  886.       x++;
  887.       dx += TwoBsquared;
  888.       d += dx;
  889.     }
  890.  
  891.     y--;
  892.     dy -= TwoAsquared;
  893.     d += Asquared - dy;
  894.   }
  895. }
  896.  
  897. void near set4Pixels(int x, int y, int xc, int yc, unsigned colour)
  898. {
  899.   register int xCoord, yCoord;
  900.  
  901.   xCoord = xc + x;
  902.   yCoord = yc + y;
  903.   if (TGE_clipPoint(xCoord, yCoord))
  904.     TGEsys->_putPixel(xCoord, yCoord, colour);
  905.  
  906.   xCoord = xc - x;
  907.   if (TGE_clipPoint(xCoord, yCoord))
  908.     TGEsys->_putPixel(xCoord, yCoord, colour);
  909.  
  910.   xCoord = xc + x;
  911.   yCoord = yc - y;
  912.   if (TGE_clipPoint(xCoord, yCoord))
  913.     TGEsys->_putPixel(xCoord, yCoord, colour);
  914.  
  915.   xCoord = xc - x;
  916.   if (TGE_clipPoint(xCoord, yCoord))
  917.     TGEsys->_putPixel(xCoord, yCoord, colour);
  918. }
  919.  
  920.  
  921. /***
  922. **** filledEllipse
  923. ***/
  924. void TGE_filledEllipse(int xc, int yc, int wide, int deep, unsigned colour)
  925. {
  926.   int x, y;
  927.   long a, b;
  928.   long Asquared, TwoAsquared;
  929.   long Bsquared, TwoBsquared;
  930.   long d, dx, dy;
  931.  
  932.   wide /= 2;
  933.   deep /= 2;
  934.  
  935.   x = 0;                /* initialize variables */
  936.   y = deep;
  937.   a = wide;
  938.   b = deep;
  939.   Asquared = a * a;
  940.   TwoAsquared = 2 * Asquared;
  941.   Bsquared = b * b;
  942.   TwoBsquared = 2 * Bsquared;
  943.  
  944.   d = Bsquared - Asquared*b + Asquared/4L;
  945.   dx = 0;
  946.   dy = TwoAsquared * b;
  947.  
  948.   while (dx < dy)
  949.   {
  950.     fill4Pixels(x, y, xc, yc, colour);
  951.  
  952.     if (d > 0L)
  953.     {
  954.       y--;
  955.       dy -= TwoAsquared;
  956.       d -= dy;
  957.     }
  958.  
  959.     x++;
  960.     dx += TwoBsquared;
  961.     d += Bsquared + dx;
  962.   }
  963.  
  964.   d += (3L*(Asquared-Bsquared)/2L - (dx+dy)) / 2L;
  965.  
  966.   while (y >= 0)
  967.   {
  968.     fill4Pixels(x, y, xc, yc, colour);
  969.  
  970.     if (d < 0L)
  971.     {
  972.       x++;
  973.       dx += TwoBsquared;
  974.       d += dx;
  975.     }
  976.  
  977.     y--;
  978.     dy -= TwoAsquared;
  979.     d += Asquared - dy;
  980.   }
  981. }
  982.  
  983. void near fill4Pixels(int x, int y, int xc, int yc, unsigned colour)
  984. {
  985.   register int xCoord1, xCoord2, yCoord;
  986.   int temp;
  987.  
  988.   xCoord1 = xc - x;
  989.   xCoord2 = xc + x;
  990.  
  991.   if (xCoord1>VIEWPORTLRX || xCoord2<VIEWPORTULX)
  992.     return;
  993.  
  994.   if (xCoord1 > xCoord2)        /* ensure xCoord1 <= xCoord2 */
  995.   {
  996.     temp = xCoord1;
  997.     xCoord1 = xCoord2;
  998.     xCoord2 = temp;
  999.   }
  1000.  
  1001.   yCoord = yc - y;
  1002.   if (yCoord>=VIEWPORTULY && yCoord<=VIEWPORTLRY)
  1003.   {
  1004.     if (xCoord1 < VIEWPORTULX)        /* clip xCoord1 horizontally */
  1005.       xCoord1 = VIEWPORTULX;
  1006.     else if (xCoord1 > VIEWPORTLRX)
  1007.       xCoord1 = VIEWPORTLRX;
  1008.     if (xCoord2 < VIEWPORTULX)        /* clip xCoord2 horizontally */
  1009.       xCoord2 = VIEWPORTULX;
  1010.     else if (xCoord2 > VIEWPORTLRX)
  1011.       xCoord2 = VIEWPORTLRX;
  1012.     TGEsys->_fillLine(yCoord, xCoord1, xCoord2, colour);
  1013.   }
  1014.  
  1015.   yCoord = yc + y;
  1016.   if (yCoord>=VIEWPORTULY && yCoord<=VIEWPORTLRY)
  1017.   {
  1018.     if (xCoord1 < VIEWPORTULX)        /* clip xCoord1 horizontally */
  1019.       xCoord1 = VIEWPORTULX;
  1020.     else if (xCoord1 > VIEWPORTLRX)
  1021.       xCoord1 = VIEWPORTLRX;
  1022.     if (xCoord2 < VIEWPORTULX)        /* clip xCoord2 horizontally */
  1023.       xCoord2 = VIEWPORTULX;
  1024.     else if (xCoord2 > VIEWPORTLRX)
  1025.       xCoord2 = VIEWPORTLRX;
  1026.     TGEsys->_fillLine(yCoord, xCoord1, xCoord2, colour);
  1027.   }
  1028. }
  1029.  
  1030.  
  1031. /***
  1032. **** circle
  1033. ***/
  1034. void TGE_circle(int x, int y, int radius, unsigned colour)
  1035. {
  1036.   TGEsys->_ellipse(x, y, 2*radius, (2*radius*(4*YRATIO))/(3*XRATIO), colour);
  1037. }
  1038.  
  1039.  
  1040. /***
  1041. **** filledCircle
  1042. ***/
  1043. void TGE_filledCircle(int x, int y, int radius, unsigned colour)
  1044. {
  1045.   TGEsys->_filledEllipse(x, y, 2*radius, (2*radius*(4*YRATIO))/(3*XRATIO), colour);
  1046. }
  1047.  
  1048.  
  1049. /***
  1050. **** fillRegion
  1051. ***/
  1052. static struct params {
  1053.   int x, y;
  1054. };
  1055. static unsigned regionColour, fillColour;
  1056. static int okToPush;
  1057. static struct params huge *stack;
  1058. static unsigned long stackSize, stackPtr;
  1059.  
  1060. void TGE_fillRegion(int seedX, int seedY, unsigned colour)
  1061. {
  1062.   struct params holder;
  1063.   register int x, v;
  1064.   int xl, xr, y;
  1065.  
  1066.   if (!TGE_clipPoint(seedX, seedY))        /* abort if seed point */
  1067.     return;                    /* is outside viewport */
  1068.  
  1069.   regionColour = TGEsys->_getPixel(seedX, seedY); /* initialize variables */
  1070.   if (regionColour == colour)
  1071.     return;
  1072.   fillColour = colour;
  1073.  
  1074.   stackSize = farcoreleft();            /* grab a very large */
  1075.   (void*)stack = farmalloc(stackSize);        /*  stack buffer     */
  1076.   stackSize /= sizeof(struct params);
  1077.   stackPtr = 0;
  1078.  
  1079.   okToPush = 1;
  1080.   holder.x = seedX;            /* push initial parameters */
  1081.   holder.y = seedY;
  1082.   stack[stackPtr] = holder;
  1083.   stackPtr++;
  1084.  
  1085.   while (stackPtr && stackPtr<=stackSize)    /* main loop */
  1086.   {
  1087.     stackPtr--;
  1088.     holder = stack[stackPtr];
  1089.  
  1090.     xl = xr = holder.x;
  1091.     y = holder.y;
  1092.  
  1093.     x = xl;                    /* scan left */
  1094.     if (x > VIEWPORTULX)
  1095.     {
  1096.       do
  1097.       {
  1098.     x--;
  1099.     v = TGEsys->_getPixel(x, y);
  1100.       }
  1101.       while ((v==regionColour) && (v!=fillColour) && (x>=VIEWPORTULX));
  1102.       x++;
  1103.       xl = x;
  1104.     }
  1105.  
  1106.     x = xr;                    /* scan right */
  1107.     if (x <= VIEWPORTLRX)
  1108.     {
  1109.       do
  1110.       {
  1111.     x++;
  1112.     v = TGEsys->_getPixel(x, y);
  1113.       }
  1114.       while ((v==regionColour) && (v!=fillColour) && (x<=VIEWPORTLRX));
  1115.       x--;
  1116.       xr = x;
  1117.     }
  1118.  
  1119.     TGEsys->_fillLine(y, xl, xr, fillColour);    /* fill the line */
  1120.  
  1121.     /* scan upwards */
  1122.     if (y > VIEWPORTULY)
  1123.     {
  1124.       for (x=xl; x<=xr; x++)
  1125.       {
  1126.     v = TGEsys->_getPixel(x, y-1);
  1127.     if (v==regionColour && okToPush)
  1128.     {
  1129.       holder.x = x;
  1130.       holder.y = y-1;
  1131.       stack[stackPtr] = holder;
  1132.       stackPtr++;
  1133.       if (stackPtr != stackSize)
  1134.       {
  1135.         do
  1136.         {
  1137.           x++;
  1138.           v = TGEsys->_getPixel(x, y-1);
  1139.         }
  1140.         while (v==regionColour && x<=xr);
  1141.         x--;
  1142.       }
  1143.       else
  1144.         okToPush = 0;
  1145.     }
  1146.       }
  1147.     }
  1148.  
  1149.     /* scan downwards */
  1150.     if (y < VIEWPORTLRY)
  1151.     {
  1152.       for (x=xl; x<=xr; x++)
  1153.       {
  1154.     v = TGEsys->_getPixel(x, y+1);
  1155.     if (v==regionColour && okToPush)
  1156.     {
  1157.       holder.x = x;
  1158.       holder.y = y+1;
  1159.       stack[stackPtr] = holder;
  1160.       stackPtr++;
  1161.       if (stackPtr != stackSize)
  1162.       {
  1163.         do
  1164.         {
  1165.           x++;
  1166.           v = TGEsys->_getPixel(x, y+1);
  1167.         }
  1168.         while (v==regionColour && x<=xr);
  1169.         x--;
  1170.       }
  1171.       else
  1172.         okToPush = 0;
  1173.     }
  1174.       }
  1175.     }
  1176.   };
  1177.  
  1178.   farfree((void far*)stack);            /* release stack memory */
  1179. }
  1180.  
  1181.  
  1182. /*****
  1183. ****** Viewport routines
  1184. *****/
  1185.  
  1186. void TGE_setViewports(int ulx, int uly, int lrx, int lry)
  1187. {
  1188.   disable();
  1189.   OUTVIEWPORTULX = ulx;                /* set values */
  1190.   INVIEWPORTULX  = ulx;
  1191.   OUTVIEWPORTULY = uly;
  1192.   INVIEWPORTULY  = uly;
  1193.   OUTVIEWPORTLRX = lrx;
  1194.   INVIEWPORTLRX  = lrx;
  1195.   OUTVIEWPORTLRY = lry;
  1196.   INVIEWPORTLRY  = lry;
  1197.   enable();
  1198. }
  1199.  
  1200. void TGE_setOutputViewport(int ulx, int uly, int lrx, int lry)
  1201. {
  1202.   disable();
  1203.   OUTVIEWPORTULX = ulx;                /* set values */
  1204.   OUTVIEWPORTULY = uly;
  1205.   OUTVIEWPORTLRX = lrx;
  1206.   OUTVIEWPORTLRY = lry;
  1207.   enable();
  1208. }
  1209.  
  1210. void TGE_setInputViewport(int ulx, int uly, int lrx, int lry)
  1211. {
  1212.   disable();
  1213.   INVIEWPORTULX = ulx;                /* set values */
  1214.   INVIEWPORTULY = uly;
  1215.   INVIEWPORTLRX = lrx;
  1216.   INVIEWPORTLRY = lry;
  1217.   enable();
  1218. }
  1219.  
  1220. void TGE_getOutputViewport(int far *ulx, int far *uly, int far *lrx, int far *lry)
  1221. {
  1222.   disable();
  1223.   *ulx = OUTVIEWPORTULX;            /* get values */
  1224.   *uly = OUTVIEWPORTULY;
  1225.   *lrx = OUTVIEWPORTLRX;
  1226.   *lry = OUTVIEWPORTLRY;
  1227.   enable();
  1228. }
  1229.  
  1230. void TGE_getInputViewport(int far *ulx, int far *uly, int far *lrx, int far *lry)
  1231. {
  1232.   disable();
  1233.   *ulx = INVIEWPORTULX;                /* get values */
  1234.   *uly = INVIEWPORTULY;
  1235.   *lrx = INVIEWPORTLRX;
  1236.   *lry = INVIEWPORTLRY;
  1237.   enable();
  1238. }
  1239.  
  1240.  
  1241. /*****
  1242. ****** Calculate the address of a pixel in a virtual screen.
  1243. *****/
  1244.  
  1245. unsigned char far* near outPixelAddr(int x, int y)
  1246. {
  1247.   unsigned char huge *p;
  1248.   unsigned long offset;
  1249.  
  1250.   (void far*) p = TGEsys->outAddr;    /* calculate pixel address */
  1251.   offset = y;
  1252.   offset *= TGEsys->outScreenWide;
  1253.   offset += x;
  1254.  
  1255.   while (offset > 0xFFFF)        /* add 'offset' to address */
  1256.   {
  1257.     p += 0xFFFF;
  1258.     offset -= 0xFFFF;
  1259.   }
  1260.   p += (unsigned)offset;
  1261.  
  1262.   return ((unsigned char far*) p);    /* return the address */
  1263. }
  1264.  
  1265. unsigned char far* near inPixelAddr(int x, int y)
  1266. {
  1267.   unsigned char huge *p;
  1268.   unsigned long offset;
  1269.  
  1270.   (void far*) p = TGEsys->inAddr;    /* calculate pixel address */
  1271.   offset = y;
  1272.   offset *= TGEsys->inScreenWide;
  1273.   offset += x;
  1274.  
  1275.   while (offset > 0xFFFF)        /* add 'offset' to address */
  1276.   {
  1277.     p += 0xFFFF;
  1278.     offset -= 0xFFFF;
  1279.   }
  1280.   p += (unsigned)offset;
  1281.  
  1282.   return ((unsigned char far*) p);    /* return the address */
  1283. }
  1284.