home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MS DOS Archives 1
/
MS-DOS_Archives_Volume_One_Walnut_Creek.iso
/
msdos
/
graphics
/
grafxlib.arc
/
CGAGRAF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1987-08-31
|
9KB
|
405 lines
/*
* grafix --- cgagraf.c
*
* CGA graphics driver
*
* Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
*
*/
#include <dos.h>
#include "macros.h"
#include "grafsys.h"
/* parameters that don't depend on graphics mode */
#define int_cga 16
#define cga_setmode 0
#define cga_setpal 11
#define mde_80bw 2
#define mde_80co 3
#define mde_320 4
#define mde_640 6
#define cid_back 0
#define cid_pal 1
#define g_linsiz 80
#define g_oddoff 0x2000
#define g_allmask 0xff
#define g_bufsiz 0x4000
#define g_screenaddr (g_obj far *)0xb8000000
#define g_charbase (g_obj far *)0xf000fa6e
/* parameters that DO depend on graphics mode */
unsigned g_mode;
/* these must be near so the .asm routines can get to them */
unsigned NEAR g_pixbyte;
unsigned NEAR g_bitpix;
g_obj NEAR g_colormask;
g_obj NEAR g_hicolormask;
g_obj NEAR g_cmask_tbl[8];
/* utility macros */
#define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
#define trimcolor(c) c &= g_colormask
#define get_cmask(c) g_cmask_tbl[c&g_colormask]
/* plot a point */
#define plot(ptr, mask, cmask) \
*ptr = g_xor ? ( *ptr ^ (cmask & mask)) \
: ((*ptr & ~mask) | (cmask & mask))
/* move one to right */
#define bumpx(ptr,mask) \
if ((mask >>= g_bitpix) == 0) { \
mask = g_hicolormask; \
ptr++; \
}
/* move one line */
#define bumpy(ptr,ydir) \
if (ptr >= (g_obj far *)(g_drawbuf+g_oddoff)) { \
ptr-=g_oddoff; \
if (!ydir) \
ptr+=g_linsiz; \
} \
else { \
ptr+=g_oddoff; \
if (ydir) \
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;
{
int y0;
y0 = y/2;
*offs = y0 * g_linsiz + x/g_pixbyte + ((y0*2 != y) ? g_oddoff : 0);
*pix = g_pixbyte - 1 - x%g_pixbyte;
}
/* fill a mask with the given color value */
g_obj make_cmask(c)
unsigned c;
{
int i;
g_obj mask = 0;
trimcolor(c);
for (i=0; i<g_pixbyte; i++)
mask = (mask<<g_bitpix) | c;
return (mask);
}
/****************************************************************************
* externally callable functions *
****************************************************************************/
/* fill a region with the specified color */
#ifdef __TURBOC__
# pragma warn -rch
#endif
void CGA_regfill(x1, y1, x2, y2, c)
unsigned x1, y1, x2, y2, c;
{
unsigned offs1, offs2, pix1, pix2, y;
int wholeobjs;
g_obj far *ptr1, far *ptr2;
g_obj cmask, begmask, endmask, mask;
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;
cmask = get_cmask(c);
begmask = g_allmask >> (g_pixbyte - 1 - pix1)*g_bitpix;
endmask = g_allmask << pix2*g_bitpix;
if (wholeobjs < 0) {
mask = begmask & endmask;
cmask &= mask;
for (y=y1; y<=y2; y++) {
*ptr1 = (*ptr1 & ~mask) | cmask;
bumpy(ptr1, 0);
}
}
else {
for (y=y1; y<=y2; y++) {
*ptr1 = (*ptr1 & ~begmask) | (cmask & begmask);
g_fmemset(ptr1+1, cmask, wholeobjs);
*ptr2 = (*ptr2 & ~endmask) | (cmask & endmask);
bumpy(ptr1, 0);
ptr2 = ptr1 + wholeobjs + 1;
}
}
}
#ifdef __TURBOC__
# pragma warn .rch
#endif
/* fill the entire buffer with a color fast */
void CGA_clearall(c)
unsigned c;
{
g_fmemset(g_drawbuf, get_cmask(c), g_bufsiz);
}
/* make the drawing buffer visible */
void CGA_show()
{
g_fmemcpy(g_physbuf, g_drawbuf, g_bufsiz);
}
/* set the background color */
void CGA_setback(c)
unsigned c;
{
union REGS inregs, outregs;
if (g_mode == CGA_320) {
inregs.h.ah = cga_setpal;
inregs.h.bh = cid_back;
inregs.h.bl = c;
int86(int_cga, &inregs, &outregs);
}
}
/* set the color pallette */
void CGA_setpal(p, v) /* pallette register number is ignored here */
unsigned p, v;
{
union REGS inregs, outregs;
inregs.h.ah = cga_setpal;
if (g_mode == 2) {
inregs.h.bh = cid_pal;
inregs.h.bl = p;
}
else {
inregs.h.bh = cid_back;
inregs.h.bl = v;
}
int86(int_cga, &inregs, &outregs);
}
/* turn on graphics mode. mode=1 is 640, mode=2 is 320 */
void CGA_gopen(mode)
unsigned mode;
{
union REGS inregs, outregs;
unsigned i;
g_mode = mode;
inregs.h.ah = cga_setmode;
inregs.h.al = (mode == CGA_640) ? mde_640 : mde_320;
int86(int_cga, &inregs, &outregs);
g_physbuf = g_screenaddr;
#if defined(__TURBOC__)
g_virtbuf = (g_obj far *)MK_FP(g_bufseg(), 0);
#else
FP_SEG(g_virtbuf) = g_bufseg();
FP_OFF(g_virtbuf) = 0;
#endif
/* set up mode-dependent parameters */
if (mode == 1) {
g_xsize = 640;
g_ysize = 200;
g_bitpix = 1;
g_aspect = 0.42;
}
else {
g_xsize = 320;
g_ysize = 200;
g_bitpix = 2;
g_aspect = 0.85;
}
g_pixbyte = 8/g_bitpix;
g_xchsize = g_xsize/8;
g_ychsize = g_ysize/8;
g_colormask = (1<<g_bitpix) - 1;
g_hicolormask = g_colormask << (g_pixbyte-1)*g_bitpix;
g_colormax = g_colormask;
g_pages = 1;
g_curpage = 0;
for (i=0; i<=g_colormask; i++)
g_cmask_tbl[i] = make_cmask(i);
}
/* turn off graphics mode */
void CGA_gclose()
{
union REGS inregs, outregs;
inregs.h.ah = cga_setmode;
inregs.h.al = mde_80co;
int86(int_cga, &inregs, &outregs);
}
/* plot a point */
/* This fine piece of code has now been supplanted by a weenie hunk
of assembly.....
void CGA_point(x1,y1,c)
unsigned x1,y1,c;
{
long p;
unsigned pixoff, offs;
g_obj far *ptr;
g_obj mask, cmask;
goffs(x1, y1, &offs, &pixoff);
ptr = g_drawbuf + offs;
cmask = get_cmask(c);
mask = g_colormask << pixoff*g_bitpix;
plot(ptr, mask, cmask); /* plot pt. *
}
*/
/* draw a line... */
void CGA_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, cmask;
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;
cmask = get_cmask(c);
mask = g_colormask << pixoff*g_bitpix;
plot(ptr, mask, cmask); /* plot pt. */
if (x1==x2 && y1==y2) /* handle 1 pt. correctly */
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, cmask); /* plot point, go around again */
}
}
/* print a character. this is really kind of cheap, and can/should
be expanded later... */
#ifdef __TURBOC__
# pragma warn -par /* TC */
# pragma warn -rch
#endif
void CGA_writech(row, col, ch, c, page)
unsigned row, col, c;
char ch;
int page;
{
unsigned x, y, pixoff, offs;
g_obj cmask, chdat, gdat;
g_obj far *ptr, far *pptr, far *chpt;
int i, j, k;
x = col*8; /* character is 8 X 8 */
y = row*8;
if (x >= g_xsize || y >= g_ysize)
return;
trimcolor(c);
cmask = get_cmask(c);
goffs(x, y, &offs, &pixoff); /* pixoff should be 0 */
ptr = g_drawbuf + offs;
chpt = g_charbase + 8*ch; /* pointer to character data */
for (i=0; i<8; i++) { /* loop for each line */
chdat = *chpt++; /* get character data */
if (g_bitpix == 1)
*ptr = chdat & cmask;
else {
pptr = ptr;
for (j=0; j<g_bitpix; j++) { /* g_bitpix is the # of bytes per ch */
gdat = 0;
for (k=0; k<g_pixbyte; k++) {
gdat = (gdat << g_bitpix) + (chdat&0x80 ? c : 0);
chdat <<= 1;
}
*pptr++ = gdat;
}
}
bumpy(ptr, 0);
}
}
#ifdef __TURBOC__
# pragma warn .par /* TC */
# pragma warn .rch
#endif
/* these two thingamabobs don't do anything */
#ifdef __TURBOC__
# pragma warn -par /* TC */
#endif
void CGA_point_set(c)
unsigned c;
{
}
#ifdef __TURBOC__
# pragma warn .par /* TC */
#endif
void CGA_point_res()
{
}