⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 egagraf.c

📁 MSC TURBO-C图形库
💻 C
字号:
/*
 * grafix --- egagraf.c
 *
 * EGA graphics driver - hi-res mode only (on enhanced, ordinary, or
 *                         mono (i hope it works!) display)
 *
 * Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
 *
 */

#include <dos.h>
#include "macros.h"
#include "grafsys.h"

/* EGA parameters */

#define int_video 16
#define ega_setmode 0
#define ega_setcur 2
#define ega_setpage 5
#define ega_writech 9
#define ega_setpal 0x10
#define mde_80bw 2
#define mde_80co 3
#define mde_320 4
#define mde_640 6
#define mde_640X200c 14
#define mde_640X350m 15
#define mde_640X350c 16

#define g_linsiz 80
#define g_allmask 0xff
#define g_pixbyte 8
#define g_bitpix 1

/* Display dependent parameters */

#define g_en_pg1       (g_obj far *)0xa0000000
#define g_en_pg2       (g_obj far *)0xa0008000
#define g_en_bufsiz    28000
#define g_en_colormask 0x0f
#define g_en_xsize     640
#define g_en_ysize     350
#define g_en_xchsize   (g_en_xsize / 8)
#define g_en_ychsize   (g_en_ysize / 14)
#define g_en_aspect    0.85

#define g_cd_pg1       (g_obj far *)0xa0000000
#define g_cd_pg2       (g_obj far *)0xa0004000
#define g_cd_bufsiz    16000
#define g_cd_colormask 0x0f
#define g_cd_xsize     640
#define g_cd_ysize     200
#define g_cd_xchsize   (g_cd_xsize / 8)
#define g_cd_ychsize   (g_cd_ysize / 8)
#define g_cd_aspect    0.43

#define g_mo_pg1       (g_obj far *)0xa0000000
#define g_mo_pg2       (g_obj far *)0xa0008000	/* is this right??? */
#define g_mo_bufsiz    28000
#define g_mo_colormask 0x03
#define g_mo_xsize     640
#define g_mo_ysize     350
#define g_mo_xchsize   (g_mo_xsize / 8)
#define g_mo_ychsize   (g_mo_ysize / 14)
#define g_mo_aspect    0.85

/* EGA port and register addresses */

#define ega_gr_addr   0x3ce	/* graphics controller address register */
#define ega_gr_data   0x3cf	/* graphics controller data register    */
#define ega_gr_sr     0		/* set/reset register index		*/
#define ega_gr_sren   1		/* set/reset enable register index	*/
#define ega_gr_ccmp   2		/* color compare register index		*/
#define ega_gr_rot    3		/* data rotate				*/
#define ega_gr_mapsel 4		/* read map select			*/
#define ega_gr_mode   5		/* mode register			*/
#define ega_gr_misc   6		/* miscellaneous			*/
#define ega_gr_colorx 7		/* color don't care			*/
#define ega_gr_mask   8		/* bit mask				*/
#define ega_gr_x_xor  24	/* xor function select			*/

/* mode variables */

STATIC unsigned g_bufsiz;
STATIC unsigned g_colormask;
STATIC g_obj far *g_page1addr, far *g_page2addr;

/* utility macros */

#define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
#define trimcolor(c) c &= g_colormask

#define plot(ptr, mask, tmp) { 	/* plot a pt. grph addr. must be mask reg */ \
  outp(ega_gr_data, mask); 						     \
  tmp = *ptr;			/* a read and a write that will STAY HERE!! */\
  *ptr = 0;								     \
}

/* move one to right */
#define bumpx(ptr,mask) 	    \
  if ((mask >>= g_bitpix) == 0) {   \
    mask = 0x80;                    \
    ptr++;                          \
  }

/* move one line */
#define bumpy(ptr,ydir) { \
  if (ydir)		  \
    ptr-=g_linsiz;	  \
  else			  \
    ptr+=g_linsiz;	  \
}

/****************************************************************************\
*                             internal utilities                             *
\****************************************************************************/

/* calculate byte and bit offsets in the graphics buffer for a point */

