[comp.sources.misc] Grafix - a PC graphics library 1/3

ssnyder@tybalt.caltech.edu@elroy.UUCP (Scott S. Snyder) (08/29/87)

  This is the source for a simple graphics library for the CGA and EGA.
It supports point, line, and circle drawing and filling of rectangular
regions. It has been tested with Microsoft C V4.0 and Turbo C V1.0.
Feel free to use it in any way you want (but courtesy would dictate 
that you document any changes you make in redistributed copies).

Scott Snyder
ssnyder@tybalt.caltech.edu or @romeo.caltech.edu or @citromeo.bitnet
..or Caltech, 1-58
     Pasadena, CA 91126

--------------------------- cut here --------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	readme
#	buildmsc.bat
#	buildtc.bat
#	cga.h
#	cgagraf.c
#	cgagrafa.asm
#	ega.h
#	egagraf.c
#	egagrafa.asm
# This archive created: Thu Aug 27 10:09:09 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'readme'" '(577 characters)'
if test -f 'readme'
then
	echo shar: will not over-write existing file "'readme'"
else
sed 's/^X//' << \SHAR_EOF > 'readme'
X
X  Here is the source to my PC CGA/EGA graphics library. It has been tested
Xwith Microsoft C 4.0 and with Turbo C 1.0. To build the libraries for all
Xfour memory models, run 'buildmsc.bat' or 'buildtc.bat'. The documentation
Xis in the doc\ subdirectory, and it is in TeX format. Just TeX 'grafix.tex':
Xit includes everything else. Also in doc\ are two example programs (grafex1.c
Xand grafex2.c). Comments about the package are solicited, especially about
Xthe documentation.
X
XScott Snyder
Xssnyder@romeo.caltech.edu or @citromeo.bitnet
X..or Caltech, 1-58
X     Pasadena, Ca 91126
SHAR_EOF
if test 577 -ne "`wc -c < 'readme'`"
then
	echo shar: error transmitting "'readme'" '(should have been 577 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'buildmsc.bat'" '(504 characters)'
if test -f 'buildmsc.bat'
then
	echo shar: will not over-write existing file "'buildmsc.bat'"
else
sed 's/^X//' << \SHAR_EOF > 'buildmsc.bat'
Xecho off
Xrem
Xrem buildmsc.bat
Xrem
Xrem Builds all four Grafix libraries from scratch using MS C and
Xrem  writes any errors to the file ERRS.
Xrem
Xdel *.obj
Xdel grafixl.lib
Xmake cflags=/AL asmflags=/DLARGE libname=grafixl makemsc >errs
Xdel *.obj
Xdel grafixm.lib
Xmake cflags=/AM asmflags=/DMEDIUM libname=grafixm makemsc >>errs
Xdel *.obj
Xdel grafixc.lib
Xmake cflags=/AC asmflags=/DCOMPACT libname=grafixc makemsc >>errs
Xdel *.obj
Xdel grafix.lib
Xmake cflags=/AS asmflags=/DSMALL libname=grafix makemsc >>errs
SHAR_EOF
if test 504 -ne "`wc -c < 'buildmsc.bat'`"
then
	echo shar: error transmitting "'buildmsc.bat'" '(should have been 504 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'buildtc.bat'" '(534 characters)'
if test -f 'buildtc.bat'
then
	echo shar: will not over-write existing file "'buildtc.bat'"
else
sed 's/^X//' << \SHAR_EOF > 'buildtc.bat'
Xecho off
Xrem
Xrem buildtc.bat
Xrem
Xrem Builds all four Grafix libraries from scratch using Turbo C and
Xrem  writes any errors to the file ERRS.
Xrem
Xdel *.obj
Xdel grafixl.lib
Xmake -Dcflags=-ml -Dasmflags=/DLARGE -Dlibname=grafixl -fmaketc >errs
Xdel *.obj
Xdel grafixm.lib
Xmake -Dcflags=-mm -Dasmflags=/DMEDIUM -Dlibname=grafixm -fmaketc >>errs
Xdel *.obj
Xdel grafixc.lib
Xmake -Dcflags=-mc -Dasmflags=/DCOMPACT -Dlibname=grafixc -fmaketc >>errs
Xdel *.obj
Xdel grafix.lib
Xmake -Dcflags=-ms -Dasmflags=/DSMALL -Dlibname=grafix -fmaketc >>errs
SHAR_EOF
if test 534 -ne "`wc -c < 'buildtc.bat'`"
then
	echo shar: error transmitting "'buildtc.bat'" '(should have been 534 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'cga.h'" '(748 characters)'
if test -f 'cga.h'
then
	echo shar: will not over-write existing file "'cga.h'"
else
sed 's/^X//' << \SHAR_EOF > 'cga.h'
X/*
X * grafix --- cga.h
X *
X * define CGA driver function calls
X *
X * Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
X *
X */
X
Xextern void CGA_regfill(unsigned, unsigned, unsigned, unsigned, unsigned);
Xextern void CGA_clearall(unsigned);
Xextern void CGA_show(void);
Xextern void CGA_setback(unsigned);
Xextern void CGA_setpal(unsigned, unsigned);
Xextern void CGA_gopen(unsigned);
Xextern void CGA_gclose();
Xextern void CGA_point(unsigned, unsigned, unsigned);
Xextern void CGA_line(unsigned, unsigned, unsigned, unsigned, unsigned);
Xextern void CGA_writech(unsigned, unsigned, char, unsigned, int);
Xextern void CGA_write_pix(int, int, int, int, unsigned);
Xextern void CGA_point_set(unsigned);
Xextern void CGA_point_res(void);
SHAR_EOF
if test 748 -ne "`wc -c < 'cga.h'`"
then
	echo shar: error transmitting "'cga.h'" '(should have been 748 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'cgagraf.c'" '(8825 characters)'
if test -f 'cgagraf.c'
then
	echo shar: will not over-write existing file "'cgagraf.c'"
