home *** CD-ROM | disk | FTP | other *** search
- /* This code supports an article in issue #51 of:
-
- Micro Cornucopia Magazine
- P.O. Box 223
- Bend, OR 97709
- */
- /*
- Module: ZG_LwLvl (ZipGraph Low-Level functions)
- Version 1.00 22-Oct-1989
-
- Language: ANSI C w/MS-DOS extensions
- Environ: IBM-PC compatibles w/MDA, CGA, HGC, EGA, MCGA, or VGA
-
- Compilers: Borland Turbo C v2.00
- Lattice C v6.01
- Microsoft C v5.10 and QuickC v2.01
- Zortech C & C++ v2.01
-
- Purpose: Provides low-level graphics routines for detecting graphics
- adapters, setting graphics modes, and plotting pixels. This
- module is required by the higher-level ZipGraph modules.
-
- Written by: Scott Robert Ladd
- 705 West Virginia
- Gunnison CO 81230
-
- MCI: srl
- FidoNet: 1:104/708
- */
-
- #define __ZG_LWLVL_C 1
-
- #if !defined(LATTICE)
- #include "conio.h"
- #endif
-
- #include "dos.h"
- #include "zg_lwlvl.h"
-
- /*-----------------------------
- handle compiler differences
- -----------------------------*/
-
- #if defined(_MSC) || defined(_QC) || defined(__ZTC__) || defined(LATTICE)
- #define OUT_PORT(port,val) outp(port,val)
- #elif defined(__TURBOC__)
- #define OUT_PORT(port,val) outportb(port,val)
- #endif
-
- #if !defined(MK_FP)
- #define MK_FP(seg,off) ((void far *)(((long)(seg) << 16L) | (long)(off)))
- #endif
-
- /*------------------------------
- ZipGraph INTERNAL PROTOTYPES
- ------------------------------*/
-
- static void DummyPlot(int x, int y, int color, int mode);
- static int DummyRead(int x, int y);
-
- static void CGA1_Plot(int x, int y, int color, int mode);
- static void CGA2_Plot(int x, int y, int color, int mode);
- static void M256_Plot(int x, int y, int color, int mode);
- static void EVGA_Plot(int x, int y, int color, int mode);
-
- static int CGA1_Read(int x, int y);
- static int CGA2_Read(int x, int y);
- static int M256_Read(int x, int y);
- static int EVGA_Read(int x, int y);
-
- static void HGC_GraphMode(void);
- static void HGC_TextMode(void);
- static void HGC_Plot(int x, int y, int color, int mode);
- static int HGC_Read(int x, int y);
-
- /*---------------------------
- ZipGraph PUBLIC VARIABLES
- ---------------------------*/
-
- struct
- {
- int Type;
- int Monitor;
- int Mode;
-
- int Xwidth;
- int Ylength;
- int NoColors;
- }
- ZG_VideoInfo;
-
- void (* ZG_PlotPixel)(int x, int y, int color, int mode) = DummyPlot;
- int (* ZG_ReadPixel)(int x, int y) = DummyRead;
-
- /*----------------------------------------
- ZipGraph INTERNAL TABLES and VARIABLES
- ----------------------------------------*/
-
- static const struct
- {
- int BestRes;
- int MostColor;
-
- unsigned long ModeList;
- }
- VideoTable[06] =
- {
- { 0, 0, 0x00000000L},
- { ZG_MOD_640x200x2, ZG_MOD_320x200x4, 0x00000006L},
- { ZG_MOD_720x348x1, ZG_MOD_720x348x1, 0x00000001L},
- { ZG_MOD_640x350x16, ZG_MOD_640x350x16, 0x0000007EL},
- { ZG_MOD_640x480x2, ZG_MOD_320x200x256, 0x00000486L},
- { ZG_MOD_640x480x16, ZG_MOD_320x200x256, 0x000003FEL}
- };
-
- static const struct
- {
- char ActualMode;
- void (* PixelProc)(int x, int y, int color, int mode);
- int (* ReadProc)(int x, int y);
- int Xwidth;
- int Ylength;
- int NoColors;
- }
- ModeData[10] =
- {
- { 0x00, HGC_Plot, HGC_Read, 720, 348, 1 },
- { 0x04, CGA2_Plot, CGA2_Read, 320, 200, 4 },
- { 0x06, CGA1_Plot, CGA1_Read, 640, 200, 2 },
- { 0x0D, EVGA_Plot, EVGA_Read, 320, 200, 16 },
- { 0x0E, EVGA_Plot, EVGA_Read, 640, 200, 16 },
- { 0x0F, EVGA_Plot, EVGA_Read, 640, 350, 2 },
- { 0x10, EVGA_Plot, EVGA_Read, 640, 350, 16 },
- { 0x11, EVGA_Plot, EVGA_Read, 640, 480, 2 },
- { 0x12, EVGA_Plot, EVGA_Read, 640, 480, 16 },
- { 0x13, M256_Plot, M256_Read, 320, 200, 256}
- };
-
- static unsigned char OriginalMode;
-
- /*------------------------------
- IBM-type adapter global data
- ------------------------------*/
-
- static const unsigned int CGA_VID_SEG = 0xB800;
- static const unsigned int EVGA_VID_SEG = 0xA000;
-
- /*-------------------------
- MDA and HGC global data
- -------------------------*/
-
- /* Hercules video RAM segment */
- static const unsigned int HGC_VID_SEG = 0xB000;
-
- /* Monochrome 6845 Video Controller ports */
- static const unsigned int HGC_IDX_PORT = 0x03B4;
- static const unsigned int HGC_DAT_PORT = 0x03B5;
- static const unsigned int HGC_CTL_PORT = 0x03B8;
- static const unsigned int HGC_CFG_PORT = 0x03BF;
-
- /*----------------------------
- ZipGraph PUBLIC FUNCTIONS!
- ----------------------------*/
-
- int ZG_Init(void)
- {
- union REGS regs;
- int i, status_changed;
- unsigned char orig_status;
-
- ZG_VideoInfo.Type = ZG_ERROR;
- ZG_VideoInfo.Monitor = ZG_ERROR;
- ZG_VideoInfo.Mode = ZG_ERROR;
-
- ZG_VideoInfo.Xwidth = 0;
- ZG_VideoInfo.Ylength = 0;
- ZG_VideoInfo.NoColors = 0;
-
- regs.h.ah = 0x1A; /* VGA Identifier Adapter Service */
- regs.h.al = 0;
- int86(0x10,®s,®s);
-
- if (regs.h.al == 0x1A)
- {
- switch (regs.h.bl)
- {
- case 1 : ZG_VideoInfo.Type = ZG_VID_MDA;
- ZG_VideoInfo.Monitor = ZG_MTR_MONO;
- break;
-
- case 2 : ZG_VideoInfo.Type = ZG_VID_CGA;
- ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
- break;
-
- case 4 : ZG_VideoInfo.Type = ZG_VID_EGA;
- ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
- break;
-
- case 5 : ZG_VideoInfo.Type = ZG_VID_EGA;
- ZG_VideoInfo.Monitor = ZG_MTR_MONO;
- break;
-
- case 7 : ZG_VideoInfo.Type = ZG_VID_VGA;
- ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
- break;
-
- case 8 : ZG_VideoInfo.Type = ZG_VID_VGA;
- ZG_VideoInfo.Monitor = ZG_MTR_MONO;
- break;
-
- case 10: ZG_VideoInfo.Type = ZG_VID_MCGA;
- ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
- break;
-
- case 11: ZG_VideoInfo.Type = ZG_VID_MCGA;
- ZG_VideoInfo.Monitor = ZG_MTR_MONO;
- break;
-
- case 12: ZG_VideoInfo.Type = ZG_VID_MCGA;
- ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
- break;
-
- default:
- return 1;
- }
- }
- else
- {
- /* check for an EGA */
- regs.h.ah = 0x12;
- regs.x.bx = 0x0010;
- int86(0x10,®s,®s);
-
- if (regs.x.bx != 0x10)
- {
- ZG_VideoInfo.Type = ZG_VID_EGA;
-
- regs.h.ah = 0x12;
- regs.x.bx = 0x0010;
- int86(0x10,®s,®s);
-
- if (regs.h.bh == 0)
- ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
- else
- ZG_VideoInfo.Monitor = ZG_MTR_MONO;
- }
- else
- {
- int86(0x11,®s,®s);
-
- switch ((regs.h.al & 0x30) >> 4)
- {
- case 0 :
- return 1;
-
- case 1 :
- case 2 :
- ZG_VideoInfo.Type = ZG_VID_CGA;
- ZG_VideoInfo.Monitor = ZG_MTR_COLOR;
- break;
-
- case 3 :
- status_changed = 0;
-
- orig_status = (unsigned char)(inp(0xBA) & 0x80);
-
- for (i = 0; (i < 30000) && (!status_changed); ++i)
- if (orig_status != (unsigned char)(inp(0xBA) & 0x80))
- status_changed = 1;
-
- if (status_changed)
- ZG_VideoInfo.Type = ZG_VID_HGC;
- else
- ZG_VideoInfo.Type = ZG_VID_MDA;
-
- ZG_VideoInfo.Monitor = ZG_MTR_MONO;
- }
- }
- }
-
- if (ZG_VideoInfo.Type != ZG_VID_HGC)
- {
- regs.h.ah = 0x0F;
- int86(0x10,®s,®s);
- OriginalMode = regs.h.al;
- }
-
- return 0;
- }
-
- int ZG_SetMode(int VideoMode)
- {
- union REGS regs;
-
- if (VideoMode < 0)
- return 1;
-
- if (VideoMode == 0x80)
- VideoMode = VideoTable[ZG_VideoInfo.Type].BestRes;
- else
- if (VideoMode == 0x81)
- VideoMode = VideoTable[ZG_VideoInfo.Type].MostColor;
-
- if ((VideoMode > 9)
- || (!(VideoTable[ZG_VideoInfo.Type].ModeList & (1 << VideoMode))))
- return 1;
-
- ZG_PlotPixel = ModeData[VideoMode].PixelProc;
- ZG_ReadPixel = ModeData[VideoMode].ReadProc;
-
- if (VideoMode == ZG_MOD_720x348x1)
- HGC_GraphMode();
- else
- {
- regs.h.ah = 0;
- regs.h.al = ModeData[VideoMode].ActualMode;
- int86(0x10,®s,®s);
- }
-
- ZG_VideoInfo.Mode = VideoMode;
- ZG_VideoInfo.Xwidth = ModeData[VideoMode].Xwidth;
- ZG_VideoInfo.Ylength = ModeData[VideoMode].Ylength;
- ZG_VideoInfo.NoColors = ModeData[VideoMode].NoColors;
-
- return 0;
- }
-
- int ZG_Done(void)
- {
- union REGS regs;
-
- if (ZG_VideoInfo.Type == ZG_VID_HGC)
- HGC_TextMode();
- else
- {
- regs.h.ah = 0;
- regs.h.al = OriginalMode;
- int86(0x10,®s,®s);
- }
-
- return 0;
- }
-
- int ZG_SetCGAPalette(char PaletteNo)
- {
- union REGS regs;
-
- if (ZG_VideoInfo.Type != ZG_VID_CGA)
- return 1;
-
- regs.h.ah = 0x0B;
- regs.h.bl = PaletteNo;
- regs.h.bh = 0x01;
- int86(0x10,®s,®s);
-
- return 0;
- }
-
- int ZG_SetEVGAPalette(char Palette, char Color)
- {
- union REGS regs;
-
- if ((ZG_VideoInfo.Type != ZG_VID_EGA) && (ZG_VideoInfo.Type != ZG_VID_VGA))
- return 1;
-
- regs.h.ah = 0x10;
- regs.h.al = 0x00;
- regs.h.bh = Color;
- regs.h.bl = Palette;
- int86(0x10,®s,®s);
-
- return 0;
- }
-
- /*--------------------------------
- Dummy pixel plotter and reader
- --------------------------------*/
-
- static void DummyPlot(int x, int y, int color, int mode)
- {
- /* it does nothing */
- }
-
- static int DummyRead(int x, int y)
- {
- /* it does nothing */
- return 0;
- }
-
- /*---------------------------------------------
- CGA, EGA, MCGA, VGA pixel plotting functions
- ---------------------------------------------*/
-
- static void CGA1_Plot(int x, int y, int color, int mode)
- {
- /* this routine used for CGA 640x200x2 mode */
- unsigned int pixel_mask, pixel_offset;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = 0x2000 * (y % 4) + 80 * (y / 2) + x / 8;
- pixel_byte = MK_FP(CGA_VID_SEG,pixel_offset);
-
- /* calculate bit mask */
- pixel_mask = 0x80 >> (x % 8);
-
- /* set pixel */
- switch (mode)
- {
- case ZG_PXL_SET :
- if (color)
- *pixel_byte |= pixel_mask;
- else
- *pixel_byte &= ~pixel_mask;
- break;
-
- case ZG_PXL_AND :
- if (color)
- *pixel_byte &= pixel_mask;
- break;
-
- case ZG_PXL_OR :
- if (!color)
- *pixel_byte |= pixel_mask;
- break;
-
- case ZG_PXL_XOR :
- if (!color)
- *pixel_byte ^= pixel_mask;
- }
- }
-
- static void CGA2_Plot(int x, int y, int color, int mode)
- {
- /* this routine used for CGA 320x200x4 mode */
- unsigned int pixel_mask, alt_mask, pixel_offset;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = 0x2000 * (y % 2) + 80 * (y / 2) + x / 4;
- pixel_byte = MK_FP(CGA_VID_SEG,pixel_offset);
- pixel_mask = (color & 0x03) << (6 - (x % 4) * 2);
-
- switch (mode)
- {
- case ZG_PXL_SET :
- /* clear the appropriate bits */
- alt_mask = 0xC0 >> ((x % 4) * 2);
- *pixel_byte &= ~alt_mask;
-
- /* insert the bits for the specified color */
- *pixel_byte |= pixel_mask;
- break;
-
- case ZG_PXL_AND :
- *pixel_byte &= pixel_mask;
- break;
-
- case ZG_PXL_OR :
- *pixel_byte |= pixel_mask;
- break;
-
- case ZG_PXL_XOR :
- *pixel_byte ^= pixel_mask;
- }
- }
-
- static void M256_Plot(int x, int y, int color, int mode)
- {
- /* this routine used for MCGA/VGA 320x200x256 mode */
- unsigned int pixel_offset;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = 320 * y + x;
- pixel_byte = MK_FP(EVGA_VID_SEG,pixel_offset);
-
- /* set pixel */
- switch (mode)
- {
- case ZG_PXL_SET :
- *pixel_byte = (unsigned char)color;
- break;
- case ZG_PXL_AND :
- *pixel_byte &= (unsigned char)color;
- break;
- case ZG_PXL_OR :
- *pixel_byte |= (unsigned char)color;
- break;
- case ZG_PXL_XOR :
- *pixel_byte ^= (unsigned char)color;
- }
- }
-
- static void EVGA_Plot(int x, int y, int color, int mode)
- {
- /* this routine used for all EGA/VGA modes expect 256-color modes */
- unsigned int pixel_offset, pixel_mask;
- volatile unsigned char dummy;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = (unsigned int)((long)y * 80L + ((long)x / 8L));
- pixel_byte = MK_FP(EVGA_VID_SEG,pixel_offset);
-
- /* set up mask */
- pixel_mask = 0x80 >> (x % 8);
-
- /* set-up video controller */
- OUT_PORT(0x03CE, 8);
- OUT_PORT(0x03CF, (char)pixel_mask);
-
- OUT_PORT(0x03CE, 3);
- OUT_PORT(0x03CF, (char)(mode << 3));
-
- OUT_PORT(0x03C4, 2);
- OUT_PORT(0x03C5, 0x0F);
-
- /* do a dummy read to load latches */
- dummy = *pixel_byte;
-
- /* clear latches */
- *pixel_byte = 0;
-
- /* set bit planes */
- OUT_PORT(0x03C4, 2);
- OUT_PORT(0x03C5, (char)color);
-
- *pixel_byte = 0xFF;
-
- /* finish up */
- OUT_PORT(0x03C4, 2);
- OUT_PORT(0x03C5, 0x0F);
-
- OUT_PORT(0x03CE, 3);
- OUT_PORT(0x03CF, 0);
-
- OUT_PORT(0x03CE, 8);
- OUT_PORT(0x03CF, 0xFF);
- }
-
- /*---------------------------------------------
- CGA, EGA, MCGA, VGA pixel reading functions
- ---------------------------------------------*/
-
- static int CGA1_Read(int x, int y)
- {
- /* this routine used for CGA 640x200x2 mode */
- unsigned int pixel_mask, pixel_offset;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = 0x2000 * (y % 4) + 80 * (y / 2) + x / 8;
- pixel_byte = MK_FP(CGA_VID_SEG,pixel_offset);
-
- /* calculate bit mask */
- pixel_mask = 0x80 >> (x % 8);
-
- /* read pixel */
- if (pixel_mask & *pixel_byte)
- return 1;
- else
- return 0;
- }
-
- static int CGA2_Read(int x, int y)
- {
- /* this routine used for CGA 320x200x4 mode */
- unsigned int pixel_mask, pixel_offset;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = 0x2000 * (y % 2) + 80 * (y / 2) + x / 4;
- pixel_byte = MK_FP(CGA_VID_SEG,pixel_offset);
- pixel_mask = 0x03 << (6 - (x % 4) * 2);
-
- return (int)((*pixel_byte & pixel_mask) >> (6 - (x % 4) * 2));
- }
-
- static int M256_Read(int x, int y)
- {
- /* this routine used for MCGA/VGA 320x200x256 mode */
- unsigned int pixel_offset;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = 320 * y + x;
- pixel_byte = MK_FP(EVGA_VID_SEG,pixel_offset);
-
- /* return pixel value */
- return *pixel_byte;
- }
-
- static int EVGA_Read(int x, int y)
- {
- /* this routine used for all EGA/VGA modes expect 256-color modes */
- unsigned int pixel_offset, pixel_mask;
- int color = 0;
- char i;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = (unsigned int)((long)y * 80L + ((long)x / 8L));
- pixel_byte = MK_FP(EVGA_VID_SEG,pixel_offset);
-
- /* set up mask */
- pixel_mask = 0x80 >> (x % 8);
-
- /* read the color bits */
- for (i = 0; i < 4; ++i)
- {
- OUT_PORT(0x3CE, 4);
- OUT_PORT(0x3CF, i);
-
- OUT_PORT(0x3CE, 5);
- OUT_PORT(0x3CF, 0);
-
- if (*pixel_byte & pixel_mask)
- color |= 1 << i;
- }
-
- return color;
- }
-
- /*---------------
- HGC functions
- ---------------*/
-
- static void HGC_GraphMode(void)
- {
- /* Codes to be loaded to Hercules 6845 to set graphics mode */
- static const unsigned char HGC_GRAPH_CODES[12] =
- {0x35,0x2D,0x2E,0x07,0x5B,0x02,0x57,0x57,0x02,0x03,0x00,0x00};
-
- unsigned int i;
- unsigned char far * screen;
-
- OUT_PORT(HGC_CFG_PORT,3);
-
- screen = MK_FP(HGC_VID_SEG,0);
-
- OUT_PORT(HGC_CTL_PORT,2); /* set control port */
-
- for (i = 0; i <= 11; ++i)
- {
- OUT_PORT(HGC_IDX_PORT, (char)i);
- OUT_PORT(HGC_DAT_PORT, HGC_GRAPH_CODES[i]);
- }
-
- for (i = 0; i <= 32767; ++i)
- {
- *screen = '\x00';
- ++screen;
- }
-
- OUT_PORT(HGC_CTL_PORT,10); /* set control port */
- }
-
- static void HGC_TextMode(void)
- {
- /* Codes to be loaded to Hercules 6845 to set text mode */
- static const unsigned char HGC_TEXT_CODES[12] =
- {0x61,0x50,0x52,0x0F,0x19,0x06,0x19,0x19,0x02,0x0D,0x0B,0x0C};
-
- unsigned int i;
- unsigned char far * screen;
-
- OUT_PORT(HGC_CFG_PORT,3);
-
- screen = MK_FP(HGC_VID_SEG,0);
-
- OUT_PORT(HGC_CTL_PORT,0x20); /* set control port */
-
- for (i = 0; i <= 11; ++i)
- {
- OUT_PORT(HGC_IDX_PORT, (char)i);
- OUT_PORT(HGC_DAT_PORT, HGC_TEXT_CODES[i]);
- }
-
- for (i = 0; i <= 32767; ++i)
- {
- if (i % 2 == 1)
- *screen = '\x07';
- else
- *screen = '\x20';
-
- ++screen;
- }
-
- OUT_PORT(HGC_CTL_PORT,0x28); /* set control port */
- }
-
- static void HGC_Plot(int x, int y, int color, int mode)
- {
- /* this routine used for HGC 720x348x2 mode */
- unsigned int pixel_mask, pixel_offset;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = 0x2000 * (y % 4) + 90 * (y / 4) + x / 8;
- pixel_byte = MK_FP(HGC_VID_SEG,pixel_offset);
-
- /* calculate bit mask */
- pixel_mask = 0x80 >> (x % 8);
-
- /* set pixel */
- switch (mode)
- {
- case ZG_PXL_SET :
- if (color)
- *pixel_byte |= pixel_mask;
- else
- *pixel_byte &= ~pixel_mask;
- break;
-
- case ZG_PXL_AND :
- if (color)
- *pixel_byte &= pixel_mask;
- break;
-
- case ZG_PXL_OR :
- if (!color)
- *pixel_byte |= pixel_mask;
- break;
-
- case ZG_PXL_XOR :
- if (!color)
- *pixel_byte ^= pixel_mask;
- }
- }
-
- static int HGC_Read(int x, int y)
- {
- /* this routine used for HGC 720x348x2 mode */
- unsigned int pixel_mask, pixel_offset;
- unsigned char far * pixel_byte;
-
- /* find the byte containing our pixel */
- pixel_offset = 0x2000 * (y % 4) + 90 * (y / 4) + x / 8;
- pixel_byte = MK_FP(HGC_VID_SEG,pixel_offset);
-
- /* calculate bit mask */
- pixel_mask = 0x80 >> (x % 8);
-
- /* read pixel */
- if (pixel_mask & *pixel_byte)
- return 1;
- else
- return 0;
- }