STATIC void goffs(x, y, offs, pix)
unsigned x, y, *offs, *pix;
{
  *offs = y*g_linsiz + x/g_pixbyte;
  *pix = g_pixbyte - 1 - x%g_pixbyte;
}

/****************************************************************************
 *                     externally callable functions                        *
 ****************************************************************************/

/* fill a region with the specified color */

#ifdef __TURBOC__
# pragma warn -aus /* TC */
# pragma warn -rch
#endif
void EGA_regfill(x1, y1, x2, y2, c)
unsigned x1, y1, x2, y2, c;
{
  unsigned offs1, offs2, pix1, pix2;
  int wholeobjs;
  g_obj far *ptr1, far *ptr2;
  g_obj begmask, endmask, mask;
  register unsigned y;
  register g_obj far *p;
  register g_obj tmp;

  if (y2 < y1) swap(y1, y2);
  if (x2 < x1) swap(x1, x2);

  goffs(x1, y1, &offs1, &pix1);
  goffs(x2, y1, &offs2, &pix2);
  wholeobjs = offs2 - offs1 - 1;
  ptr1 = g_drawbuf + offs1;
  ptr2 = g_drawbuf + offs2;

  trimcolor(c);
  begmask = g_allmask >> (g_pixbyte - 1 - pix1)*g_bitpix;
  endmask = g_allmask << pix2*g_bitpix;

  /* set up EGA registers for write */

  outp(ega_gr_addr, ega_gr_sr);		/* set/reset register           */
  outp(ega_gr_data, c);
  outp(ega_gr_addr, ega_gr_sren);	/* set/reset enable register    */
  outp(ega_gr_data, g_colormask);
  outp(ega_gr_addr, ega_gr_mode);	/* mode register        	*/
  outp(ega_gr_data, 0);			/* write mode 0			*/
  outp(ega_gr_addr, ega_gr_mask);	/* select bit mask register	*/

  /* do the write */

  if (wholeobjs < 0) {			/* region is less than 8 pels wide */
    p = ptr1;
    mask = begmask & endmask;
    outp(ega_gr_data, mask);		/* set bitmask for writes	*/
    for (y=y1; y<=y2; y++) {
      tmp = *p;				/* read byte into latches	*/
      *p = 0;				/* then write there to set the	*/
					/* bits				*/
      bumpy(p, 0);
    }
  }
  else {
    p = ptr1;				/* do left edge 		*/
    outp(ega_gr_data, begmask);
    for (y=y1; y<=y2; y++) {
      tmp = *p;
      *p = 0;
      bumpy(p, 0);
    }

    p = ptr2;				/* do right egde		*/
    outp(ega_gr_data, endmask);
    for (y=y1; y<=y2; y++) {
      tmp = *p;
      *p = 0;
      bumpy(p, 0);
    }

    p = ptr1+1;				/* now fill it in		*/
    outp(ega_gr_data, g_allmask);
    for (y=y1; y<=y2; y++) {
      g_fmemset(p, g_allmask, wholeobjs); /* can write it with anything here */
      bumpy(p, 0);
    }
  }

  /* reset the EGA to something nice */

  outp(ega_gr_data, g_allmask);		/* reset bit mask		*/
  outp(ega_gr_addr, ega_gr_sren);	/* disable set/reset mode	*/
  outp(ega_gr_data, 0);
}
#ifdef __TURBOC__
# pragma warn .aus /* TC */
# pragma warn .rch
#endif

/* fill the entire buffer with a color fast */

void EGA_clearall(c)
unsigned c;
{
  /* set up EGA registers for write */

  outp(ega_gr_addr, ega_gr_sr);		/* set/reset register           */
  outp(ega_gr_data, c);
  outp(ega_gr_addr, ega_gr_sren);	/* set/reset enable register    */
  outp(ega_gr_data, g_colormask);
  outp(ega_gr_addr, ega_gr_mode);	/* mode register        	*/
  outp(ega_gr_data, 0);			/* write mode 0			*/

  g_fmemset(g_drawbuf, g_allmask, g_bufsiz);

  outp(ega_gr_addr, ega_gr_sren);	/* disable set/reset mode	*/
  outp(ega_gr_data, 0);
}

