home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 099 / TGE101.ZIP / TGE.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  16KB  |  664 lines

  1. /*****************************************************************************
  2. *    The Graphics Engine v1.01                         *
  3. *                                         *
  4. *    All program code and documentation associated with The Graphics         *
  5. *    Engine is Copyright (c) 1993 by Matthew Hildebrand.             *
  6. *                                         *
  7. *    Unauthorised usage or modification of any or all of The Graphics     *
  8. *    Engine is strictly prohibited.                              *
  9. *****************************************************************************/
  10.  
  11. /* This notice may NOT be removed and MUST remain intact */
  12. static char copyright[] = "The Graphics Engine -- Copyright (c) 1993 by Matthew Hildebrand";
  13.  
  14.  
  15. /* Guess what... this file must be compiled with the large or huge model. */
  16.  
  17. #ifdef __TINY__
  18. #error This module MUST be compiled with the large or huge model.
  19. #endif
  20. #ifdef __SMALL__
  21. #error This module MUST be compiled with the large or huge model.
  22. #endif
  23. #ifdef M_I86SM
  24. #error This module MUST be compiled with the large or huge model.
  25. #endif
  26. #ifdef __MEDIUM__
  27. #error This module MUST be compiled with the large or huge model.
  28. #endif
  29. #ifdef M_I86MM
  30. #error This module MUST be compiled with the large or huge model.
  31. #endif
  32. #ifdef __COMPACT__
  33. #error This module MUST be compiled with the large or huge model.
  34. #endif
  35. #ifdef M_I86CM
  36. #error This module MUST be compiled with the large or huge model.
  37. #endif
  38.  
  39.  
  40. #include <alloc.h>
  41. #include <dos.h>
  42. #include <math.h>
  43. #include <mem.h>
  44. #include <stdio.h>
  45. #include "tge.h"
  46.  
  47. #define MAXX    (_grSystemDrv->maxx)
  48. #define MAXY    (_grSystemDrv->maxy)
  49.  
  50. static void *forceOffset(void far *p);
  51. static void setupInfo(struct GraphDrv far *grDrv);
  52. static void huge GE_deInitGraphics(void);
  53. static void huge GE_putImage(int x, int y, void far *image);
  54. static void huge GE_putImageInv(int x, int y, void far *image);
  55. static void huge GE_getImage(int ulx, int uly, int lrx, int lry, void far
  56.     *image);
  57. static void huge GE_putLine(int lineNum, int xOff, int lineLen, void far *buf);
  58. static void huge GE_getLine(int lineNum, int xOff, int lineLen, void far *buf);
  59. static unsigned long huge GE_imageSize(int ulx, int uly, int lrx, int lry);
  60. static void huge GE_putPixel(int x, int y, unsigned colour);
  61. static unsigned huge GE_getPixel(int x, int y);
  62. static void huge GE_line(int x1, int y1, int x2, int y2, unsigned colour);
  63. static void huge GE_horizLine(int y, int x1, int x2, unsigned colour);
  64. static void huge GE_drawRect(int ulx, int uly, int lrx, int lry, unsigned
  65.     colour);
  66. static void huge GE_filledRect(int ulx, int uly, int lrx, int lry, unsigned
  67.     colour);
  68. static void huge GE_setPaletteReg(unsigned palReg, unsigned char red,
  69.     unsigned char blue, unsigned char green);
  70. static void huge GE_getPaletteReg(unsigned palReg, unsigned char *red,
  71.     unsigned char *blue, unsigned char *green);
  72. static void huge GE_setBlockPalette(unsigned firstReg, unsigned numRegs,
  73.     void far *data);
  74. static void huge GE_getBlockPalette(unsigned firstReg, unsigned numRegs,
  75.     void far *data);
  76. static void huge GE_clearGraphics(unsigned colour);
  77.  
  78. static struct GraphDrv far *drvAddr = NULL;
  79. struct GraphDrv far *_grSystemDrv = NULL;
  80.  
  81.  
  82. /******
  83. ******* Routines to load a graphics driver from disk.
  84. ******/
  85.  
  86. /* Call this function to load a driver */
  87. int loadGraphDriver(char *filename)
  88. {
  89.   struct GraphDrv far *grDrv = NULL;
  90.   FILE *fp;
  91.   long l;
  92.   char signature[4];
  93.  
  94.   if ((fp=fopen(filename,"rb")) != NULL) {
  95.     fseek(fp, 0L, SEEK_END);
  96.     l = ftell(fp);
  97.     rewind(fp);
  98.  
  99.     fread(signature, 1, 4, fp);
  100.     if (!memcmp(signature, "GRAP", 4))
  101.     {
  102.       l -= 4;
  103.       if (l < 0xFFFFl && (grDrv=(struct GraphDrv far *)farmalloc(l+15)) != NULL)
  104.       {
  105.         drvAddr = grDrv;
  106.     (void *)grDrv = forceOffset(drvAddr);    /* force to XXXX:0004 */
  107.         _grSystemDrv = grDrv;
  108.  
  109.     /* initialize the function pointers */
  110.     if (fread(grDrv, 1, (unsigned)l, fp) == (unsigned)l)
  111.         {
  112.           setupInfo(grDrv);
  113.         }
  114.         else
  115.         {
  116.           farfree(grDrv);
  117.           drvAddr = _grSystemDrv = grDrv = NULL;
  118.         }
  119.       }
  120.     }
  121.     fclose(fp);
  122.   }
  123.   return (grDrv ? 1 : 0);
  124. }
  125.  
  126. /* Force a pointer to the form XXXX:0004 */
  127. static void *forceOffset(void far *p)
  128. {
  129.   void huge *temp = (void huge *)p;
  130.  
  131.   if (FP_OFF(temp) == 4)
  132.     return ((void far *)temp);
  133.   else if (FP_OFF(temp) > 4)
  134.     return (MK_FP(FP_SEG(temp)+1, 4));
  135.   else
  136.     return (MK_FP(FP_SEG(temp), 4));
  137. }
  138.  
  139. /* Set up function pointers once a driver has been loaded */
  140. static void setupInfo(struct GraphDrv far *grDrv)
  141. {
  142.   register unsigned seg = FP_SEG(grDrv);
  143.  
  144.   /* initGraphics must always be present */
  145.   (void *)grDrv->_initGraphics = MK_FP(seg, FP_OFF(grDrv->_initGraphics));
  146.  
  147.   /* These functions are optional; fill in the default ones if the
  148.      driver doesn't contain them.  It's tedious, but somebody has
  149.      to do it... */
  150.   if (FP_OFF(grDrv->_deInitGraphics))    /* deInitGraphics */
  151.     (void *)grDrv->_deInitGraphics = MK_FP(seg, FP_OFF(grDrv->_deInitGraphics));
  152.   else
  153.     grDrv->_deInitGraphics = GE_deInitGraphics;
  154.  
  155.   if (FP_OFF(grDrv->_putImage))        /* putImage */
  156.     (void *)grDrv->_putImage = MK_FP(seg, FP_OFF(grDrv->_putImage));
  157.   else
  158.     grDrv->_putImage = GE_putImage;
  159.  
  160.   if (FP_OFF(grDrv->_putImageInv))    /* putImageInv */
  161.     (void *)grDrv->_putImageInv = MK_FP(seg, FP_OFF(grDrv->_putImageInv));
  162.   else
  163.     grDrv->_putImageInv = GE_putImageInv;
  164.  
  165.   if (FP_OFF(grDrv->_getImage))        /* getImage */
  166.     (void *)grDrv->_getImage = MK_FP(seg, FP_OFF(grDrv->_getImage));
  167.   else
  168.     grDrv->_getImage = GE_getImage;
  169.  
  170.   if (FP_OFF(grDrv->_putLine))        /* putLine */
  171.     (void *)grDrv->_putLine = MK_FP(seg, FP_OFF(grDrv->_putLine));
  172.   else
  173.     grDrv->_putLine = GE_putLine;
  174.  
  175.   if (FP_OFF(grDrv->_getLine))        /* getLine */
  176.     (void *)grDrv->_getLine = MK_FP(seg, FP_OFF(grDrv->_getLine));
  177.   else
  178.     grDrv->_getLine = GE_getLine;
  179.  
  180.   if (FP_OFF(grDrv->_imageSize))    /* imageSize */
  181.     (void *)grDrv->_imageSize = MK_FP(seg, FP_OFF(grDrv->_imageSize));
  182.   else
  183.     grDrv->_imageSize = GE_imageSize;
  184.  
  185.   if (FP_OFF(grDrv->_putPixel))        /* putPixel */
  186.     (void *)grDrv->_putPixel = MK_FP(seg, FP_OFF(grDrv->_putPixel));
  187.   else
  188.     grDrv->_putPixel = GE_putPixel;
  189.  
  190.   if (FP_OFF(grDrv->_getPixel))        /* getPixel */
  191.     (void *)grDrv->_getPixel = MK_FP(seg, FP_OFF(grDrv->_getPixel));
  192.   else
  193.     grDrv->_getPixel = GE_getPixel;
  194.  
  195.   if (FP_OFF(grDrv->_line))        /* line */
  196.     (void *)grDrv->_line = MK_FP(seg, FP_OFF(grDrv->_line));
  197.   else
  198.     grDrv->_line = GE_line;
  199.  
  200.   if (FP_OFF(grDrv->_horizLine))    /* horizLine */
  201.     (void *)grDrv->_horizLine = MK_FP(seg, FP_OFF(grDrv->_horizLine));
  202.   else
  203.     grDrv->_horizLine = GE_horizLine;
  204.  
  205.   if (FP_OFF(grDrv->_drawRect))        /* drawRect */
  206.     (void *)grDrv->_drawRect = MK_FP(seg, FP_OFF(grDrv->_drawRect));
  207.   else
  208.     grDrv->_drawRect = GE_drawRect;
  209.  
  210.   if (FP_OFF(grDrv->_filledRect))    /* filledRect */
  211.     (void *)grDrv->_filledRect = MK_FP(seg, FP_OFF(grDrv->_filledRect));
  212.   else
  213.     grDrv->_filledRect = GE_filledRect;
  214.  
  215.   if (FP_OFF(grDrv->_setPaletteReg))    /* setPaletteReg */
  216.     (void *)grDrv->_setPaletteReg = MK_FP(seg, FP_OFF(grDrv->_setPaletteReg));
  217.   else
  218.     grDrv->_setPaletteReg = GE_setPaletteReg;
  219.  
  220.   if (FP_OFF(grDrv->_getPaletteReg))    /* getPaletteReg */
  221.     (void *)grDrv->_getPaletteReg = MK_FP(seg, FP_OFF(grDrv->_getPaletteReg));
  222.   else
  223.     grDrv->_getPaletteReg = GE_getPaletteReg;
  224.  
  225.   if (FP_OFF(grDrv->_setBlockPalette))    /* setBlockPalette */
  226.     (void *)grDrv->_setBlockPalette = MK_FP(seg, FP_OFF(grDrv->_setBlockPalette));
  227.   else
  228.     grDrv->_setBlockPalette = GE_setBlockPalette;
  229.  
  230.   if (FP_OFF(grDrv->_getBlockPalette))    /* getBlockPalette */
  231.     (void *)grDrv->_getBlockPalette = MK_FP(seg, FP_OFF(grDrv->_getBlockPalette));
  232.   else
  233.     grDrv->_getBlockPalette = GE_getBlockPalette;
  234.  
  235.   if (FP_OFF(grDrv->_clearGraphics))    /* clearGraphics */
  236.     (void *)grDrv->_clearGraphics = MK_FP(seg, FP_OFF(grDrv->_clearGraphics));
  237.   else
  238.     grDrv->_clearGraphics = GE_clearGraphics;
  239. }
  240.  
  241. /******
  242. ******* Free graphics driver memory
  243. ******/
  244.  
  245. void unloadGraphDriver(void)
  246. {
  247.   if (drvAddr)
  248.     farfree(drvAddr);
  249. }
  250.  
  251. /******
  252. ******* High-level driver routines to be used if they aren't in a driver
  253. ******/
  254.  
  255. static void huge GE_deInitGraphics(void)
  256. {
  257.   _AX = 0x0003;
  258.   geninterrupt(0x10);
  259. }
  260.  
  261. static void huge GE_putImage(int x, int y, void far *image)
  262. {
  263.   register unsigned ycount;
  264.   unsigned wide, deep;
  265.   register unsigned sadd = 0;
  266.   unsigned char huge *p = (unsigned char *)image;
  267.  
  268.   wide = *(unsigned *)image;
  269.   deep = *((unsigned *)image+1);
  270.   p += 4;
  271.  
  272.   if (y < 0)                /* clip y coordinate */
  273.   {
  274.     if (y+deep)
  275.     {
  276.       p += wide * abs(y);
  277.       deep -= abs(y);
  278.       y = 0;
  279.     }
  280.     else
  281.       return;
  282.   }
  283.   else if (y > MAXY)
  284.     return;
  285.   else if (y+deep > MAXY)
  286.     deep = MAXY-y+1;
  287.  
  288.   if (x < 0)                /* clip x coordinate */
  289.   {
  290.     if (x+wide)
  291.     {
  292.       sadd += abs(x);
  293.       p += abs(x);
  294.       wide -= abs(x);
  295.       x = 0;
  296.     }
  297.     else
  298.       return;
  299.   }
  300.   else if (x > MAXX)
  301.     return;
  302.   else if (x+wide > MAXX)
  303.   {
  304.     sadd += wide-1 - (MAXX-x);
  305.     wide = MAXX-x+1;
  306.   }
  307.  
  308.   sadd += wide;
  309.   for (ycount=0; ycount<deep; ycount++)
  310.   {
  311.     putLine(y+ycount, x, wide, (void *)p);
  312.     p += sadd;
  313.   }
  314. }
  315.  
  316. static void huge GE_putImageInv(int x, int y, void far *image)
  317. {
  318.   register unsigned xcount, ycount;
  319.   unsigned wide, deep;
  320.   register unsigned sadd = 0;
  321.   unsigned char huge *p = (unsigned char *)image;
  322.  
  323.   wide = *(unsigned *)image;
  324.   deep = *((unsigned *)image+1);
  325.   p += 4;
  326.  
  327.   if (y < 0)                /* clip y coordinate */
  328.   {
  329.     if (y+deep)
  330.     {
  331.       p += wide * abs(y);
  332.       deep -= abs(y);
  333.       y = 0;
  334.     }
  335.     else
  336.       return;
  337.   }
  338.   else if (y > MAXY)
  339.     return;
  340.   else if (y+deep > MAXY)
  341.     deep = MAXY-y+1;
  342.  
  343.   if (x < 0)                /* clip x coordinate */
  344.   {
  345.     if (x+wide)
  346.     {
  347.       sadd += abs(x);
  348.       p += abs(x);
  349.       wide -= abs(x);
  350.       x = 0;
  351.     }
  352.     else
  353.       return;
  354.   }
  355.   else if (x > MAXX)
  356.     return;
  357.   else if (x+wide > MAXX)
  358.   {
  359.     sadd += wide-1 - (MAXX-x);
  360.     wide = MAXX-x+1;
  361.   }
  362.  
  363.   for (ycount=0; ycount<deep; ycount++)
  364.   {
  365.     for (xcount=0; xcount<wide; xcount++)
  366.     {
  367.       if (*p)
  368.         putPixel(x+xcount, y+ycount, *p);
  369.       p++;
  370.     }
  371.     p += sadd;
  372.   }
  373. }
  374.  
  375. static void huge GE_getImage(int ulx, int uly, int lrx, int lry, void far
  376.     *image)
  377. {
  378.   register unsigned ycount, wide;
  379.   int temp;
  380.   unsigned char huge *p = (unsigned char *)image;
  381.  
  382.   if (lrx < ulx)            /* swap coordinates if necessary */
  383.   {
  384.     temp = ulx;
  385.     lrx = ulx;
  386.     lrx = temp;
  387.   }
  388.   if (lry < uly)
  389.   {
  390.     temp = uly;
  391.     lry = uly;
  392.     lry = temp;
  393.   }
  394.  
  395.   if (ulx < 0)                /* ensure coords are in bounds */
  396.     ulx = 0;
  397.   else if (ulx > MAXX)
  398.     ulx = MAXX;
  399.  
  400.   if (uly < 0)
  401.     uly = 0;
  402.   else if (uly > MAXY)
  403.     uly = MAXY;
  404.  
  405.   if (lrx < 0)
  406.     lrx = 0;
  407.   else if (lrx > MAXX)
  408.     lrx = MAXX;
  409.  
  410.   if (lry < 0)
  411.     lry = 0;
  412.   else if (lry > MAXY)
  413.     lry = MAXY;
  414.  
  415.   *(unsigned *)image = lrx-ulx+1;
  416.   *((unsigned *)image+1) = lry-uly+1;
  417.   p += 4;
  418.  
  419.   wide = lrx-ulx+1;
  420.   for (ycount=uly; ycount<=lry; ycount++)
  421.   {
  422.     getLine(ycount, ulx, wide, (void *)p);
  423.     p += wide;
  424.   }
  425. }
  426.  
  427. static void huge GE_putLine(int lineNum, int xOff, int lineLen, void far *buf)
  428. {
  429.   register unsigned count, y;
  430.  
  431.   for (count=0,y=lineNum; count<lineLen; count++)
  432.     putPixel(xOff+count, y, *((unsigned char huge *)buf+count));
  433. }
  434.  
  435. static void huge GE_getLine(int lineNum, int xOff, int lineLen, void far *buf)
  436. {
  437.   register unsigned count, y;
  438.  
  439.   for (count=0,y=lineNum; count<lineLen; count++)
  440.     *((unsigned char huge *)buf+count) = getPixel(xOff+count, y);
  441. }
  442.  
  443. static unsigned long huge GE_imageSize(int ulx, int uly, int lrx, int lry)
  444. {
  445.   unsigned long size;
  446.   int temp;
  447.  
  448.   if (lrx < ulx)            /* swap coordinates if necessary */
  449.   {
  450.     temp = ulx;
  451.     lrx = ulx;
  452.     lrx = temp;
  453.   }
  454.   if (lry < uly)
  455.   {
  456.     temp = uly;
  457.     lry = uly;
  458.     lry = temp;
  459.   }
  460.  
  461.   if (ulx < 0)                /* ensure coords are in bounds */
  462.     ulx = 0;
  463.   else if (ulx > MAXX)
  464.     ulx = MAXX;
  465.  
  466.   if (uly < 0)
  467.     uly = 0;
  468.   else if (uly > MAXY)
  469.     uly = MAXY;
  470.  
  471.   if (lrx < 0)
  472.     lrx = 0;
  473.   else if (lrx > MAXX)
  474.     lrx = MAXX;
  475.  
  476.   if (lry < 0)
  477.     lry = 0;
  478.   else if (lry > MAXY)
  479.     lry = MAXY;
  480.  
  481.   size = (unsigned long)(lrx-ulx+1);
  482.   size *= (unsigned long)(lry-uly+1);
  483.  
  484.   return (size+4);            /* +4 for dimension information */
  485. }
  486.  
  487. static void huge GE_putPixel(int x, int y, unsigned colour)
  488. {
  489.   _AH = 0x0C;
  490.   _AL = (unsigned char)colour;
  491.   _BH = 0;
  492.   _CX = x;
  493.   _DX = y;
  494.   geninterrupt(0x10);
  495. }
  496.  
  497. static unsigned huge GE_getPixel(int x, int y)
  498. {
  499.   _AH = 0x0D;
  500.   _BH = 0;
  501.   _CX = x;
  502.   _DX = y;
  503.   geninterrupt(0x10);
  504.  
  505.   _AH = 0;
  506.   return (_AX);
  507. }
  508.  
  509. static void huge GE_line(int x1, int y1, int x2, int y2, unsigned colour)
  510. {
  511.   register int t, distance;
  512.   int xerr=0, yerr=0, deltax, deltay;
  513.   int incx, incy;
  514.  
  515.   deltax = x2 - x1;            /* compute both distances */
  516.   deltay = y2 - y1;
  517.  
  518.   if (deltax > 0)            /* compute increments */
  519.     incx = 1;
  520.   else if (deltax == 0)
  521.     incx = 0;
  522.   else
  523.     incx = -1;
  524.  
  525.   if (deltay > 0)
  526.     incy = 1;
  527.   else if (deltay == 0)
  528.     incy = 0;
  529.   else
  530.     incy = -1;
  531.  
  532.   deltax = abs(deltax);            /* determine greater distance */
  533.   deltay = abs(deltay);
  534.   if (deltax > deltay)
  535.     distance = deltax;
  536.   else
  537.     distance = deltay;
  538.  
  539.   for (t=0; t<=distance+1; t++)        /* draw the line */
  540.   {
  541.     putPixel(x1, y1, colour);
  542.     xerr += deltax;
  543.     yerr += deltay;
  544.     if (xerr > distance)
  545.     {
  546.       xerr -= distance;
  547.       x1 += incx;
  548.     }
  549.     if (yerr > distance)
  550.     {
  551.       yerr -= distance;
  552.       y1 += incy;
  553.     }
  554.   }
  555. }
  556.  
  557. static void huge GE_horizLine(int y, int x1, int x2, unsigned colour)
  558. {
  559.   register unsigned count, max;
  560.  
  561.   max = x2;
  562.   for (count=x1; count<=max; count++)
  563.     putPixel(count, y, colour);
  564. }
  565.  
  566. static void huge GE_drawRect(int ulx, int uly, int lrx, int lry, unsigned
  567.     colour)
  568. {
  569.   register int t;
  570.  
  571.   if (ulx > lrx)            /* swap coords if necessary */
  572.   {
  573.     t = ulx;
  574.     ulx = lrx;
  575.     lrx = t;
  576.   }
  577.   if (uly > lry)
  578.   {
  579.     t = uly;
  580.     uly = lry;
  581.     lry = t;
  582.   }
  583.  
  584.   horizLine(uly, ulx, lrx, colour);    /* top */
  585.   horizLine(lry, ulx, lrx, colour);    /* bottom */
  586.   line(ulx, uly, ulx, lry, colour);    /* left */
  587.   line(lrx, uly, lrx, lry, colour);    /* bottom */
  588. }
  589.  
  590. static void huge GE_filledRect(int ulx, int uly, int lrx, int lry, unsigned
  591.     colour)
  592. {
  593.   register unsigned count, max;
  594.   int t;
  595.  
  596.   if (ulx > lrx)            /* swap coords if necessary */
  597.   {
  598.     t = ulx;
  599.     ulx = lrx;
  600.     lrx = t;
  601.   }
  602.   if (uly > lry)
  603.   {
  604.     t = uly;
  605.     uly = lry;
  606.     lry = t;
  607.   }
  608.  
  609.   max = lry;
  610.   for (count=uly; count<=max; count++)
  611.     horizLine(count, ulx, lrx, colour);
  612. }
  613.  
  614. static void huge GE_setPaletteReg(unsigned palReg, unsigned char red, unsigned
  615.     char blue, unsigned char green)
  616. {
  617.   _AX = 0x1010;
  618.   _BX = palReg;
  619.   _DH = red;
  620.   _CH = green;
  621.   _CL = blue;
  622.   geninterrupt(0x10);
  623. }
  624.  
  625. static void huge GE_getPaletteReg(unsigned palReg, unsigned char *red, unsigned
  626.     char *blue, unsigned char *green)
  627. {
  628.   _AX = 0x1015;
  629.   _BX = palReg;
  630.   geninterrupt(0x10);
  631.   *red = _DH;
  632.   *green = _CH;
  633.   *blue = _CL;
  634. }
  635.  
  636. static void huge GE_setBlockPalette(unsigned firstReg, unsigned numRegs, void
  637.     far *data)
  638. {
  639.   _ES = FP_SEG(data);
  640.   _DX = FP_OFF(data);
  641.   _AX = 0x1012;
  642.   _BX = firstReg;
  643.   _CX = numRegs;
  644.   geninterrupt(0x10);
  645. }
  646.  
  647. static void huge GE_getBlockPalette(unsigned firstReg, unsigned numRegs, void
  648.     far *data)
  649. {
  650.   _ES = FP_SEG(data);
  651.   _DX = FP_OFF(data);
  652.   _AX = 0x1017;
  653.   _BX = firstReg;
  654.   _CX = numRegs;
  655.   geninterrupt(0x10);
  656. }
  657.  
  658. static void huge GE_clearGraphics(unsigned colour)
  659. {
  660.   register unsigned count;
  661.  
  662.   for (count=0; count<=MAXY; count++)
  663.     horizLine(count, 0, MAXX, colour);
  664. }