else
sed 's/^X//' << \SHAR_EOF > 'cgagraf.c'
X/*
X * grafix --- cgagraf.c
X *
X * CGA graphics driver
X *
X * Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
X *
X */
X
X#include <dos.h>
X#include "macros.h"
X#include "grafsys.h"
X
X/* parameters that don't depend on graphics mode */
X
X#define int_cga 16
X#define cga_setmode 0
X#define cga_setpal 11
X#define mde_80bw 2
X#define mde_80co 3
X#define mde_320 4
X#define mde_640 6
X#define cid_back 0
X#define cid_pal 1
X
X#define g_linsiz 80
X#define g_oddoff 0x2000
X#define g_allmask 0xff
X#define g_bufsiz 0x4000
X#define g_screenaddr (g_obj far *)0xb8000000
X#define g_charbase (g_obj far *)0xf000fa6e
X
X/* parameters that DO depend on graphics mode */
X
Xunsigned g_mode;
X
X/* these must be near so the .asm routines can get to them */
X
Xunsigned NEAR g_pixbyte;
Xunsigned NEAR g_bitpix;
Xg_obj NEAR g_colormask;
Xg_obj NEAR g_hicolormask;
Xg_obj NEAR g_cmask_tbl[8];
X
X/* utility macros */
X
X#define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
X#define trimcolor(c) c &= g_colormask
X#define get_cmask(c) g_cmask_tbl[c&g_colormask]
X
X/* plot a point */
X#define plot(ptr, mask, cmask) \
X  *ptr = g_xor ? ( *ptr          ^ (cmask & mask)) \
X               : ((*ptr & ~mask) | (cmask & mask))
X
X/* move one to right */
X#define bumpx(ptr,mask) 	    \
X  if ((mask >>= g_bitpix) == 0) {   \
X    mask = g_hicolormask;           \
X    ptr++;                          \
X  }
X
X/* move one line */
X#define bumpy(ptr,ydir)         \
X  if (ptr >= (g_obj far *)(g_drawbuf+g_oddoff)) { \
X    ptr-=g_oddoff;              \
X    if (!ydir)                  \
X      ptr+=g_linsiz;            \
X  }                             \
X  else {                        \
X    ptr+=g_oddoff;              \
X    if (ydir)                   \
X      ptr-=g_linsiz;            \
X  }
X
X/*****************************************************************************
X *                            internal utilities                             *
X *****************************************************************************/
X
X/* calculate byte and bit offsets in the graphics buffer for a point */
X
XSTATIC void goffs(x, y, offs, pix)
Xunsigned x, y, *offs, *pix;
X{
X  int y0;
X
X  y0 = y/2;
X  *offs = y0 * g_linsiz + x/g_pixbyte + ((y0*2 != y) ? g_oddoff : 0);
X  *pix = g_pixbyte - 1 - x%g_pixbyte;
X}
X
X/* fill a mask with the given color value */
X
Xg_obj make_cmask(c)
Xunsigned c;
X{
X  int i;
X  g_obj mask = 0;
X
X  trimcolor(c);
X  for (i=0; i<g_pixbyte; i++)
X    mask = (mask<<g_bitpix) | c;
X  return (mask);
X}
X
X/****************************************************************************
X *                     externally callable functions                        *
X ****************************************************************************/
X
X/* fill a region with the specified color */
X
X#ifdef __TURBOC__
X# pragma warn -rch
X#endif
Xvoid CGA_regfill(x1, y1, x2, y2, c)
Xunsigned x1, y1, x2, y2, c;
X{
X  unsigned offs1, offs2, pix1, pix2, y;
X  int wholeobjs;
X  g_obj far *ptr1, far *ptr2;
X  g_obj cmask, begmask, endmask, mask;
X
X  if (y2 < y1) swap(y1, y2);
X  if (x2 < x1) swap(x1, x2);
X
X  goffs(x1, y1, &offs1, &pix1);
X  goffs(x2, y1, &offs2, &pix2);
X  wholeobjs = offs2 - offs1 - 1;
X  ptr1 = g_drawbuf + offs1;
X  ptr2 = g_drawbuf + offs2;
X
X  cmask = get_cmask(c);
X  begmask = g_allmask >> (g_pixbyte - 1 - pix1)*g_bitpix;
X  endmask = g_allmask << pix2*g_bitpix;
X
X  if (wholeobjs < 0) {
X    mask = begmask & endmask;
X    cmask &= mask;
X    for (y=y1; y<=y2; y++) {
X      *ptr1 = (*ptr1 & ~mask) | cmask;
X      bumpy(ptr1, 0);
X    }
X  }
X  else {
X    for (y=y1; y<=y2; y++) {
X      *ptr1 = (*ptr1 & ~begmask) | (cmask & begmask);
X      g_fmemset(ptr1+1, cmask, wholeobjs);
X      *ptr2 = (*ptr2 & ~endmask) | (cmask & endmask);
X      bumpy(ptr1, 0);
X      ptr2 = ptr1 + wholeobjs + 1;
X    }
X  }
X}
X#ifdef __TURBOC__
X# pragma warn .rch
X#endif
X
X/* fill the entire buffer with a color fast */
X
Xvoid CGA_clearall(c)
Xunsigned c;
X{
X  g_fmemset(g_drawbuf, get_cmask(c), g_bufsiz);
X}
X
X/* make the drawing buffer visible */
X
Xvoid CGA_show()
X{
X  g_fmemcpy(g_physbuf, g_drawbuf, g_bufsiz);
X}
X
X/* set the background color */
X
Xvoid CGA_setback(c)
Xunsigned c;
X{
X  union REGS inregs, outregs;
X
X  if (g_mode == CGA_320) {
X    inregs.h.ah = cga_setpal;
X    inregs.h.bh = cid_back;
X    inregs.h.bl = c;
X    int86(int_cga, &inregs, &outregs);
X  }
X}
X
X/* set the color pallette */
X
Xvoid CGA_setpal(p, v)	/* pallette register number is ignored here */
Xunsigned p, v;
X{
X  union REGS inregs, outregs;
X
X  inregs.h.ah = cga_setpal;
X  if (g_mode == 2) {
X    inregs.h.bh = cid_pal;
X    inregs.h.bl = p;
X  }
X  else {
X    inregs.h.bh = cid_back;
X    inregs.h.bl = v;
X  }
X  int86(int_cga, &inregs, &outregs);
X}
X
X/* turn on graphics mode. mode=1 is 640, mode=2 is 320 */
X
Xvoid CGA_gopen(mode)
Xunsigned mode;
X{
X  union REGS inregs, outregs;
X  unsigned i;
X
X  g_mode = mode;
X  inregs.h.ah = cga_setmode;
X  inregs.h.al = (mode == CGA_640) ? mde_640 : mde_320;
X  int86(int_cga, &inregs, &outregs);
X  g_physbuf = g_screenaddr;
X#if defined(__TURBOC__)
X  g_virtbuf = (g_obj far *)MK_FP(g_bufseg(), 0);
X#else
X  FP_SEG(g_virtbuf) = g_bufseg();
X  FP_OFF(g_virtbuf) = 0;
X#endif
X
X  /* set up mode-dependent parameters */
X
X  if (mode == 1) {
X    g_xsize = 640;
X    g_ysize = 200;
X    g_bitpix = 1;
X    g_aspect = 0.42;
X  }
X  else {
X    g_xsize = 320;
X    g_ysize = 200;
X    g_bitpix = 2;
X    g_aspect = 0.85;
X  }
X  g_pixbyte = 8/g_bitpix;
X  g_xchsize = g_xsize/8;
X  g_ychsize = g_ysize/8;
X  g_colormask = (1<<g_bitpix) - 1;
X  g_hicolormask = g_colormask << (g_pixbyte-1)*g_bitpix;
X  g_colormax = g_colormask;
X  g_pages = 1;
X  g_curpage = 0;
X
X  for (i=0; i<=g_colormask; i++)
X    g_cmask_tbl[i] = make_cmask(i);
X}
X
X/* turn off graphics mode */
X
Xvoid CGA_gclose()
X{
X  union REGS inregs, outregs;
X
X  inregs.h.ah = cga_setmode;
X  inregs.h.al = mde_80co;
X  int86(int_cga, &inregs, &outregs);
X}
X
X/* plot a point */
X
X/* This fine piece of code has now been supplanted by a weenie hunk
X   of assembly.....
X
Xvoid CGA_point(x1,y1,c)
Xunsigned x1,y1,c;
X{
X  long p;
X  unsigned pixoff, offs;
X  g_obj far *ptr;
X  g_obj mask, cmask;
X 
X  goffs(x1, y1, &offs, &pixoff);
X  ptr = g_drawbuf + offs;
X  cmask = get_cmask(c);
X  mask = g_colormask << pixoff*g_bitpix;
X  plot(ptr, mask, cmask);	/* plot pt. *
X}
X*/
X
X/* draw a line... */
X
Xvoid CGA_line(x1,y1,x2,y2,c)
Xunsigned x1,y1,x2,y2,c;
X{
X  unsigned pixoff, offs;
X  g_obj far *ptr;
X  int delx,dely;
X  int xyswap=0;
X  int ydir=0;
X  int i,ydelx;
X  g_obj mask, cmask;
X 
X  if (x1 > x2) { 		/* sort into left-right order */
X    register int tmp;
X    tmp=x1; x1=x2; x2=tmp;
X    tmp=y1; y1=y2; y2=tmp;
X  }
X  goffs(x1, y1, &offs, &pixoff);
X  ptr = g_drawbuf+offs;
X  cmask = get_cmask(c);
X  mask = g_colormask << pixoff*g_bitpix;
X  plot(ptr, mask, cmask);	/* plot pt. */
X  if (x1==x2 && y1==y2)		/* handle 1 pt. correctly */
X    return;
X  delx=x2-x1;
X  dely=y2-y1;
X  if (dely < 0)	{		/* handle lines from up to down */
X    ydir=1;
X    dely=-dely;
X  }
X  if (abs(dely) > delx) {	/* handle slopes > 1 */
X    register int tmp;
X    tmp=x1;   x1=y1;     y1=tmp;
X    tmp=x2;   x2=y2;     y2=tmp;
X    tmp=delx; delx=dely; dely=tmp;
X    xyswap=1;
X  }
X  ydelx=0;
X  for (i=1; i<=delx; i++) {
X    if ((ydelx+=dely) >= delx) {
X      bumpx(ptr, mask);		/* bump both x & y */
X      bumpy(ptr, ydir);
X      ydelx-=delx;
X    }
X    else
X      if (xyswap)		/* bump x only */
X        bumpy(ptr, ydir)
X      else
X        bumpx(ptr, mask);
X    plot(ptr, mask, cmask);	/* plot point, go around again */
X  }
X}
X
X/* print a character. this is really kind of cheap, and can/should
X   be expanded later... */
X
X#ifdef __TURBOC__
X# pragma warn -par /* TC */
X# pragma warn -rch
X#endif
Xvoid CGA_writech(row, col, ch, c, page)
Xunsigned row, col, c;
Xchar ch;
Xint page;
X{
X  unsigned x, y, pixoff, offs;
X  g_obj cmask, chdat, gdat;
X  g_obj far *ptr, far *pptr, far *chpt;
X  int i, j, k;
X
X  x = col*8;			/* character is 8 X 8 */
X  y = row*8;
X  if (x >= g_xsize || y >= g_ysize)
X    return;
X  trimcolor(c);
X  cmask = get_cmask(c);
X  goffs(x, y, &offs, &pixoff);	/* pixoff should be 0 */
X  ptr = g_drawbuf + offs;
X  chpt = g_charbase + 8*ch;	/* pointer to character data */
X  for (i=0; i<8; i++) {		/* loop for each line        */
X    chdat = *chpt++;		/* get character data        */
X    if (g_bitpix == 1)
X      *ptr = chdat & cmask;
X    else {
X      pptr = ptr;
X      for (j=0; j<g_bitpix; j++) { /* g_bitpix is the # of bytes per ch */
X        gdat = 0;
X        for (k=0; k<g_pixbyte; k++) {
X          gdat = (gdat << g_bitpix) + (chdat&0x80 ? c : 0);
X          chdat <<= 1;
X        }
X        *pptr++ = gdat;
X      }
X    }
X    bumpy(ptr, 0);
X  }
X}
X#ifdef __TURBOC__
X# pragma warn .par /* TC */
X# pragma warn .rch
X#endif
X
X/* these two thingamabobs don't do anything */
X
X#ifdef __TURBOC__
X# pragma warn -par /* TC */
X#endif
Xvoid CGA_point_set(c)
Xunsigned c;
X{
X}
X#ifdef __TURBOC__
X# pragma warn .par /* TC */
X#endif
X
Xvoid CGA_point_res()
X{
X}
SHAR_EOF
if test 8825 -ne "`wc -c < 'cgagraf.c'`"
then
	echo shar: error transmitting "'cgagraf.c'" '(should have been 8825 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'cgagrafa.asm'" '(2858 characters)'
