Category : Printer + Display Graphics
Archive   : BMRPH102.ZIP
Filename : ZG_LWLVL.C

 
Output of file : ZG_LWLVL.C contained in archive : BMRPH102.ZIP
/*
Module: ZG_LwLvl (ZipGraph Low-Level functions)
Version 1.10 28-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

BBS (303)641-6438
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

/*--------------------------
pointer conversion macro
--------------------------*/

#if !defined(MK_FP)
#define MK_FP(seg,off) ((void far *)(((long)(seg) << 16)|(unsigned)(off)))
#endif

/*------------------------------
ZipGraph INTERNAL PROTOTYPES
------------------------------*/

static void DummyPlot(int x, int y, int color);
static int DummyRead(int x, int y);

static void CGA1_Plot(int x, int y, int color);
static void CGA2_Plot(int x, int y, int color);
static void M256_Plot(int x, int y, int color);
static void EVGA_Plot(int x, int y, int color);

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);
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) = 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_720x348x2, ZG_MOD_720x348x2, 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 (* ReadProc)(int x, int y);
int Xwidth;
int Ylength;
int NoColors;
}
ModeData[10] =
{
{ 0x00, HGC_Plot, HGC_Read, 720, 348, 2 },
{ 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 = 0;

static int PixelMode = ZG_PXL_SET;

/*------------------------------
IBM-type adapter global data
------------------------------*/

#define CGA_VID_SEG 0xB800
#define EVGA_VID_SEG 0xA000

/*-------------------------
MDA and HGC global data
-------------------------*/

/* Hercules video RAM segment */
#define HGC_VID_SEG 0xB000

/* Monochrome 6845 Video Controller ports */
#define HGC_IDX_PORT 0x03B4
#define HGC_DAT_PORT 0x03B5
#define HGC_CTL_PORT 0x03B8
#define 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(0x03BA) & 0x80);

for (i = 0; (i < 30000) && (!status_changed); ++i)
if (orig_status != (unsigned char)(inp(0x03BA) & 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_720x348x2)
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_SetPixelMode(int PixMode)
{
if ((PixMode < ZG_PXL_SET) || (PixMode > ZG_PXL_XOR))
return 1;

PixelMode = PixMode;

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)
{
/* 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)
{
/* this routine used for CGA 640x200x2 mode */
unsigned int pixel_mask;
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(CGA_VID_SEG,0x2000 * (y & 3) + 80 * (y >> 1) + (x >> 3));

/* calculate bit mask */
pixel_mask = 0x80 >> (x & 7);

/* set pixel */
switch (PixelMode)
{
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)
{
/* this routine used for CGA 320x200x4 mode */
unsigned int pixel_mask, alt_mask;
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(CGA_VID_SEG,0x2000 * (y & 1) + 80 * (y >> 1) + (x >> 2));
pixel_mask = (color & 3) << (6 - ((x & 3) << 1));

switch (PixelMode)
{
case ZG_PXL_SET :
/* clear the appropriate bits */
alt_mask = 0xC0 >> ((x & 3) << 1);
*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)
{
/* this routine used for MCGA/VGA 320x200x256 mode */
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(EVGA_VID_SEG, (y << 8) + (y << 6) + x);

/* set pixel */
switch (PixelMode)
{
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)
{
/* this routine used for all EGA/VGA modes expect 256-color modes */
unsigned char pixel_mask;
volatile unsigned char dummy;
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(EVGA_VID_SEG, (y * 80) + (x >> 3));

/* set up mask */
pixel_mask = (char)(0x80 >> (x & 7));

/* set-up video controller */
OUT_PORT(0x03CE, 8);
OUT_PORT(0x03CF, pixel_mask);

OUT_PORT(0x03CE, 3);
OUT_PORT(0x03CF, (char)(PixelMode << 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;
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(CGA_VID_SEG,0x2000 * (y & 3) + 80 * (y >> 1) + (x >> 3));

/* calculate bit mask */
pixel_mask = 0x80 >> (x & 7);

/* 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;
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(CGA_VID_SEG,0x2000 * (y & 1) + 80 * (y >> 1) + (x >> 2));
pixel_mask = 3 << (6 - ((x & 3) << 1));

return (int)((*pixel_byte & pixel_mask) >> (6 - ((x & 3) << 1)));
}

static int M256_Read(int x, int y)
{
/* this routine used for MCGA/VGA 320x200x256 mode */
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(EVGA_VID_SEG, (y << 8) + (y << 6) + x);

/* 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 */
char i;
int color = 0;
unsigned int pixel_mask;
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(EVGA_VID_SEG, (y * 80 + (x >> 3)));

/* set up mask */
pixel_mask = 0x80 >> (x & 7);

/* 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)
{
/* this routine used for HGC 720x348x2 mode */
unsigned int pixel_mask;
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(HGC_VID_SEG,0x2000 * (y & 3) + 90 * (y >> 2) + (x >> 3));

/* calculate bit mask */
pixel_mask = 0x80 >> (x & 7);

/* set pixel */
switch (PixelMode)
{
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;
unsigned char far * pixel_byte;

/* find the byte containing our pixel */
pixel_byte = MK_FP(HGC_VID_SEG,0x2000 * (y & 3) + 90 * (y >> 2) + (x >> 3));

/* calculate bit mask */
pixel_mask = 0x80 >> (x & 7);

/* read pixel */
if (pixel_mask & *pixel_byte)
return 1;
else
return 0;
}


  3 Responses to “Category : Printer + Display Graphics
Archive   : BMRPH102.ZIP
Filename : ZG_LWLVL.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/