Category : C Source Code
Archive   : C-GRAF.ZIP
Filename : GRAF.C

 
Output of file : GRAF.C contained in archive : C-GRAF.ZIP
/*
* grafix --- graf.c
*
* graphics interface
*
* Written 4/87 by Scott Snyder ([email protected] or @citromeo.bitnet)
*
* 5/29/87 sss - fixed bug in box() and allow for different memory models
*
*/

#include "macros.h"
#include "graf.h"
#include "grafsys.h"
#include

#define int_video 0x10
#define video_point 0x0c
#define ega_altsel 0x12
#define egaalt_info 0x10

/* utility macros */

#define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
#define inrange(a, x, b) ((a)<=(x) && (x)<=(b))
#define clipto(x, lo, hi) { \
if (x < lo) \
x = lo; \
else if (x > hi) \
x = hi; \
}

/*****************************************************************************
* variable definitions *
*****************************************************************************/

unsigned NEAR g_card; /* graphics card we're using */
unsigned NEAR g_display; /* type of display we're using */

g_obj far * NEAR g_drawbuf; /* graphics drawing buffer */
g_obj far * NEAR g_physbuf; /* physical screen address */
g_obj far * NEAR g_virtbuf; /* virtual buffer address */
unsigned NEAR g_colormax; /* maximum color value */
unsigned NEAR g_xsize, NEAR g_ysize; /* physical size of screen */
unsigned NEAR g_xchsize, NEAR g_ychsize; /* size of screen in characters */
unsigned NEAR g_xor; /* xor mode flag */
unsigned NEAR g_bufflg; /* buffered mode flag */
unsigned NEAR g_pages; /* number of pagse available */
unsigned NEAR g_curpage; /* page currently visible */

int NEAR g_xcliplo, NEAR g_xcliphi; /* clipping boundaries */
int NEAR g_ycliplo, NEAR g_ycliphi;

float NEAR g_aspect; /* aspect ratio */

/*****************************************************************************
* interfaces to graphics drivers *
*****************************************************************************/

/************************* calls for internal use only ***********************/

STATIC void nocl_regfill(x1, y1, x2, y2, c)
unsigned x1, y1, x2, y2, c;
{
switch(g_card) {
case (CGA): CGA_regfill(x1, y1, x2, y2, c); break;
case (EGA): EGA_regfill(x1, y1, x2, y2, c); break;
}
}

STATIC void nocl_point(x, y, c)
unsigned x, y, c;
{
switch(g_card) {
case (CGA): CGA_point(x, y, c); break;
case (EGA): EGA_point(x, y, c); break;
}
}

STATIC void nocl_line(x1, y1, x2, y2, c)
unsigned x1, y1, x2, y2, c;
{
switch(g_card) {
case (CGA): CGA_line(x1, y1, x2, y2, c); break;
case (EGA): EGA_line(x1, y1, x2, y2, c); break;
}
}

STATIC void write_pix(x1, y1, x2, y2, c)
int x1, y1, x2, y2;
unsigned c;
{
switch(g_card) {
case (CGA): CGA_write_pix(x1, y1, x2, y2, c); break;
case (EGA): EGA_write_pix(x1, y1, x2, y2, c); break;
}
}

/* set up for plotting mucho points */

STATIC void point_set(c)
unsigned c;
{
switch(g_card) {
case (CGA): CGA_point_set(c); break;
case (EGA): EGA_point_set(c); break;
}
}

STATIC void point_res()
{
switch(g_card) {
case (CGA): CGA_point_res(); break;
case (EGA): EGA_point_res(); break;
}
}

/******************** calls safe for anyone to use **************************/

void g_clearall(c)
unsigned c;
{
switch(g_card) {
case (CGA): CGA_clearall(c); break;
case (EGA): EGA_clearall(c); break;
}
}

void g_show()
{
switch(g_card) {
case (CGA): CGA_show(); break;
case (EGA): EGA_show(); break;
}
}

void g_setback(c)
unsigned c;
{
switch(g_card) {
case (CGA): CGA_setback(c); break;
case (EGA): EGA_setback(c); break;
}
}

void g_setpal(pallette, value)
unsigned pallette, value;
{
switch(g_card) {
case (CGA): CGA_setpal(pallette, value); break;
case (EGA): EGA_setpal(pallette, value); break;
}
}

/* g_open also sets clipping boundaries to the physical screen size */
/* and initializes other things... */

void g_open(mode)
unsigned mode;
{
switch(g_card) {
case (CGA): CGA_gopen(mode); break;
case (EGA): EGA_gopen(mode); break;
}
g_xcliplo = 0;
g_ycliplo = 0;
g_xcliphi = g_xsize-1;
g_ycliphi = g_ysize-1;

g_xor = g_bufflg = 0;

/* set g_drawbuf to something appropriately */

g_setbuf(g_bufflg);
}

