home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MS DOS Archives 1
/
MS-DOS_Archives_Volume_One_Walnut_Creek.iso
/
msdos
/
graphics
/
grafxlib.arc
/
EGAGRAF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1987-08-31
|
13KB
|
499 lines
/*
* grafix --- egagraf.c
*
* EGA graphics driver - hi-res mode only (on enhanced, ordinary, or
* mono (i hope it works!) display)
*
* Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
*
*/
#include <dos.h>
#include "macros.h"
#include "grafsys.h"
/* EGA parameters */
#define int_video 16
#define ega_setmode 0
#define ega_setcur 2
#define ega_setpage 5
#define ega_writech 9
#define ega_setpal 0x10
#define mde_80bw 2
#define mde_80co 3
#define mde_320 4
#define mde_640 6
#define mde_640X200c 14
#define mde_640X350m 15
#define mde_640X350c 16
#define g_linsiz 80
#define g_allmask 0xff
#define g_pixbyte 8
#define g_bitpix 1
/* Display dependent parameters */
#define g_en_pg1 (g_obj far *)0xa0000000
#define g_en_pg2 (g_obj far *)0xa0008000
#define g_en_bufsiz 28000
#define g_en_colormask 0x0f
#define g_en_xsize 640
#define g_en_ysize 350
#define g_en_xchsize (g_en_xsize / 8)
#define g_en_ychsize (g_en_ysize / 14)
#define g_en_aspect 0.85
#define g_cd_pg1 (g_obj far *)0xa0000000
#define g_cd_pg2 (g_obj far *)0xa0004000
#define g_cd_bufsiz 16000
#define g_cd_colormask 0x0f
#define g_cd_xsize 640
#define g_cd_ysize 200
#define g_cd_xchsize (g_cd_xsize / 8)
#define g_cd_ychsize (g_cd_ysize / 8)
#define g_cd_aspect 0.43
#define g_mo_pg1 (g_obj far *)0xa0000000
#define g_mo_pg2 (g_obj far *)0xa0008000 /* is this right??? */
#define g_mo_bufsiz 28000
#define g_mo_colormask 0x03
#define g_mo_xsize 640
#define g_mo_ysize 350
#define g_mo_xchsize (g_mo_xsize / 8)
#define g_mo_ychsize (g_mo_ysize / 14)
#define g_mo_aspect 0.85
/* EGA port and register addresses */
#define ega_gr_addr 0x3ce /* graphics controller address register */
#define ega_gr_data 0x3cf /* graphics controller data register */
#define ega_gr_sr 0 /* set/reset register index */
#define ega_gr_sren 1 /* set/reset enable register index */
#define ega_gr_ccmp 2 /* color compare register index */
#define ega_gr_rot 3 /* data rotate */
#define ega_gr_mapsel 4 /* read map select */
#define ega_gr_mode 5 /* mode register */
#define ega_gr_misc 6 /* miscellaneous */
#define ega_gr_colorx 7 /* color don't care */
#define ega_gr_mask 8 /* bit mask */
#define ega_gr_x_xor 24 /* xor function select */
/* mode variables */
STATIC unsigned g_bufsiz;
STATIC unsigned g_colormask;
STATIC g_obj far *g_page1addr, far *g_page2addr;
/* utility macros */
#define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
#define trimcolor(c) c &= g_colormask
#define plot(ptr, mask, tmp) { /* plot a pt. grph addr. must be mask reg */ \
outp(ega_gr_data, mask); \
tmp = *ptr; /* a read and a write that will STAY HERE!! */\
*ptr = 0; \
}
/* move one to right */
#define bumpx(ptr,mask) \
if ((mask >>= g_bitpix) == 0) { \
mask = 0x80; \
ptr++; \
}
/* move one line */
#define bumpy(ptr,ydir) { \
if (ydir) \
ptr-=g_linsiz; \
else \
ptr+=g_linsiz; \
}
/****************************************************************************\
* internal utilities *
\****************************************************************************/
/* calculate byte and bit offsets in the graphics buffer for a point */
STATIC void goffs(x, y, offs, pix)
unsigned x, y, *offs, *pix;
{
*offs = y*g_linsiz + x/g_pixbyte;
*pix = g_pixbyte - 1 - x%g_pixbyte;
}
/****************************************************************************
* externally callable functions *
****************************************************************************/
/* fill a region with the specified color */
#ifdef __TURBOC__
# pragma warn -aus /* TC */
# pragma warn -rch
#endif
void EGA_regfill(x1, y1, x2, y2, c)
unsigned x1, y1, x2, y2, c;
{
unsigned offs1, offs2, pix1, pix2;
int wholeobjs;
g_obj far *ptr1, far *ptr2;
g_obj begmask, endmask, mask;
register unsigned y;
register g_obj far *p;
register g_obj tmp;
if (y2 < y1) swap(y1, y2);
if (x2 < x1) swap(x1, x2);
goffs(x1, y1, &offs1, &pix1);
goffs(x2, y1, &offs2, &pix2);
wholeobjs = offs2 - offs1 - 1;
ptr1 = g_drawbuf + offs1;
ptr2 = g_drawbuf + offs2;
trimcolor(c);
begmask = g_allmask >> (g_pixbyte - 1 - pix1)*g_bitpix;
endmask = g_allmask << pix2*g_bitpix;
/* set up EGA registers for write */
outp(ega_gr_addr, ega_gr_sr); /* set/reset register */
outp(ega_gr_data, c);
outp(ega_gr_addr, ega_gr_sren); /* set/reset enable register */
outp(ega_gr_data, g_colormask);
outp(ega_gr_addr, ega_gr_mode); /* mode register */
outp(ega_gr_data, 0); /* write mode 0 */
outp(ega_gr_addr, ega_gr_mask); /* select bit mask register */
/* do the write */
if (wholeobjs < 0) { /* region is less than 8 pels wide */
p = ptr1;
mask = begmask & endmask;
outp(ega_gr_data, mask); /* set bitmask for writes */
for (y=y1; y<=y2; y++) {
tmp = *p; /* read byte into latches */
*p = 0; /* then write there to set the */
/* bits */
bumpy(p, 0);
}
}
else {
p = ptr1; /* do left edge */
outp(ega_gr_data, begmask);
for (y=y1; y<=y2; y++) {
tmp = *p;
*p = 0;
bumpy(p, 0);
}
p = ptr2; /* do right egde */
outp(ega_gr_data, endmask);
for (y=y1; y<=y2; y++) {
tmp = *p;
*p = 0;
bumpy(p, 0);
}
p = ptr1+1; /* now fill it in */
outp(ega_gr_data, g_allmask);
for (y=y1; y<=y2; y++) {
g_fmemset(p, g_allmask, wholeobjs); /* can write it with anything here */
bumpy(p, 0);
}
}
/* reset the EGA to something nice */
outp(ega_gr_data, g_allmask); /* reset bit mask */
outp(ega_gr_addr, ega_gr_sren); /* disable set/reset mode */
outp(ega_gr_data, 0);
}
#ifdef __TURBOC__
# pragma warn .aus /* TC */
# pragma warn .rch
#endif
/* fill the entire buffer with a color fast */
void EGA_clearall(c)
unsigned c;
{
/* set up EGA registers for write */
outp(ega_gr_addr, ega_gr_sr); /* set/reset register */
outp(ega_gr_data, c);
outp(ega_gr_addr, ega_gr_sren); /* set/reset enable register */
outp(ega_gr_data, g_colormask);
outp(ega_gr_addr, ega_gr_mode); /* mode register */
outp(ega_gr_data, 0); /* write mode 0 */
g_fmemset(g_drawbuf, g_allmask, g_bufsiz);
outp(ega_gr_addr, ega_gr_sren); /* disable set/reset mode */
outp(ega_gr_data, 0);
}
/* make the drawing buffer visible by switching pages */
void EGA_show()
{
union REGS inregs, outregs;
if (g_bufflg) {
g_curpage = 1-g_curpage;
inregs.h.ah = ega_setpage;
inregs.h.al = g_curpage;
int86(int_video, &inregs, &outregs);
g_drawbuf = g_physbuf; /* swap around buffer pointers */
g_physbuf = g_virtbuf;
g_virtbuf = g_drawbuf;
}
}
/* set the color pallette */
void EGA_setpal(p, v)
unsigned p, v;
{
union REGS inregs, outregs;
inregs.h.ah = ega_setpal;
inregs.h.al = 0;
inregs.h.bl = p;
inregs.h.bh = v;
int86(int_video, &inregs, &outregs);
}
/* set the background color - just use setpal() */
void EGA_setback(c)
unsigned c;
{
EGA_setpal(0, c);
}
/* turn on graphics mode. mode has no meaning */
#ifdef __TURBOC__
# pragma warn -par /* TC */
#endif
void EGA_gopen(mode)
unsigned mode;
{
union REGS inregs, outregs;
if (g_display == EN) { /* Enhanced color display */
inregs.h.ah = ega_setmode;
inregs.h.al = mde_640X350c;
int86(int_video, &inregs, &outregs);
g_page1addr = g_en_pg1;
g_page2addr = g_en_pg2;
g_bufsiz = g_en_bufsiz;
g_colormask = g_en_colormask;
g_xsize = g_en_xsize;
g_ysize = g_en_ysize;
g_xchsize = g_en_xchsize;
g_ychsize = g_en_ychsize;
g_aspect = g_en_aspect;
}
else if (g_display == CD) { /* Ordinary color display */
inregs.h.ah = ega_setmode;
inregs.h.al = mde_640X200c;
int86(int_video, &inregs, &outregs);
g_page1addr = g_cd_pg1;
g_page2addr = g_cd_pg2;
g_bufsiz = g_cd_bufsiz;
g_colormask = g_cd_colormask;
g_xsize = g_cd_xsize;
g_ysize = g_cd_ysize;
g_xchsize = g_cd_xchsize;
g_ychsize = g_cd_ychsize;
g_aspect = g_cd_aspect;
}
else if (g_display == MO) { /* Monochrome display */
inregs.h.ah = ega_setmode; /* THIS HAS NOT BEEN TESTED */
inregs.h.al = mde_640X350m;
int86(int_video, &inregs, &outregs);
g_page1addr = g_mo_pg1;
g_page2addr = g_mo_pg2;
g_bufsiz = g_mo_bufsiz;
g_colormask = g_mo_colormask;
g_xsize = g_mo_xsize;
g_ysize = g_mo_ysize;
g_xchsize = g_mo_xchsize;
g_ychsize = g_mo_ychsize;
g_aspect = g_mo_aspect;
}
g_physbuf = g_page1addr;
g_virtbuf = g_page2addr;
g_colormax = g_colormask;
g_pages = 2;
g_curpage = 0;
}
#ifdef __TURBOC__
# pragma warn .par /* TC */
#endif
/* turn off graphics mode */
void EGA_gclose()
{
union REGS inregs, outregs;
inregs.h.ah = ega_setmode;
inregs.h.al = mde_80co;
int86(int_video, &inregs, &outregs);
}
/* setup for point plotting */
void EGA_point_set(c)
unsigned c;
{
trimcolor(c);
outp(ega_gr_addr, ega_gr_sr); /* set/reset register */
outp(ega_gr_data, c);
outp(ega_gr_addr, ega_gr_sren); /* set/reset enable register */
outp(ega_gr_data, g_colormask);
outp(ega_gr_addr, ega_gr_mode); /* mode register */
outp(ega_gr_data, 0); /* write mode 0 */
outp(ega_gr_addr, ega_gr_rot);
outp(ega_gr_data, g_xor ? ega_gr_x_xor : 0); /* set xor mode */
outp(ega_gr_addr, ega_gr_mask); /* set graphics addr to map reg */
}
/* reset ega afterwards */
void EGA_point_res()
{
outp(ega_gr_data, g_allmask); /* to map register */
outp(ega_gr_addr, ega_gr_rot); /* reset ega */
outp(ega_gr_data, 0);
outp(ega_gr_addr, ega_gr_sren);
outp(ega_gr_data, 0);
}
/* plot a point */
/* This fine piece of code has now been supplanted by a weenie hunk
of assembly..... */
/* Well, in this case it really wasn't quite so fine but still... */
/*
void EGA_point(x1,y1,c)
unsigned x1,y1,c;
{
long p;
unsigned pixoff, offs;
g_obj far *ptr;
g_obj mask;
register g_obj tmp;
/* icky, icky, icky! *
EGA_point_set(c);
goffs(x1, y1, &offs, &pixoff);
ptr = g_drawbuf + offs;
mask = 1 << pixoff*g_bitpix;
plot(ptr, mask, tmp); /* plot pt. *
EGA_point_res();
}
*/
/* draw a line... */
#ifdef __TURBOC__
# pragma warn -aus /* TC */
#endif
void EGA_line(x1,y1,x2,y2,c)
unsigned x1,y1,x2,y2,c;
{
unsigned pixoff, offs;
g_obj far *ptr;
int delx,dely;
int xyswap=0;
int ydir=0;
int i,ydelx;
g_obj mask;
register g_obj tmp;
EGA_point_set(c);
if (x1 > x2) { /* sort into left-right order */
register int tmp;
tmp=x1; x1=x2; x2=tmp;
tmp=y1; y1=y2; y2=tmp;
}
goffs(x1, y1, &offs, &pixoff);
ptr = g_drawbuf+offs;
mask = 1 << pixoff*g_bitpix;
plot(ptr, mask, tmp); /* plot pt. */
if (x1==x2 && y1==y2) { /* handle 1 pt. correctly */
EGA_point_res();
return;
}
delx=x2-x1;
dely=y2-y1;
if (dely < 0) { /* handle lines from up to down */
ydir=1;
dely=-dely;
}
if (abs(dely) > delx) { /* handle slopes > 1 */
register int tmp;
tmp=x1; x1=y1; y1=tmp;
tmp=x2; x2=y2; y2=tmp;
tmp=delx; delx=dely; dely=tmp;
xyswap=1;
}
ydelx=0;
for (i=1; i<=delx; i++) {
if ((ydelx+=dely) >= delx) {
bumpx(ptr, mask); /* bump both x & y */
bumpy(ptr, ydir);
ydelx-=delx;
}
else
if (xyswap) /* bump x only */
bumpy(ptr, ydir)
else
bumpx(ptr, mask);
plot(ptr, mask, tmp); /* plot point, go around again */
}
EGA_point_res();
}
#ifdef __TURBOC__
# pragma warn .aus /* TC */
#endif
/* since we're always writing to an EGA buffer, we can use the BIOS
routine! */
void EGA_writech(row, col, ch, c, page)
unsigned row, col, c;
char ch;
int page;
{
union REGS inregs, outregs;
inregs.h.ah = ega_setcur;
inregs.h.dh = row;
inregs.h.dl = col;
inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
int86(int_video, &inregs, &outregs);
inregs.h.ah = ega_writech;
inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
inregs.x.cx = 1;
inregs.h.al = ch;
inregs.h.bl = c /*| (g_xor ? 0x80 : 0)*/;
int86(int_video, &inregs, &outregs);
}