/* make the drawing buffer visible by switching pages */

void EGA_show()
{
  union REGS inregs, outregs;

  if (g_bufflg) {
    g_curpage = 1-g_curpage;
    inregs.h.ah = ega_setpage;
    inregs.h.al = g_curpage;
    int86(int_video, &inregs, &outregs);

    g_drawbuf = g_physbuf;		/* swap around buffer pointers */
    g_physbuf = g_virtbuf;
    g_virtbuf = g_drawbuf;    
  }
}

/* set the color pallette */

void EGA_setpal(p, v)
unsigned p, v;
{
  union REGS inregs, outregs;

  inregs.h.ah = ega_setpal;
  inregs.h.al = 0;
  inregs.h.bl = p;
  inregs.h.bh = v;
  int86(int_video, &inregs, &outregs);
}

/* set the background color - just use setpal() */

void EGA_setback(c)
unsigned c;
{
  EGA_setpal(0, c);
}

/* turn on graphics mode. mode has no meaning */

#ifdef __TURBOC__
# pragma warn -par /* TC */
#endif
void EGA_gopen(mode)
unsigned mode;
{
  union REGS inregs, outregs;

  if (g_display == EN) {		/* Enhanced color display	*/
    inregs.h.ah = ega_setmode;
    inregs.h.al = mde_640X350c;
    int86(int_video, &inregs, &outregs);
    g_page1addr = g_en_pg1;
    g_page2addr = g_en_pg2;
    g_bufsiz = g_en_bufsiz;
    g_colormask = g_en_colormask;
    g_xsize = g_en_xsize;
    g_ysize = g_en_ysize;
    g_xchsize = g_en_xchsize;
    g_ychsize = g_en_ychsize;
    g_aspect = g_en_aspect;
  }
  else if (g_display == CD) {		/* Ordinary color display	*/
    inregs.h.ah = ega_setmode;
    inregs.h.al = mde_640X200c;
    int86(int_video, &inregs, &outregs);
    g_page1addr = g_cd_pg1;
    g_page2addr = g_cd_pg2;
    g_bufsiz = g_cd_bufsiz;
    g_colormask = g_cd_colormask;
    g_xsize = g_cd_xsize;
    g_ysize = g_cd_ysize;
    g_xchsize = g_cd_xchsize;
    g_ychsize = g_cd_ychsize;
    g_aspect = g_cd_aspect;
  }
  else if (g_display == MO) {			/* Monochrome display	*/
    inregs.h.ah = ega_setmode;			/* THIS HAS NOT BEEN TESTED */
    inregs.h.al = mde_640X350m;
    int86(int_video, &inregs, &outregs);
    g_page1addr = g_mo_pg1;
    g_page2addr = g_mo_pg2;
    g_bufsiz = g_mo_bufsiz;
    g_colormask = g_mo_colormask;
    g_xsize = g_mo_xsize;
    g_ysize = g_mo_ysize;
    g_xchsize = g_mo_xchsize;
    g_ychsize = g_mo_ychsize;
    g_aspect = g_mo_aspect;
  }

  g_physbuf = g_page1addr;
  g_virtbuf = g_page2addr;
  g_colormax = g_colormask;
  g_pages = 2;
  g_curpage = 0;
}
#ifdef __TURBOC__
# pragma warn .par /* TC */
#endif

/* turn off graphics mode */

void EGA_gclose()
{
  union REGS inregs, outregs;

  inregs.h.ah = ega_setmode;
  inregs.h.al = mde_80co;
  int86(int_video, &inregs, &outregs);
}

/* setup for point plotting */

void EGA_point_set(c)
unsigned c;
{
  trimcolor(c);
  outp(ega_gr_addr, ega_gr_sr);		/* set/reset register           */
  outp(ega_gr_data, c);
  outp(ega_gr_addr, ega_gr_sren);	/* set/reset enable register    */
  outp(ega_gr_data, g_colormask);
  outp(ega_gr_addr, ega_gr_mode);	/* mode register        	*/
  outp(ega_gr_data, 0);			/* write mode 0			*/
  outp(ega_gr_addr, ega_gr_rot);
  outp(ega_gr_data, g_xor ? ega_gr_x_xor : 0);	/* set xor mode		*/
  outp(ega_gr_addr, ega_gr_mask);	/* set graphics addr to map reg */
}