if test -f 'cgagrafa.asm'
then
	echo shar: will not over-write existing file "'cgagrafa.asm'"
else
sed 's/^X//' << \SHAR_EOF > 'cgagrafa.asm'
X;
X; grafix --- cgagrafa.asm
X;
X; stuff to plot points fast in 8086 assembler (BLEECH!!!)
X;
X; Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
X;
X; Modified 5/29/87 by sss to allow for different memory models
X;
X
X	title	cgagrafa
X
Xinclude macros.ah
X
X	df CGA_point
X	df CGA_write_pix
X
Xsseg
Xendss
X
Xg_oddoff equ	02000h
Xg_linsiz equ	80
X
Xdseg
X
X	ex g_drawbuf,     dword
X	ex g_pixbyte,     word
X	ex g_bitpix,      word
X	ex g_colormask,   byte
X	ex g_cmask_tbl,   byte
X	ex g_hicolormask, byte
X	ex g_xor,         word
X	ex g_xcliplo,     word
X	ex g_xcliphi,     word
X	ex g_ycliplo,     word
X	ex g_ycliphi,     word
X
Xendds
X
Xcseg _cgagrafa
X
X; plot a point. ax = y; bl = c; cx = x;
X
XpBegin	plot
X
X	les	si, g_drawbuf		; get address of buffer
X	sar	ax, 1			; y /= 2
X	jnc	p1			; add in offset if it was odd
X	add	si, g_oddoff
Xp1:	mov	dx, g_linsiz		; y * g_linsiz
X	mul	dx
X	add	si, ax			; add to offset
X	mov	ax, cx			; x to AC (ohhh... what symmetry!)
X	mov	dx, 0
X	div	g_pixbyte
X	add	si, ax			; add quotient to offset (now complete)
X	and	bl, g_colormask		; get cmask
X	mov	bl, g_cmask_tbl[bx]
X	mov	cx, g_bitpix		; only works for bitpix = 0 or 1!
X	dec	cx
X	shl	dx, cl			; dx = mask shift count
X	mov	cx, dx
X	mov	dl, g_hicolormask	; get mask
X	shr	dl, cl			; shift it
X	and	bx, dx			; bx = cmask & mask
X	mov	al, es:[si]		; get image byte
X	cmp	g_xor, 0		; xor mode?
X	jne	p2
X	not	dl			; no - (*ptr & ~mask) | (cmask & mask)
X	and	al, dl
X	or	al, bl
X	jmp	p3
Xp2:	xor	al, bl			; yes - *ptr ^ (cmask & mask)
Xp3:	mov	es:[si], al		; done!
X	ret
X
XpEnd	plot
X
X;
X; C interface for point plotter
X;
X; CGA_point(x, y, c)
X;
X
XpBegin	CGA_point
X	push	bp
X	mov	bp, sp
X	push	si
X	push	di
X
X	mov	ax, [bp+argbase+2]
X	mov	bx, [bp+argbase+4]
X	mov	cx, [bp+argbase]
X	call	plot
X
X	pop	di
X	pop	si
X	mov	sp, bp
X	pop	bp
X	ret
X
XpEnd	CGA_point
X
X;
X; write for pixels for circle drawing
X;
X; void CGA_write_pix(x1, y1, x2, y2, c)
X;
X
XpBegin	CGA_write_pix
X
X	push	bp
X	mov	bp, sp
X	push	si
X	push	di
X
X	mov	bx, [bp+argbase+8]	; bx = c (for plot)
X	mov	cx, [bp+argbase]	; cx = x1
X	cmp	cx, g_xcliplo		; check for clipping
X	jb	w2
X	cmp	cx, g_xcliphi
X	ja	w2
X
X	mov	ax, [bp+argbase+2]	; ax = y1
X	cmp	ax, g_ycliplo		; do clipping
X	jb	w1
X	cmp	ax, g_ycliphi
X	ja	w1
X
X	push	bx			; plot (x1, y1)
X	push	cx
X	call	plot
X	pop	cx
X	pop	bx
X
Xw1:	mov	ax, [bp+argbase+6]	; ax = y2
X	cmp	ax, g_ycliplo
X	jb	w2
X	cmp	ax, g_ycliphi
X	ja	w2
X
X	push	bx			; plot (x1, y2)
X	call	plot
X	pop	bx
X
Xw2:	mov	cx, [bp+argbase+4]	; cx = x2
X	cmp	cx, g_xcliplo
X	jb	w4
X	cmp	cx, g_xcliphi
X	ja	w4
X
X	mov	ax, [bp+argbase+2]	; ax = y1
X	cmp	ax, g_ycliplo		; do clipping
X	jb	w3
X	cmp	ax, g_ycliphi
X	ja	w3
X
X	push	bx			; plot (x2, y1)
X	push	cx
X	call	plot
X	pop	cx
X	pop	bx
X
Xw3:	mov	ax, [bp+argbase+6]	; ax = y2
X	cmp	ax, g_ycliplo
X	jb	w4
X	cmp	ax, g_ycliphi
X	ja	w4
X
X	call	plot			; plot (x2, y2)
X
Xw4:	pop	di
X	pop	si
X	mov	sp, bp
X	pop	bp
X	ret
X
XpEnd	CGA_write_pix
X
Xendcs	_cgagrafa
X
Xend
SHAR_EOF
if test 2858 -ne "`wc -c < 'cgagrafa.asm'`"
then
	echo shar: error transmitting "'cgagrafa.asm'" '(should have been 2858 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ega.h'" '(694 characters)'
