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