void g_close()
{
switch(g_card) {
case (CGA): CGA_gclose(); break;
case (EGA): EGA_gclose(); break;
}
}

void g_writech(row, col, ch, c, page)
unsigned row, col, c;
char ch;
int page;
{
switch(g_card) {
case (CGA): CGA_writech(row, col, ch, c, page); break;
case (EGA): EGA_writech(row, col, ch, c, page); break;
}
}

/***************************************************************************
* graphics drawing and control routines *
***************************************************************************/

/* fill a region with the specified color */

void g_regfill(x1, y1, x2, y2, c)
int x1, y1, x2, y2;
unsigned c;
{
if (x1 > x2)
swap(x1, x2);
if (y1 > y2)
swap(y1, y2);

if (x1 < g_xcliplo)
x1 = g_xcliplo;
else if (x1 > g_xcliphi)
return;

if (x2 < g_xcliplo)
return;
else if (x2 > g_xcliphi)
x2 = g_xcliphi;

if (y1 < g_ycliplo)
y1 = g_ycliplo;
else if (y1 > g_ycliphi)
return;

if (y2 < g_ycliplo)
return;
else if (y2 > g_ycliphi)
y2 = g_ycliphi;

nocl_regfill(x1, y1, x2, y2, c);
}

/* plot a point */

void g_point(x, y, c)
int x, y;
unsigned c;
{
if (inrange(g_xcliplo, x, g_xcliphi) &&
inrange(g_ycliplo, y, g_ycliphi))
nocl_point(x, y, c);
}

/* routine to clip one endpoint of a line */

STATIC int clipln(x1,y1,xc,yc,x2,y2)
int x1,y1,x2,y2,*xc,*yc;
{
int delx,dely,xx,yy;

if (x1 >= g_xcliplo && x1 <= g_xcliphi &&
y1 >= g_ycliplo && y1 <= g_ycliphi) {
*xc=x1; *yc=y1;
return(1);
}
dely=y2-y1;
delx=x2-x1;
if (y1 > g_ycliphi || y1 < g_ycliplo) {
if (dely == 0)
return(0);
if (y1 > g_ycliphi) {
if (dely > 0 || y2 > g_ycliphi) return (0);
yy=g_ycliphi;
}
else {
if (dely < 0 || y2 < g_ycliplo) return(0);
yy=g_ycliplo;
}
xx=(float)(yy-y1)*delx/dely+x1;
if (xx >= g_xcliplo && xx <= g_xcliphi) {
*xc=xx; *yc=yy;
return(1);
}
}
if (x1 > g_xcliphi || x1 < g_xcliplo) {
if (delx == 0)
return(0);
if (x1 > g_xcliphi) {
if (delx > 0 || x2 > g_xcliphi) return(0);
xx=g_xcliphi;
}
else {
if (delx < 0 || x2 < g_xcliplo) return(0);
xx=g_xcliplo;
}
yy=(float)(xx-x1)*dely/delx+y1;
if (yy >= g_ycliplo && yy <= g_ycliphi) {
*xc=xx; *yc=yy;
return(1);
}
}
return(0);
}

/* draw a clipped line */

void g_line(x1,y1,x2,y2,c)
int x1,y1,x2,y2;
unsigned c;
{
if (clipln(x1,y1,&x1,&y1,x2,y2) &&
clipln(x2,y2,&x2,&y2,x1,y1)) {
nocl_line(x1,y1,x2,y2,c);
}
}

/* draw an ellipse with aspect aspect and half-major axis length r_sum_m */
/* from a routine by Tim Hogan in Dr. Dobb's Journal May '85 p. 40 */

void g_ellipse(x, y, r_sub_m, aspect, c)
int x,y,r_sub_m;
unsigned c;
float aspect;
{
long alpha, beta, two_alpha, four_alpha, two_beta, four_beta, d;
int row, col, two_x, two_y, rel_x, rel_y;
double square_aspect;

if (aspect < 0.004) aspect = 0.004;

square_aspect = aspect*aspect;

if (aspect < 1.0) {
alpha = (long)r_sub_m * (long)r_sub_m;
beta = alpha * square_aspect;
row = y + r_sub_m*aspect;
}
else {
beta = (long)r_sub_m * (long)r_sub_m;
alpha = beta / square_aspect;
row = y + r_sub_m;
}

if (alpha == 0L) alpha = 1L;
if (beta == 0L) beta = 1L;

col = x;
two_x = x<<1;
two_y = y<<1;
rel_y = row-y;
two_alpha = alpha<<1;
four_alpha = alpha<<2;
two_beta = beta<<1;
four_beta = beta<<2;

d = two_alpha*((long)(rel_y-1)*rel_y) + alpha + two_beta*(1-alpha);

point_set(c); /* set up for point plotting */

while (alpha*(rel_y = row-y) > beta*(rel_x = col-x)) {
write_pix(col, row, two_x-col, two_y-row, c);
if (d>=0) {
d += four_alpha*(1-rel_y);
row--;
}
d += two_beta*(3+(rel_x<<1));
col++;
}

d = two_beta * ((long)rel_x * (rel_x+1)) + two_alpha*((long)rel_y*(rel_y-2)+1) +
beta*(1-two_alpha);

while ((rel_y = row-y) + 1) {
write_pix(col, row, two_x-col, two_y-row, c);
if (d<=0) {
d += four_beta*(1+col-x);
col++;
}
d += two_alpha*(3-(rel_y<<1));
row--;
}
point_res(); /* reset the graphics device */
}