if test -f 'ega.h'
then
	echo shar: will not over-write existing file "'ega.h'"
else
sed 's/^X//' << \SHAR_EOF > 'ega.h'
X/*
X * grafix --- ega.h
X *
X * define EGA driver function calls
X *
X * Copyright Caltech 1987
X *
X */
X
Xextern void EGA_regfill(unsigned, unsigned, unsigned, unsigned, unsigned);
Xextern void EGA_clearall(unsigned);
Xextern void EGA_show(void);
Xextern void EGA_setback(unsigned);
Xextern void EGA_setpal(unsigned, unsigned);
Xextern void EGA_gopen(unsigned);
Xextern void EGA_gclose();
Xextern void EGA_point(unsigned, unsigned, unsigned);
Xextern void EGA_line(unsigned, unsigned, unsigned, unsigned, unsigned);
Xextern void EGA_writech(unsigned, unsigned, char, unsigned, int);
Xextern void EGA_write_pix(int, int, int, int, unsigned);
Xextern void EGA_point_set(unsigned);
Xextern void EGA_point_res(void);
SHAR_EOF
if test 694 -ne "`wc -c < 'ega.h'`"
then
	echo shar: error transmitting "'ega.h'" '(should have been 694 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'egagraf.c'" '(12500 characters)'
if test -f 'egagraf.c'
then
	echo shar: will not over-write existing file "'egagraf.c'"
else
sed 's/^X//' << \SHAR_EOF > 'egagraf.c'
X/*
X * grafix --- egagraf.c
X *
X * EGA graphics driver - hi-res mode only (on enhanced, ordinary, or
X *                         mono (i hope it works!) display)
X *
X * Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
X *
X */
X
X#include <dos.h>
X#include "macros.h"
X#include "grafsys.h"
X
X/* EGA parameters */
X
X#define int_video 16
X#define ega_setmode 0
X#define ega_setcur 2
X#define ega_setpage 5
X#define ega_writech 9
X#define ega_setpal 0x10
X#define mde_80bw 2
X#define mde_80co 3
X#define mde_320 4
X#define mde_640 6
X#define mde_640X200c 14
X#define mde_640X350m 15
X#define mde_640X350c 16
X
X#define g_linsiz 80
X#define g_allmask 0xff
X#define g_pixbyte 8
X#define g_bitpix 1
X
X/* Display dependent parameters */
X
X#define g_en_pg1       (g_obj far *)0xa0000000
X#define g_en_pg2       (g_obj far *)0xa0008000
X#define g_en_bufsiz    28000
X#define g_en_colormask 0x0f
X#define g_en_xsize     640
X#define g_en_ysize     350
X#define g_en_xchsize   (g_en_xsize / 8)
X#define g_en_ychsize   (g_en_ysize / 14)
X#define g_en_aspect    0.85
X
X#define g_cd_pg1       (g_obj far *)0xa0000000
X#define g_cd_pg2       (g_obj far *)0xa0004000
X#define g_cd_bufsiz    16000
X#define g_cd_colormask 0x0f
X#define g_cd_xsize     640
X#define g_cd_ysize     200
X#define g_cd_xchsize   (g_cd_xsize / 8)
X#define g_cd_ychsize   (g_cd_ysize / 8)
X#define g_cd_aspect    0.43
X
X#define g_mo_pg1       (g_obj far *)0xa0000000
X#define g_mo_pg2       (g_obj far *)0xa0008000	/* is this right??? */
X#define g_mo_bufsiz    28000
X#define g_mo_colormask 0x03
X#define g_mo_xsize     640
X#define g_mo_ysize     350
X#define g_mo_xchsize   (g_mo_xsize / 8)
X#define g_mo_ychsize   (g_mo_ysize / 14)
X#define g_mo_aspect    0.85
X
X/* EGA port and register addresses */
X
X#define ega_gr_addr   0x3ce	/* graphics controller address register */
X#define ega_gr_data   0x3cf	/* graphics controller data register    */
X#define ega_gr_sr     0		/* set/reset register index		*/
X#define ega_gr_sren   1		/* set/reset enable register index	*/
X#define ega_gr_ccmp   2		/* color compare register index		*/
X#define ega_gr_rot    3		/* data rotate				*/
X#define ega_gr_mapsel 4		/* read map select			*/
X#define ega_gr_mode   5		/* mode register			*/
X#define ega_gr_misc   6		/* miscellaneous			*/
X#define ega_gr_colorx 7		/* color don't care			*/
X#define ega_gr_mask   8		/* bit mask				*/
X#define ega_gr_x_xor  24	/* xor function select			*/
X
X/* mode variables */
X
XSTATIC unsigned g_bufsiz;
XSTATIC unsigned g_colormask;
XSTATIC g_obj far *g_page1addr, far *g_page2addr;
X
X/* utility macros */
X
X#define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
X#define trimcolor(c) c &= g_colormask
X
X#define plot(ptr, mask, tmp) { 	/* plot a pt. grph addr. must be mask reg */ \
X  outp(ega_gr_data, mask); 						     \
X  tmp = *ptr;			/* a read and a write that will STAY HERE!! */\
X  *ptr = 0;								     \
X}
X
X/* move one to right */
X#define bumpx(ptr,mask) 	    \
X  if ((mask >>= g_bitpix) == 0) {   \
X    mask = 0x80;                    \
X    ptr++;                          \
X  }
X
X/* move one line */
X#define bumpy(ptr,ydir) { \
X  if (ydir)		  \
X    ptr-=g_linsiz;	  \
X  else			  \
X    ptr+=g_linsiz;	  \
X}
X
X/****************************************************************************\
X*                             internal utilities                             *
X\****************************************************************************/
X
X/* calculate byte and bit offsets in the graphics buffer for a point */
X
XSTATIC void goffs(x, y, offs, pix)
Xunsigned x, y, *offs, *pix;
X{
X  *offs = y*g_linsiz + x/g_pixbyte;
X  *pix = g_pixbyte - 1 - x%g_pixbyte;
X}
X
X/****************************************************************************
X *                     externally callable functions                        *
X ****************************************************************************/
X
X/* fill a region with the specified color */
X
X#ifdef __TURBOC__
X# pragma warn -aus /* TC */
X# pragma warn -rch
X#endif
Xvoid EGA_regfill(x1, y1, x2, y2, c)
Xunsigned x1, y1, x2, y2, c;
X{
X  unsigned offs1, offs2, pix1, pix2;
X  int wholeobjs;
X  g_obj far *ptr1, far *ptr2;
X  g_obj begmask, endmask, mask;
X  register unsigned y;
X  register g_obj far *p;
X  register g_obj tmp;
X
X  if (y2 < y1) swap(y1, y2);
X  if (x2 < x1) swap(x1, x2);
X
X  goffs(x1, y1, &offs1, &pix1);
X  goffs(x2, y1, &offs2, &pix2);
X  wholeobjs = offs2 - offs1 - 1;
X  ptr1 = g_drawbuf + offs1;
X  ptr2 = g_drawbuf + offs2;
X
X  trimcolor(c);
X  begmask = g_allmask >> (g_pixbyte - 1 - pix1)*g_bitpix;
X  endmask = g_allmask << pix2*g_bitpix;
X
X  /* set up EGA registers for write */
X
X  outp(ega_gr_addr, ega_gr_sr);		/* set/reset register           */
X  outp(ega_gr_data, c);
X  outp(ega_gr_addr, ega_gr_sren);	/* set/reset enable register    */
X  outp(ega_gr_data, g_colormask);
X  outp(ega_gr_addr, ega_gr_mode);	/* mode register        	*/
X  outp(ega_gr_data, 0);			/* write mode 0			*/
X  outp(ega_gr_addr, ega_gr_mask);	/* select bit mask register	*/
X
X  /* do the write */
X
X  if (wholeobjs < 0) {			/* region is less than 8 pels wide */
X    p = ptr1;
X    mask = begmask & endmask;
X    outp(ega_gr_data, mask);		/* set bitmask for writes	*/
X    for (y=y1; y<=y2; y++) {
X      tmp = *p;				/* read byte into latches	*/
X      *p = 0;				/* then write there to set the	*/
X					/* bits				*/
X      bumpy(p, 0);
X    }
X  }
X  else {
X    p = ptr1;				/* do left edge 		*/
X    outp(ega_gr_data, begmask);
X    for (y=y1; y<=y2; y++) {
X      tmp = *p;
X      *p = 0;
X      bumpy(p, 0);
X    }
X
X    p = ptr2;				/* do right egde		*/
X    outp(ega_gr_data, endmask);
X    for (y=y1; y<=y2; y++) {
X      tmp = *p;
X      *p = 0;
X      bumpy(p, 0);
X    }
X
X    p = ptr1+1;				/* now fill it in		*/
X    outp(ega_gr_data, g_allmask);
X    for (y=y1; y<=y2; y++) {
X      g_fmemset(p, g_allmask, wholeobjs); /* can write it with anything here */
X      bumpy(p, 0);
X    }
X  }
X
X  /* reset the EGA to something nice */
X
X  outp(ega_gr_data, g_allmask);		/* reset bit mask		*/
X  outp(ega_gr_addr, ega_gr_sren);	/* disable set/reset mode	*/
X  outp(ega_gr_data, 0);
X}
X#ifdef __TURBOC__
X# pragma warn .aus /* TC */
X# pragma warn .rch
X#endif
X
X/* fill the entire buffer with a color fast */
X
Xvoid EGA_clearall(c)
Xunsigned c;
X{
X  /* set up EGA registers for write */
X
X  outp(ega_gr_addr, ega_gr_sr);		/* set/reset register           */
X  outp(ega_gr_data, c);
X  outp(ega_gr_addr, ega_gr_sren);	/* set/reset enable register    */
X  outp(ega_gr_data, g_colormask);
X  outp(ega_gr_addr, ega_gr_mode);	/* mode register        	*/
X  outp(ega_gr_data, 0);			/* write mode 0			*/
X
X  g_fmemset(g_drawbuf, g_allmask, g_bufsiz);
X
X  outp(ega_gr_addr, ega_gr_sren);	/* disable set/reset mode	*/
X  outp(ega_gr_data, 0);
X}
X
X/* make the drawing buffer visible by switching pages */
X
Xvoid EGA_show()
X{
X  union REGS inregs, outregs;
X
X  if (g_bufflg) {
X    g_curpage = 1-g_curpage;
X    inregs.h.ah = ega_setpage;
X    inregs.h.al = g_curpage;
X    int86(int_video, &inregs, &outregs);
X
X    g_drawbuf = g_physbuf;		/* swap around buffer pointers */
X    g_physbuf = g_virtbuf;
X    g_virtbuf = g_drawbuf;    
X  }
X}
X
X/* set the color pallette */
X
Xvoid EGA_setpal(p, v)
Xunsigned p, v;
X{
X  union REGS inregs, outregs;
X
X  inregs.h.ah = ega_setpal;
X  inregs.h.al = 0;
X  inregs.h.bl = p;
X  inregs.h.bh = v;
X  int86(int_video, &inregs, &outregs);
X}
X
X/* set the background color - just use setpal() */
X
Xvoid EGA_setback(c)
Xunsigned c;
X{
X  EGA_setpal(0, c);
X}
X
X/* turn on graphics mode. mode has no meaning */
X
X#ifdef __TURBOC__
X# pragma warn -par /* TC */
X#endif
Xvoid EGA_gopen(mode)
Xunsigned mode;
X{
X  union REGS inregs, outregs;
X
X  if (g_display == EN) {		/* Enhanced color display	*/
X    inregs.h.ah = ega_setmode;
X    inregs.h.al = mde_640X350c;
X    int86(int_video, &inregs, &outregs);
X    g_page1addr = g_en_pg1;
X    g_page2addr = g_en_pg2;
X    g_bufsiz = g_en_bufsiz;
X    g_colormask = g_en_colormask;
X    g_xsize = g_en_xsize;
X    g_ysize = g_en_ysize;
X    g_xchsize = g_en_xchsize;
X    g_ychsize = g_en_ychsize;
X    g_aspect = g_en_aspect;
X  }
X  else if (g_display == CD) {		/* Ordinary color display	*/
X    inregs.h.ah = ega_setmode;
X    inregs.h.al = mde_640X200c;
X    int86(int_video, &inregs, &outregs);
X    g_page1addr = g_cd_pg1;
X    g_page2addr = g_cd_pg2;
X    g_bufsiz = g_cd_bufsiz;
X    g_colormask = g_cd_colormask;
X    g_xsize = g_cd_xsize;
X    g_ysize = g_cd_ysize;
X    g_xchsize = g_cd_xchsize;
X    g_ychsize = g_cd_ychsize;
X    g_aspect = g_cd_aspect;
X  }
X  else if (g_display == MO) {			/* Monochrome display	*/
X    inregs.h.ah = ega_setmode;			/* THIS HAS NOT BEEN TESTED */
X    inregs.h.al = mde_640X350m;
X    int86(int_video, &inregs, &outregs);
X    g_page1addr = g_mo_pg1;
X    g_page2addr = g_mo_pg2;
X    g_bufsiz = g_mo_bufsiz;
X    g_colormask = g_mo_colormask;
X    g_xsize = g_mo_xsize;
X    g_ysize = g_mo_ysize;
X    g_xchsize = g_mo_xchsize;
X    g_ychsize = g_mo_ychsize;
X    g_aspect = g_mo_aspect;
X  }
X
X  g_physbuf = g_page1addr;
X  g_virtbuf = g_page2addr;
X  g_colormax = g_colormask;
X  g_pages = 2;
X  g_curpage = 0;
X}
X#ifdef __TURBOC__
X# pragma warn .par /* TC */
X#endif
X
X/* turn off graphics mode */
X
Xvoid EGA_gclose()
X{
X  union REGS inregs, outregs;
X
X  inregs.h.ah = ega_setmode;
X  inregs.h.al = mde_80co;
X  int86(int_video, &inregs, &outregs);
X}
X
X/* setup for point plotting */
X
Xvoid EGA_point_set(c)
Xunsigned c;
X{
X  trimcolor(c);
X  outp(ega_gr_addr, ega_gr_sr);		/* set/reset register           */
X  outp(ega_gr_data, c);
X  outp(ega_gr_addr, ega_gr_sren);	/* set/reset enable register    */
X  outp(ega_gr_data, g_colormask);
X  outp(ega_gr_addr, ega_gr_mode);	/* mode register        	*/
X  outp(ega_gr_data, 0);			/* write mode 0			*/
X  outp(ega_gr_addr, ega_gr_rot);
X  outp(ega_gr_data, g_xor ? ega_gr_x_xor : 0);	/* set xor mode		*/
X  outp(ega_gr_addr, ega_gr_mask);	/* set graphics addr to map reg */
X}
X
X/* reset ega afterwards */
X
Xvoid EGA_point_res()
X{
X  outp(ega_gr_data, g_allmask);		/* to map register		*/
X  outp(ega_gr_addr, ega_gr_rot);	/* reset ega */
X  outp(ega_gr_data, 0);
X  outp(ega_gr_addr, ega_gr_sren);
X  outp(ega_gr_data, 0);
X}
X
X/* plot a point */
X
X
X/* This fine piece of code has now been supplanted by a weenie hunk
X   of assembly.....  */
X/* Well, in this case it really wasn't quite so fine but still...   */
X/*
Xvoid EGA_point(x1,y1,c)
Xunsigned x1,y1,c;
X{
X  long p;
X  unsigned pixoff, offs;
X  g_obj far *ptr;
X  g_obj mask;
X  register g_obj tmp;
X
X  /* icky, icky, icky! *
X
X  EGA_point_set(c); 
X 
X  goffs(x1, y1, &offs, &pixoff);
X  ptr = g_drawbuf + offs;
X  mask = 1 << pixoff*g_bitpix;
X  plot(ptr, mask, tmp);			/* plot pt. *
X
X  EGA_point_res();
X}
X*/
X/* draw a line... */
X
X#ifdef __TURBOC__
X# pragma warn -aus /* TC */
X#endif
Xvoid EGA_line(x1,y1,x2,y2,c)
Xunsigned x1,y1,x2,y2,c;
X{
X  unsigned pixoff, offs;
X  g_obj far *ptr;
X  int delx,dely;
X  int xyswap=0;
X  int ydir=0;
X  int i,ydelx;
X  g_obj mask;
X  register g_obj tmp;
X
X  EGA_point_set(c);
X 
X  if (x1 > x2) { 		/* sort into left-right order */
X    register int tmp;
X    tmp=x1; x1=x2; x2=tmp;
X    tmp=y1; y1=y2; y2=tmp;
X  }
X  goffs(x1, y1, &offs, &pixoff);
X  ptr = g_drawbuf+offs;
X  mask = 1 << pixoff*g_bitpix;
X  plot(ptr, mask, tmp);		/* plot pt. */
X  if (x1==x2 && y1==y2) {	/* handle 1 pt. correctly */
X    EGA_point_res();
X    return;
X  }
X  delx=x2-x1;
X  dely=y2-y1;
X  if (dely < 0)	{		/* handle lines from up to down */
X    ydir=1;
X    dely=-dely;
X  }
X  if (abs(dely) > delx) {	/* handle slopes > 1 */
X    register int tmp;
X    tmp=x1;   x1=y1;     y1=tmp;
X    tmp=x2;   x2=y2;     y2=tmp;
X    tmp=delx; delx=dely; dely=tmp;
X    xyswap=1;
X  }
X  ydelx=0;
X  for (i=1; i<=delx; i++) {
X    if ((ydelx+=dely) >= delx) {
X      bumpx(ptr, mask);		/* bump both x & y */
X      bumpy(ptr, ydir);
X      ydelx-=delx;
X    }
X    else
X      if (xyswap)		/* bump x only */
X        bumpy(ptr, ydir)
X      else
X        bumpx(ptr, mask);
X    plot(ptr, mask, tmp);	/* plot point, go around again */
X  }
X  EGA_point_res();
X}
X#ifdef __TURBOC__
X# pragma warn .aus /* TC */
X#endif
X
X/* since we're always writing to an EGA buffer, we can use the BIOS
X   routine! */
X
Xvoid EGA_writech(row, col, ch, c, page)
Xunsigned row, col, c;
Xchar ch;
Xint page;
X{
X  union REGS inregs, outregs;
X
X  inregs.h.ah = ega_setcur;
X  inregs.h.dh = row;
X  inregs.h.dl = col;
X  inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
X  int86(int_video, &inregs, &outregs);
X
X  inregs.h.ah = ega_writech;
X  inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
X  inregs.x.cx = 1;
X  inregs.h.al = ch;
X  inregs.h.bl = c /*| (g_xor ? 0x80 : 0)*/;
X  int86(int_video, &inregs, &outregs);
X}
SHAR_EOF
if test 12500 -ne "`wc -c < 'egagraf.c'`"
then
	echo shar: error transmitting "'egagraf.c'" '(should have been 12500 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'egagrafa.asm'" '(2624 characters)'
