home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / microcrn / issue_51.arc / ZG_LWLVL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-13  |  19.6 KB  |  751 lines

  1. /*  This code supports an article in issue #51 of:
  2.  
  3.     Micro Cornucopia Magazine
  4.     P.O. Box 223
  5.     Bend, OR 97709
  6. */
  7. /*
  8.     Module:     ZG_LwLvl    (ZipGraph Low-Level functions)
  9.     Version     1.00        22-Oct-1989
  10.  
  11.     Language:   ANSI C w/MS-DOS extensions
  12.     Environ:    IBM-PC compatibles w/MDA, CGA, HGC, EGA, MCGA, or VGA
  13.  
  14.     Compilers:  Borland Turbo C v2.00
  15.                 Lattice C v6.01
  16.                 Microsoft C v5.10 and QuickC v2.01
  17.                 Zortech C & C++ v2.01
  18.  
  19.     Purpose:    Provides low-level graphics routines for detecting graphics
  20.                 adapters, setting graphics modes, and plotting pixels. This
  21.                 module is required by the higher-level ZipGraph modules.
  22.  
  23.     Written by: Scott Robert Ladd
  24.                 705 West Virginia
  25.                 Gunnison CO 81230
  26.  
  27.                 MCI:     srl
  28.                 FidoNet: 1:104/708
  29. */
  30.  
  31. #define __ZG_LWLVL_C 1
  32.  
  33. #if !defined(LATTICE)
  34.     #include "conio.h"
  35. #endif
  36.  
  37. #include "dos.h"
  38. #include "zg_lwlvl.h"
  39.  
  40. /*-----------------------------
  41.   handle compiler differences
  42. -----------------------------*/
  43.  
  44. #if defined(_MSC) || defined(_QC) || defined(__ZTC__) || defined(LATTICE)
  45.     #define OUT_PORT(port,val) outp(port,val)
  46. #elif defined(__TURBOC__)
  47.     #define OUT_PORT(port,val) outportb(port,val)
  48. #endif
  49.  
  50. #if !defined(MK_FP)
  51.     #define MK_FP(seg,off) ((void far *)(((long)(seg) << 16L) | (long)(off)))
  52. #endif
  53.  
  54. /*------------------------------
  55.   ZipGraph INTERNAL PROTOTYPES
  56. ------------------------------*/
  57.  
  58. static void DummyPlot(int x, int y, int color, int mode);
  59. static int  DummyRead(int x, int y);
  60.  
  61. static void CGA1_Plot(int x, int y, int color, int mode);
  62. static void CGA2_Plot(int x, int y, int color, int mode);
  63. static void M256_Plot(int x, int y, int color, int mode);
  64. static void EVGA_Plot(int x, int y, int color, int mode);
  65.  
  66. static int  CGA1_Read(int x, int y);
  67. static int  CGA2_Read(int x, int y);
  68. static int  M256_Read(int x, int y);
  69. static int  EVGA_Read(int x, int y);
  70.  
  71. static void HGC_GraphMode(void);
  72. static void HGC_TextMode(void);
  73. static void HGC_Plot(int x, int y, int color, int mode);
  74. static int  HGC_Read(int x, int y);
  75.  
  76. /*---------------------------
  77.   ZipGraph PUBLIC VARIABLES
  78. ---------------------------*/
  79.  
  80. struct
  81.     {
  82.     int     Type;
  83.     int     Monitor;
  84.     int     Mode;
  85.  
  86.     int     Xwidth;
  87.     int     Ylength;
  88.     int     NoColors;
  89.     }
  90.     ZG_VideoInfo;
  91.  
  92. void (* ZG_PlotPixel)(int x, int y, int color, int mode) = DummyPlot;
  93. int  (* ZG_ReadPixel)(int x, int y) = DummyRead;
  94.  
  95. /*----------------------------------------
  96.   ZipGraph INTERNAL TABLES and VARIABLES
  97. ----------------------------------------*/
  98.  
  99. static const struct
  100.     {
  101.     int BestRes;
  102.     int MostColor;
  103.  
  104.     unsigned long ModeList;
  105.     }
  106.     VideoTable[06] =
  107.         {
  108.         { 0,                 0,                  0x00000000L},
  109.         { ZG_MOD_640x200x2,  ZG_MOD_320x200x4,   0x00000006L},
  110.         { ZG_MOD_720x348x1,  ZG_MOD_720x348x1,   0x00000001L},
  111.         { ZG_MOD_640x350x16, ZG_MOD_640x350x16,  0x0000007EL},
  112.         { ZG_MOD_640x480x2,  ZG_MOD_320x200x256, 0x00000486L},
  113.         { ZG_MOD_640x480x16, ZG_MOD_320x200x256, 0x000003FEL}
  114.         };
  115.  
  116. static const struct
  117.     {
  118.     char ActualMode;
  119.     void (* PixelProc)(int x, int y, int color, int mode);
  120.     int  (* ReadProc)(int x, int y);
  121.     int Xwidth;
  122.     int Ylength;
  123.     int NoColors;
  124.     }
  125.     ModeData[10] =
  126.         {
  127.         { 0x00, HGC_Plot,  HGC_Read,  720, 348, 1  },
  128.         { 0x04, CGA2_Plot, CGA2_Read, 320, 200, 4  },
  129.         { 0x06, CGA1_Plot, CGA1_Read, 640, 200, 2  },
  130.         { 0x0D, EVGA_Plot, EVGA_Read, 320, 200, 16 },
  131.         { 0x0E, EVGA_Plot, EVGA_Read, 640, 200, 16 },
  132.         { 0x0F, EVGA_Plot, EVGA_Read, 640, 350, 2  },
  133.         { 0x10, EVGA_Plot, EVGA_Read, 640, 350, 16 },
  134.         { 0x11, EVGA_Plot, EVGA_Read, 640, 480, 2  },
  135.         { 0x12, EVGA_Plot, EVGA_Read, 640, 480, 16 },
  136.         { 0x13, M256_Plot, M256_Read, 320, 200, 256}
  137.         };
  138.  
  139. static unsigned char OriginalMode;
  140.  
  141. /*------------------------------
  142.   IBM-type adapter global data
  143. ------------------------------*/
  144.  
  145. static const unsigned int CGA_VID_SEG  = 0xB800;
  146. static const unsigned int EVGA_VID_SEG = 0xA000;
  147.  
  148. /*-------------------------
  149.   MDA and HGC global data
  150. -------------------------*/
  151.  
  152. /* Hercules video RAM segment */
  153. static const unsigned int HGC_VID_SEG  = 0xB000;
  154.  
  155. /* Monochrome 6845 Video Controller ports */
  156. static const unsigned int HGC_IDX_PORT = 0x03B4;
  157. static const unsigned int HGC_DAT_PORT = 0x03B5;
  158. static const unsigned int HGC_CTL_PORT = 0x03B8;
  159. static const unsigned int HGC_CFG_PORT = 0x03BF;
  160.  
  161. /*----------------------------
  162.   ZipGraph PUBLIC FUNCTIONS!
  163. ----------------------------*/
  164.  
  165. int ZG_Init(void)
  166.     {
  167.     union REGS regs;
  168.     int i, status_changed;
  169.     unsigned char orig_status;
  170.  
  171.     ZG_VideoInfo.Type    = ZG_ERROR;
  172.     ZG_VideoInfo.Monitor = ZG_ERROR;
  173.     ZG_VideoInfo.Mode    = ZG_ERROR;
  174.  
  175.     ZG_VideoInfo.Xwidth   = 0;
  176.     ZG_VideoInfo.Ylength  = 0;
  177.     ZG_VideoInfo.NoColors = 0;
  178.  
  179.     regs.h.ah = 0x1A; /* VGA Identifier Adapter Service */
  180.     regs.h.al = 0;
  181.     int86(0x10,®s,®s);
  182.  
  183.     if (regs.h.al == 0x1A)
  184.         {
  185.         switch (regs.h.bl)
  186.             {
  187.             case 1 : ZG_VideoInfo.Type    = ZG_VID_MDA;
  188.                      ZG_VideoInfo.Monitor = ZG_MTR_MONO;
  189.                      break;
  190.  
  191.             case 2 : ZG_VideoInfo.Type    = ZG_VID_CGA;
  192.                      ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
  193.                      break;
  194.  
  195.             case 4 : ZG_VideoInfo.Type    = ZG_VID_EGA;
  196.                      ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
  197.                      break;
  198.  
  199.             case 5 : ZG_VideoInfo.Type    = ZG_VID_EGA;
  200.                      ZG_VideoInfo.Monitor = ZG_MTR_MONO;
  201.                      break;
  202.  
  203.             case 7 : ZG_VideoInfo.Type    = ZG_VID_VGA;
  204.                      ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
  205.                      break;
  206.  
  207.             case 8 : ZG_VideoInfo.Type    = ZG_VID_VGA;
  208.                      ZG_VideoInfo.Monitor = ZG_MTR_MONO;
  209.                      break;
  210.  
  211.             case 10: ZG_VideoInfo.Type    = ZG_VID_MCGA;
  212.                      ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
  213.                      break;
  214.  
  215.             case 11: ZG_VideoInfo.Type    = ZG_VID_MCGA;
  216.                      ZG_VideoInfo.Monitor = ZG_MTR_MONO;
  217.                      break;
  218.  
  219.             case 12: ZG_VideoInfo.Type    = ZG_VID_MCGA;
  220.                      ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
  221.                      break;
  222.  
  223.             default:
  224.                      return 1;
  225.             }
  226.         }
  227.     else
  228.         {
  229.         /* check for an EGA */
  230.         regs.h.ah = 0x12;
  231.         regs.x.bx = 0x0010;
  232.         int86(0x10,®s,®s);
  233.  
  234.         if (regs.x.bx != 0x10)
  235.             {
  236.             ZG_VideoInfo.Type = ZG_VID_EGA;
  237.  
  238.             regs.h.ah = 0x12;
  239.             regs.x.bx = 0x0010;
  240.             int86(0x10,®s,®s);
  241.  
  242.             if (regs.h.bh == 0)
  243.                 ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
  244.             else
  245.                 ZG_VideoInfo.Monitor = ZG_MTR_MONO;
  246.             }
  247.         else
  248.             {
  249.             int86(0x11,®s,®s);
  250.  
  251.             switch ((regs.h.al & 0x30) >> 4)
  252.                 {
  253.                 case 0 :
  254.                     return 1;
  255.  
  256.                 case 1 :
  257.                 case 2 :
  258.                     ZG_VideoInfo.Type    = ZG_VID_CGA;
  259.                     ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
  260.                     break;
  261.  
  262.                 case 3 :
  263.                     status_changed = 0;
  264.  
  265.                     orig_status = (unsigned char)(inp(0xBA) & 0x80);
  266.  
  267.                     for (i = 0; (i < 30000) && (!status_changed); ++i)
  268.                         if (orig_status != (unsigned char)(inp(0xBA) & 0x80))
  269.                             status_changed = 1;
  270.  
  271.                     if (status_changed)
  272.                         ZG_VideoInfo.Type = ZG_VID_HGC;
  273.                     else
  274.                         ZG_VideoInfo.Type = ZG_VID_MDA;
  275.  
  276.                     ZG_VideoInfo.Monitor  = ZG_MTR_MONO;
  277.                 }
  278.             }
  279.         }
  280.  
  281.     if (ZG_VideoInfo.Type != ZG_VID_HGC)
  282.         {
  283.         regs.h.ah = 0x0F;
  284.         int86(0x10,®s,®s);
  285.         OriginalMode = regs.h.al;
  286.         }
  287.  
  288.     return 0;
  289.     }
  290.  
  291. int ZG_SetMode(int VideoMode)
  292.     {
  293.     union REGS regs;
  294.  
  295.     if (VideoMode < 0)
  296.         return 1;
  297.  
  298.     if (VideoMode == 0x80)
  299.         VideoMode = VideoTable[ZG_VideoInfo.Type].BestRes;
  300.     else
  301.         if (VideoMode == 0x81)
  302.             VideoMode = VideoTable[ZG_VideoInfo.Type].MostColor;
  303.  
  304.     if ((VideoMode > 9)
  305.     || (!(VideoTable[ZG_VideoInfo.Type].ModeList & (1 << VideoMode))))
  306.         return 1;
  307.  
  308.     ZG_PlotPixel = ModeData[VideoMode].PixelProc;
  309.     ZG_ReadPixel = ModeData[VideoMode].ReadProc;
  310.  
  311.     if (VideoMode == ZG_MOD_720x348x1)
  312.         HGC_GraphMode();
  313.     else
  314.         {
  315.         regs.h.ah = 0;
  316.         regs.h.al = ModeData[VideoMode].ActualMode;
  317.         int86(0x10,®s,®s);
  318.         }
  319.  
  320.     ZG_VideoInfo.Mode     = VideoMode;
  321.     ZG_VideoInfo.Xwidth   = ModeData[VideoMode].Xwidth;
  322.     ZG_VideoInfo.Ylength  = ModeData[VideoMode].Ylength;
  323.     ZG_VideoInfo.NoColors = ModeData[VideoMode].NoColors;
  324.  
  325.     return 0;
  326.     }
  327.  
  328. int ZG_Done(void)
  329.     {
  330.     union REGS regs;
  331.  
  332.     if (ZG_VideoInfo.Type == ZG_VID_HGC)
  333.         HGC_TextMode();
  334.     else
  335.         {
  336.         regs.h.ah = 0;
  337.         regs.h.al = OriginalMode;
  338.         int86(0x10,®s,®s);
  339.         }
  340.  
  341.     return 0;
  342.     }
  343.  
  344. int ZG_SetCGAPalette(char PaletteNo)
  345.     {
  346.     union REGS regs;
  347.  
  348.     if (ZG_VideoInfo.Type != ZG_VID_CGA)
  349.         return 1;
  350.  
  351.     regs.h.ah = 0x0B;
  352.     regs.h.bl = PaletteNo;
  353.     regs.h.bh = 0x01;
  354.     int86(0x10,®s,®s);
  355.  
  356.     return 0;
  357.     }
  358.  
  359. int ZG_SetEVGAPalette(char Palette, char Color)
  360.     {
  361.     union REGS regs;
  362.  
  363.     if ((ZG_VideoInfo.Type != ZG_VID_EGA) && (ZG_VideoInfo.Type != ZG_VID_VGA))
  364.         return 1;
  365.  
  366.     regs.h.ah = 0x10;
  367.     regs.h.al = 0x00;
  368.     regs.h.bh = Color;
  369.     regs.h.bl = Palette;
  370.     int86(0x10,®s,®s);
  371.  
  372.     return 0;
  373.     }
  374.  
  375. /*--------------------------------
  376.   Dummy pixel plotter and reader
  377. --------------------------------*/
  378.  
  379. static void DummyPlot(int x, int y, int color, int mode)
  380.     {
  381.     /* it does nothing */
  382.     }
  383.  
  384. static int DummyRead(int x, int y)
  385.     {
  386.     /* it does nothing */
  387.     return 0;
  388.     }
  389.  
  390. /*---------------------------------------------
  391.   CGA, EGA, MCGA, VGA pixel plotting functions
  392. ---------------------------------------------*/
  393.  
  394. static void CGA1_Plot(int x, int y, int color, int mode)
  395.     {
  396.     /* this routine used for CGA 640x200x2 mode */
  397.     unsigned int pixel_mask, pixel_offset;
  398.     unsigned char far * pixel_byte;
  399.  
  400.     /* find the byte containing our pixel */
  401.     pixel_offset = 0x2000 * (y % 4) + 80 * (y / 2) + x / 8;
  402.     pixel_byte   = MK_FP(CGA_VID_SEG,pixel_offset);
  403.  
  404.     /* calculate bit mask */
  405.     pixel_mask = 0x80 >> (x % 8);
  406.  
  407.     /* set pixel */
  408.     switch (mode)
  409.         {
  410.         case ZG_PXL_SET :
  411.             if (color)
  412.                 *pixel_byte |= pixel_mask;
  413.             else
  414.                 *pixel_byte &= ~pixel_mask;
  415.             break;
  416.  
  417.         case ZG_PXL_AND :
  418.             if (color)
  419.                 *pixel_byte &= pixel_mask;
  420.             break;
  421.  
  422.         case ZG_PXL_OR  :
  423.             if (!color)
  424.                 *pixel_byte |= pixel_mask;
  425.             break;
  426.  
  427.         case ZG_PXL_XOR :
  428.             if (!color)
  429.                 *pixel_byte ^= pixel_mask;
  430.         }
  431.     }
  432.  
  433. static void CGA2_Plot(int x, int y, int color, int mode)
  434.     {
  435.     /* this routine used for CGA 320x200x4 mode */
  436.     unsigned int pixel_mask, alt_mask, pixel_offset;
  437.     unsigned char far * pixel_byte;
  438.  
  439.     /* find the byte containing our pixel */
  440.     pixel_offset = 0x2000 * (y % 2) + 80 * (y / 2) + x / 4;
  441.     pixel_byte   = MK_FP(CGA_VID_SEG,pixel_offset);
  442.     pixel_mask   = (color & 0x03) << (6 - (x % 4) * 2);
  443.  
  444.     switch (mode)
  445.         {
  446.         case ZG_PXL_SET :
  447.             /* clear the appropriate bits */
  448.             alt_mask     = 0xC0 >> ((x % 4) * 2);
  449.             *pixel_byte &= ~alt_mask;
  450.  
  451.             /* insert the bits for the specified color */
  452.             *pixel_byte |= pixel_mask;
  453.             break;
  454.  
  455.         case ZG_PXL_AND :
  456.             *pixel_byte &= pixel_mask;
  457.             break;
  458.  
  459.         case ZG_PXL_OR :
  460.             *pixel_byte |= pixel_mask;
  461.             break;
  462.  
  463.         case ZG_PXL_XOR :
  464.             *pixel_byte ^= pixel_mask;
  465.         }
  466.     }
  467.  
  468. static void M256_Plot(int x, int y, int color, int mode)
  469.     {
  470.     /* this routine used for MCGA/VGA 320x200x256 mode */
  471.     unsigned int pixel_offset;
  472.     unsigned char far * pixel_byte;
  473.  
  474.     /* find the byte containing our pixel */
  475.     pixel_offset = 320 * y + x;
  476.     pixel_byte   = MK_FP(EVGA_VID_SEG,pixel_offset);
  477.  
  478.     /* set pixel */
  479.     switch (mode)
  480.         {
  481.         case ZG_PXL_SET :
  482.             *pixel_byte = (unsigned char)color;
  483.             break;
  484.         case ZG_PXL_AND :
  485.             *pixel_byte &= (unsigned char)color;
  486.             break;
  487.         case ZG_PXL_OR  :
  488.             *pixel_byte |= (unsigned char)color;
  489.             break;
  490.         case ZG_PXL_XOR :
  491.             *pixel_byte ^= (unsigned char)color;
  492.         }
  493.     }
  494.  
  495. static void EVGA_Plot(int x, int y, int color, int mode)
  496.     {
  497.     /* this routine used for all EGA/VGA modes expect 256-color modes */
  498.     unsigned int pixel_offset, pixel_mask;
  499.     volatile unsigned char dummy;
  500.     unsigned char far * pixel_byte;
  501.  
  502.     /* find the byte containing our pixel */
  503.     pixel_offset = (unsigned int)((long)y * 80L + ((long)x / 8L));
  504.     pixel_byte   = MK_FP(EVGA_VID_SEG,pixel_offset);
  505.  
  506.     /* set up mask */
  507.     pixel_mask   = 0x80 >> (x % 8);
  508.  
  509.     /* set-up video controller */
  510.     OUT_PORT(0x03CE, 8);
  511.     OUT_PORT(0x03CF, (char)pixel_mask);
  512.  
  513.     OUT_PORT(0x03CE, 3);
  514.     OUT_PORT(0x03CF, (char)(mode << 3));
  515.  
  516.     OUT_PORT(0x03C4, 2);
  517.     OUT_PORT(0x03C5, 0x0F);
  518.  
  519.     /* do a dummy read to load latches */
  520.     dummy = *pixel_byte;
  521.  
  522.     /* clear latches */
  523.     *pixel_byte = 0;
  524.  
  525.     /* set bit planes */
  526.     OUT_PORT(0x03C4, 2);
  527.     OUT_PORT(0x03C5, (char)color);
  528.  
  529.     *pixel_byte = 0xFF;
  530.  
  531.     /* finish up */
  532.     OUT_PORT(0x03C4, 2);
  533.     OUT_PORT(0x03C5, 0x0F);
  534.  
  535.     OUT_PORT(0x03CE, 3);
  536.     OUT_PORT(0x03CF, 0);
  537.  
  538.     OUT_PORT(0x03CE, 8);
  539.     OUT_PORT(0x03CF, 0xFF);
  540.     }
  541.  
  542. /*---------------------------------------------
  543.   CGA, EGA, MCGA, VGA pixel reading functions
  544. ---------------------------------------------*/
  545.  
  546. static int CGA1_Read(int x, int y)
  547.     {
  548.     /* this routine used for CGA 640x200x2 mode */
  549.     unsigned int pixel_mask, pixel_offset;
  550.     unsigned char far * pixel_byte;
  551.  
  552.     /* find the byte containing our pixel */
  553.     pixel_offset = 0x2000 * (y % 4) + 80 * (y / 2) + x / 8;
  554.     pixel_byte   = MK_FP(CGA_VID_SEG,pixel_offset);
  555.  
  556.     /* calculate bit mask */
  557.     pixel_mask = 0x80 >> (x % 8);
  558.  
  559.     /* read pixel */
  560.     if (pixel_mask & *pixel_byte)
  561.         return 1;
  562.     else
  563.         return 0;
  564.     }
  565.  
  566. static int CGA2_Read(int x, int y)
  567.     {
  568.     /* this routine used for CGA 320x200x4 mode */
  569.     unsigned int pixel_mask, pixel_offset;
  570.     unsigned char far * pixel_byte;
  571.  
  572.     /* find the byte containing our pixel */
  573.     pixel_offset = 0x2000 * (y % 2) + 80 * (y / 2) + x / 4;
  574.     pixel_byte   = MK_FP(CGA_VID_SEG,pixel_offset);
  575.     pixel_mask   = 0x03 << (6 - (x % 4) * 2);
  576.  
  577.     return (int)((*pixel_byte & pixel_mask) >> (6 - (x % 4) * 2));
  578.     }
  579.  
  580. static int M256_Read(int x, int y)
  581.     {
  582.     /* this routine used for MCGA/VGA 320x200x256 mode */
  583.     unsigned int pixel_offset;
  584.     unsigned char far * pixel_byte;
  585.  
  586.     /* find the byte containing our pixel */
  587.     pixel_offset = 320 * y + x;
  588.     pixel_byte   = MK_FP(EVGA_VID_SEG,pixel_offset);
  589.  
  590.     /* return pixel value */
  591.     return *pixel_byte;
  592.     }
  593.  
  594. static int EVGA_Read(int x, int y)
  595.     {
  596.     /* this routine used for all EGA/VGA modes expect 256-color modes */
  597.     unsigned int pixel_offset, pixel_mask;
  598.     int color = 0;
  599.     char i;
  600.     unsigned char far * pixel_byte;
  601.  
  602.     /* find the byte containing our pixel */
  603.     pixel_offset = (unsigned int)((long)y * 80L + ((long)x / 8L));
  604.     pixel_byte   = MK_FP(EVGA_VID_SEG,pixel_offset);
  605.  
  606.     /* set up mask */
  607.     pixel_mask   = 0x80 >> (x % 8);
  608.  
  609.     /* read the color bits */
  610.     for (i = 0; i < 4; ++i)
  611.         {
  612.         OUT_PORT(0x3CE, 4);
  613.         OUT_PORT(0x3CF, i);
  614.  
  615.         OUT_PORT(0x3CE, 5);
  616.         OUT_PORT(0x3CF, 0);
  617.  
  618.         if (*pixel_byte & pixel_mask)
  619.             color |= 1 << i;
  620.         }
  621.  
  622.     return color;
  623.     }
  624.  
  625. /*---------------
  626.   HGC functions
  627. ---------------*/
  628.  
  629. static void HGC_GraphMode(void)
  630.     {
  631.     /* Codes to be loaded to Hercules 6845 to set graphics mode */
  632.     static const unsigned char HGC_GRAPH_CODES[12] =
  633.         {0x35,0x2D,0x2E,0x07,0x5B,0x02,0x57,0x57,0x02,0x03,0x00,0x00};
  634.  
  635.     unsigned int  i;
  636.     unsigned char far * screen;
  637.  
  638.     OUT_PORT(HGC_CFG_PORT,3);
  639.  
  640.     screen = MK_FP(HGC_VID_SEG,0);
  641.  
  642.     OUT_PORT(HGC_CTL_PORT,2); /* set control port */
  643.  
  644.     for (i = 0; i <= 11; ++i)
  645.         {
  646.         OUT_PORT(HGC_IDX_PORT, (char)i);
  647.         OUT_PORT(HGC_DAT_PORT, HGC_GRAPH_CODES[i]);
  648.         }
  649.  
  650.     for (i = 0; i <= 32767; ++i)
  651.         {
  652.         *screen = '\x00';
  653.         ++screen;
  654.         }
  655.  
  656.     OUT_PORT(HGC_CTL_PORT,10); /* set control port */
  657.     }
  658.  
  659. static void HGC_TextMode(void)
  660.     {
  661.     /* Codes to be loaded to Hercules 6845 to set text mode */
  662.     static const unsigned char HGC_TEXT_CODES[12]  =
  663.         {0x61,0x50,0x52,0x0F,0x19,0x06,0x19,0x19,0x02,0x0D,0x0B,0x0C};
  664.  
  665.     unsigned int  i;
  666.     unsigned char far * screen;
  667.  
  668.     OUT_PORT(HGC_CFG_PORT,3);
  669.  
  670.     screen = MK_FP(HGC_VID_SEG,0);
  671.  
  672.     OUT_PORT(HGC_CTL_PORT,0x20); /* set control port */
  673.  
  674.     for (i = 0; i <= 11; ++i)
  675.         {
  676.         OUT_PORT(HGC_IDX_PORT, (char)i);
  677.         OUT_PORT(HGC_DAT_PORT, HGC_TEXT_CODES[i]);
  678.         }
  679.  
  680.     for (i = 0; i <= 32767; ++i)
  681.         {
  682.         if (i % 2 == 1)
  683.             *screen = '\x07';
  684.         else
  685.             *screen = '\x20';
  686.  
  687.         ++screen;
  688.         }
  689.  
  690.     OUT_PORT(HGC_CTL_PORT,0x28); /* set control port */
  691.     }
  692.  
  693. static void HGC_Plot(int x, int y, int color, int mode)
  694.     {
  695.     /* this routine used for HGC 720x348x2 mode */
  696.     unsigned int pixel_mask, pixel_offset;
  697.     unsigned char far * pixel_byte;
  698.  
  699.     /* find the byte containing our pixel */
  700.     pixel_offset = 0x2000 * (y % 4) + 90 * (y / 4) + x / 8;
  701.     pixel_byte   = MK_FP(HGC_VID_SEG,pixel_offset);
  702.  
  703.     /* calculate bit mask */
  704.     pixel_mask = 0x80 >> (x % 8);
  705.  
  706.     /* set pixel */
  707.     switch (mode)
  708.         {
  709.         case ZG_PXL_SET :
  710.             if (color)
  711.                 *pixel_byte |= pixel_mask;
  712.             else
  713.                 *pixel_byte &= ~pixel_mask;
  714.             break;
  715.  
  716.         case ZG_PXL_AND :
  717.             if (color)
  718.                 *pixel_byte &= pixel_mask;
  719.             break;
  720.  
  721.         case ZG_PXL_OR  :
  722.             if (!color)
  723.                 *pixel_byte |= pixel_mask;
  724.             break;
  725.  
  726.         case ZG_PXL_XOR :
  727.             if (!color)
  728.                 *pixel_byte ^= pixel_mask;
  729.         }
  730.     }
  731.  
  732. static int HGC_Read(int x, int y)
  733.     {
  734.     /* this routine used for HGC 720x348x2 mode */
  735.     unsigned int pixel_mask, pixel_offset;
  736.     unsigned char far * pixel_byte;
  737.  
  738.     /* find the byte containing our pixel */
  739.     pixel_offset = 0x2000 * (y % 4) + 90 * (y / 4) + x / 8;
  740.     pixel_byte   = MK_FP(HGC_VID_SEG,pixel_offset);
  741.  
  742.     /* calculate bit mask */
  743.     pixel_mask = 0x80 >> (x % 8);
  744.  
  745.     /* read pixel */
  746.     if (pixel_mask & *pixel_byte)
  747.         return 1;
  748.     else
  749.         return 0;
  750.     }
  751.