/* draw a circle */

void g_circle(x, y, r, c)
int x, y, r;
unsigned c;
{
g_ellipse(x, y, r, g_aspect, c);
}

/* draw a box */

void g_box(x1, y1, x2, y2, c)
int x1, y1, x2, y2;
unsigned c;
{
g_line(x1, y1, x2, y1, c);
g_line(x2, y1, x2, y2, c);
g_line(x2, y2, x1, y2, c);
g_line(x1, y2, x1, y1, c);
}

/* set xor mode */

void g_setxor(flag)
unsigned flag;
{
g_xor = flag;
}

/* set clipping boundaries */

void g_setclip(x1, y1, x2, y2)
int x1, y1, x2, y2;
{
if (x1 > x2)
swap(x1, x2);
if (y1 > y2)
swap(y1, y2);

clipto(x1, 0, g_xsize-1);
clipto(x2, 0, g_xsize-1);
clipto(y1, 0, g_ysize-1);
clipto(y2, 0, g_ysize-1);

g_xcliplo = x1;
g_xcliphi = x2;
g_ycliplo = y1;
g_ycliphi = y2;
}

/* clear screen within clipping boundaries */

void g_clear(c)
unsigned c;
{
nocl_regfill(g_xcliplo, g_ycliplo, g_xcliphi, g_ycliphi, c);
}

/* set buffered mode flag and initialize drawbuf appropriately */

void g_setbuf(flag)
unsigned flag;
{
g_bufflg = flag;
if (flag)
g_drawbuf = g_virtbuf;
else
g_drawbuf = g_physbuf;
}

/* initialize graphics system */

void g_init(card, display)
unsigned card;
unsigned display; /* ignored if card = 0 */
{
unsigned swt;
union REGS inregs, outregs;

/* try to get EGA information. if we have enough memory for 2 hi-res
pages, then say we have an EGA. if not, or if the card does not
respond, assume we have a CGA. if argument is nonzero however, force
result to that.
*/

if (card == 0) {
inregs.h.ah = ega_altsel;
inregs.h.bl = egaalt_info;
int86(int_video, &inregs, &outregs);
if (outregs.h.bl != 3) { /* not valid | mem. < 256k */
g_card = CGA;
g_display = CD;
}
else {
g_card = EGA;

/* now look at the adapter switch settings (in cl) and try to figure
out what sort of display is attached */

swt = outregs.h.cl & 0x0e;
swt = (swt >= 6 ? swt-6 : swt);
if (swt == 4)
g_display = MO;
else if (swt == 2)
g_display = EN;
else if (swt == 0)
g_display = CD;
else
g_display = CD;
}
}
else {
g_card = card;
g_display = display;
}

g_xor = 0;
g_bufflg = 0;
g_xcliplo = g_xcliplo = g_ycliphi = g_ycliplo = 0;
}

/* write a string tty style with color c at row, col */

void g_writestr(row, col, s, c, page)
unsigned row, col;
unsigned c;
char *s;
int page;
{
while (*s) {
if (col >= g_xchsize) { /* do wrapping */
col = 0;
row++;
}
if (row >= g_ychsize) /* abort if we run out of screen */
return;
if (*s == '\012') /* newline */
col = g_xchsize; /* force a wrap next time around */
else if (*s == '\015') /* ignore any carriage returns (for compat) */
;
else {
g_writech (row, col, *s, c, page);
col++;
}
s++;
}
}

/* get information about physical graphics device */

void g_info(p)
struct g_info *p;
{
p->card = g_card;
p->display = g_display;
p->xsize = g_xsize;
p->ysize = g_ysize;
p->colormax = g_colormax;
p->pages = g_pages;
p->curpage = g_curpage;
p->xchsize = g_xchsize;
p->ychsize = g_ychsize;
}


  3 Responses to “Category : C Source Code
Archive   : C-GRAF.ZIP
Filename : GRAF.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/