/* reset ega afterwards */

void EGA_point_res()
{
  outp(ega_gr_data, g_allmask);		/* to map register		*/
  outp(ega_gr_addr, ega_gr_rot);	/* reset ega */
  outp(ega_gr_data, 0);
  outp(ega_gr_addr, ega_gr_sren);
  outp(ega_gr_data, 0);
}

/* plot a point */


/* This fine piece of code has now been supplanted by a weenie hunk
   of assembly.....  */
/* Well, in this case it really wasn't quite so fine but still...   */
/*
void EGA_point(x1,y1,c)
unsigned x1,y1,c;
{
  long p;
  unsigned pixoff, offs;
  g_obj far *ptr;
  g_obj mask;
  register g_obj tmp;

  /* icky, icky, icky! *

  EGA_point_set(c); 
 
  goffs(x1, y1, &offs, &pixoff);
  ptr = g_drawbuf + offs;
  mask = 1 << pixoff*g_bitpix;
  plot(ptr, mask, tmp);			/* plot pt. *

  EGA_point_res();
}
*/
/* draw a line... */

#ifdef __TURBOC__
# pragma warn -aus /* TC */
#endif
void EGA_line(x1,y1,x2,y2,c)
unsigned x1,y1,x2,y2,c;
{
  unsigned pixoff, offs;
  g_obj far *ptr;
  int delx,dely;
  int xyswap=0;
  int ydir=0;
  int i,ydelx;
  g_obj mask;
  register g_obj tmp;

  EGA_point_set(c);
 
  if (x1 > x2) { 		/* sort into left-right order */
    register int tmp;
    tmp=x1; x1=x2; x2=tmp;
    tmp=y1; y1=y2; y2=tmp;
  }
  goffs(x1, y1, &offs, &pixoff);
  ptr = g_drawbuf+offs;
  mask = 1 << pixoff*g_bitpix;
  plot(ptr, mask, tmp);		/* plot pt. */
  if (x1==x2 && y1==y2) {	/* handle 1 pt. correctly */
    EGA_point_res();
    return;
  }
  delx=x2-x1;
  dely=y2-y1;
  if (dely < 0)	{		/* handle lines from up to down */
    ydir=1;
    dely=-dely;
  }
  if (abs(dely) > delx) {	/* handle slopes > 1 */
    register int tmp;
    tmp=x1;   x1=y1;     y1=tmp;
    tmp=x2;   x2=y2;     y2=tmp;
    tmp=delx; delx=dely; dely=tmp;
    xyswap=1;
  }
  ydelx=0;
  for (i=1; i<=delx; i++) {
    if ((ydelx+=dely) >= delx) {
      bumpx(ptr, mask);		/* bump both x & y */
      bumpy(ptr, ydir);
      ydelx-=delx;
    }
    else
      if (xyswap)		/* bump x only */
        bumpy(ptr, ydir)
      else
        bumpx(ptr, mask);
    plot(ptr, mask, tmp);	/* plot point, go around again */
  }
  EGA_point_res();
}
#ifdef __TURBOC__
# pragma warn .aus /* TC */
#endif

/* since we're always writing to an EGA buffer, we can use the BIOS
   routine! */

void EGA_writech(row, col, ch, c, page)
unsigned row, col, c;
char ch;
int page;
{
  union REGS inregs, outregs;

  inregs.h.ah = ega_setcur;
  inregs.h.dh = row;
  inregs.h.dl = col;
  inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
  int86(int_video, &inregs, &outregs);

  inregs.h.ah = ega_writech;
  inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
  inregs.x.cx = 1;
  inregs.h.al = ch;
  inregs.h.bl = c /*| (g_xor ? 0x80 : 0)*/;
  int86(int_video, &inregs, &outregs);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -