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