if test -f 'egagrafa.asm'
then
	echo shar: will not over-write existing file "'egagrafa.asm'"
else
sed 's/^X//' << \SHAR_EOF > 'egagrafa.asm'
X;
X; grafix --- egagrafa.asm
X;
X; stuff to plot points fast in 8086 assembler (BLEECH!!!)
X;
X; Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
X;
X; Modified 5/29/87 by sss to allow for different memory models
X;
X
X	title	egagrafa
X
Xinclude macros.ah
X
X	df EGA_point
X	df EGA_write_pix
X	df EGA_plot
X
Xsseg
Xendss
X
Xg_linsiz  equ	80
Xg_pixbyte equ	8
Xega_gr_data equ 03cfh
X
Xdseg
X
X	ex g_drawbuf,     dword
X	ex g_xor,         word
X	ex g_xcliplo,     word
X	ex g_xcliphi,     word
X	ex g_ycliplo,     word
X	ex g_ycliphi,     word
X
Xendds
X
X	exProc EGA_point_set
X	exProc EGA_point_res
X
Xcseg	_egagrafa
X
XEGA_plot label byte			; to get accurate profiling data
X
X; plot a point. ax = y; bl = c; cx = x;
X
XpBegin	plot
X
X	les	si, g_drawbuf		; get address of buffer
X	mov	dx, g_linsiz		; y * g_linsiz
X	mul	dx
X	add	si, ax			; add to offset
X	mov	ax, cx			; x to AC (ohhh... what symmetry!)
X	mov	cx, g_pixbyte		; move it to use it...
X	div	cx
X	add	si, ax			; add quotient to offset (now complete)
X	mov	al, 80h			; make mask
X	mov	cx, dx
X	shr	ax, cl			; shift it
X	mov	dx, ega_gr_data		; shove it out to the mask register
X	out	dx, al
X	mov	al, es:[si]		; read data into latches
X	mov	es:[si], al		; and do a write
X	ret
X
XpEnd	plot
X
X;
X; C interface for point plotter
X;
X; EGA_point(x, y, c)
X;
X
XpBegin	EGA_point
X
X	push	bp
X	mov	bp, sp
X	push	si
X	push	di
X
X	push	[bp+argbase+4]			; call setup routine
X	call	EGA_point_set
X	add	sp, 2
X
X	mov	ax, [bp+argbase+2]
X	mov	bx, [bp+argbase+4]
X	mov	cx, [bp+argbase]
X	call	plot
X
X	call	EGA_point_res		; reset EGA
X
X	pop	di
X	pop	si
X	mov	sp, bp
X	pop	bp
X	ret
X
XpEnd	EGA_point
X
X;
X; write for pixels for circle drawing
X;
X; void EGA_write_pix(x1, y1, x2, y2, c)
X;
X; can just ignore color here 'cause that's all setup at setup time...
X;
X
XpBegin	EGA_write_pix
X
X	push	bp
X	mov	bp, sp
X	push	si
X	push	di
X
X	mov	cx, [bp+argbase]	; cx = x1
X	cmp	cx, g_xcliplo		; check for clipping
X	jb	w2
X	cmp	cx, g_xcliphi
X	ja	w2
X
X	mov	ax, [bp+argbase+2]	; ax = y1
X	cmp	ax, g_ycliplo		; do clipping
X	jb	w1
X	cmp	ax, g_ycliphi
X	ja	w1
X
X	push	cx			; plot (x1, y1)
X	call	plot
X	pop	cx
X
Xw1:	mov	ax, [bp+argbase+6]	; ax = y2
X	cmp	ax, g_ycliplo
X	jb	w2
X	cmp	ax, g_ycliphi
X	ja	w2
X
X	call	plot			; plot (x1, y2)
X
Xw2:	mov	cx, [bp+argbase+4]	; cx = x2
X	cmp	cx, g_xcliplo
X	jb	w4
X	cmp	cx, g_xcliphi
X	ja	w4
X
X	mov	ax, [bp+argbase+2]	; ax = y1
X	cmp	ax, g_ycliplo		; do clipping
X	jb	w3
X	cmp	ax, g_ycliphi
X	ja	w3
X
X	push	cx			; plot (x2, y1)
X	call	plot
X	pop	cx
X
Xw3:	mov	ax, [bp+argbase+6]	; ax = y2
X	cmp	ax, g_ycliplo
X	jb	w4
X	cmp	ax, g_ycliphi
X	ja	w4
X
X	call	plot			; plot (x2, y2)
X
Xw4:	pop	di
X	pop	si
X	mov	sp, bp
X	pop	bp
X	ret
X
XpEnd	EGA_write_pix
X
Xendcs	_egagrafa
X
Xend
SHAR_EOF
if test 2624 -ne "`wc -c < 'egagrafa.asm'`"
then
	echo shar: error transmitting "'egagrafa.asm'" '(should have been 2624 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exiadd