[comp.sys.ibm.pc] Graphics driver

lesmem@cs.vu.nl (Marco Lesmeister) (08/25/87)

Could anyone tell me what the fastest way is to control the screen in, for
instance games and simulators? I want to move a C64-sprite like figure
as fast as possible across the screen in CGA-mode.
I think I need a device driver for this, but maybe there is another fast
way to control the screen in C, since that is the language in which I'm
writing this program.
If someone knows the answer to this question, please write it to the net
because I guess there are other people as well, who would like to know
how to control the graphics screen as fast as possible.

P.S. A fast line-drawing routine is welcome also.

Thanks in advance
			Marco Lesmeister,
			VU (Free University),
			Holland.


--------------------------------------------------------------------------

perkins@bnrmtv.UUCP (Henry Perkins) (08/26/87)

In article <1096@ark.cs.vu.nl>, lesmem@cs.vu.nl (Marco Lesmeister) writes:
> Could anyone tell me what the fastest way is to control the screen in, for
> instance games and simulators? I want to move a C64-sprite like figure
> as fast as possible across the screen in CGA-mode.

If you want to modify a CGA screen, the fastest way to do it
is with direct writes to CGA memory, located in B800:0000 to
B800:1F40 (even scan lines) and B800:2000 to B800:2F40 (odd
scan lines).  A device driver would be s l o w .

You're trying to do something that IBM really didn't provide
for.  There is no hardware support for sprites or anything
resembling them; you'll have to save the original screen
contents so you can restore things when the "sprite" moves,
and you'll need to do your own collision calculations.  You
can't even do color table animation, because the color
palettes are fixed with two non-intersecting sets of 3 colors
each.  Since each byte of memory represents 4 pixels, you'll
need to OR and AND with pixel masks for horizontal movement.
Vertical movement is harder, because you need to add or
subtract your screen memory offset depending on whether you're
in an even or odd row.

Good luck; you'll need it, plus lots of patience.

(I did the animation for Championship Golf, published by
Activision's GameStar division.)
-- 
{hplabs,amdahl,ames}!bnrmtv!perkins         --Henry Perkins

It is better never to have been born.  But who among us has such luck?
One in a million, perhaps.

lesmem@ark.UUCP (08/27/87)

In article 5194 Henry Perkins writes :

  Direct writes to CGA memory are fastest.

I tried to figure this out, but couldn't succeed. My
question is this :

  Can somebody post a fast line drawing algorithm that
uses direct memory writes to CGA memory.

		Thanks in advance,  Marco Lesmeister.

ssnyder@tybalt.caltech.edu (Scott S. Snyder) (08/27/87)

In article <1099@ark.cs.vu.nl> lesmem@cs.vu.nl (Marco Lesmeister) writes:
>  Can somebody post a fast line drawing algorithm that
>uses direct memory writes to CGA memory.

  I have just sent a simple PC graphics library to comp.sources.misc.
I hope that it will answer your question.

psfales@ihlpe.ATT.COM (Pete Fales) (08/28/87)

In article <1099@ark.cs.vu.nl>, lesmem@cs.vu.nl (Marco Lesmeister) writes:
> 
>   Can somebody post a fast line drawing algorithm that
> uses direct memory writes to CGA memory.
> 
> 		Thanks in advance,  Marco Lesmeister.

I won't make any claims about how fast this algorithm is relative to 
other potential candidates, but it is pretty good.  I didn't write it
(it was published in the IBM Journal of Research and Development), but
I have had several occasions to use it over the years, including some
assembly language implementations.  It uses only integer arithmetic
and multiplications only by powers of 2.

---------------------------- cut here ------------------------------

int xm1[] = { 1, 0, 1, 0,-1, 0,-1, 0 };
int ym1[] = { 0, 1, 0,-1, 0, 1, 0,-1 };
int xm2[] = { 1, 1, 1, 1,-1,-1,-1,-1 };
int ym2[] = { 1, 1,-1,-1, 1, 1,-1,-1 };

/* Bresenham (spelling?) algorithm to draw a line from (x1,y1) to (x2,y2) */

void 
absline(x1,y1,x2,y2,col)
{
	int m,deltax,deltay,e,cx,savedx,t;

	m=0;
	deltax=x2-x1;
	if ( deltax<0 ) {
		m=4;
		deltax = -deltax;
	}
	deltay=y2-y1;
	if (deltay<0 ) {
		m += 2;
		deltay = -deltay;
	}
	if ( deltax - deltay < 0 ) {
		m++;
		t=deltax;
		deltax=deltay;
		deltay=t;
	}

	deltay *= 2; /* OK, use a shift if you really want speed */
	e = deltay-deltax;
	savedx = deltax;
	deltax *= 2;

	for ( cx=savedx+1 ; cx >= 1 ; cx-- ) {
		scr_wdot(x1,y1,col);
		if ( e > 0 ) {
			x1 += xm2[m];
			y1 += ym2[m];
			e += deltay-deltax;
		}
		else {
			x1 += xm1[m];
			y1 += ym1[m];
			e += deltay;
		}
	}
}

-- 
Peter Fales		UUCP:	...ihnp4!ihlpe!psfales
			work:	(312) 979-7784
				AT&T Information Systems, IW 1Z-243
				1100 E. Warrenville Rd., IL 60566

jru@etn-rad.UUCP (John Unekis) (08/29/87)

In article <1099@ark.cs.vu.nl> lesmem@cs.vu.nl (Marco Lesmeister) writes:
>...
>  Can somebody post a fast line drawing algorithm that
>uses direct memory writes to CGA memory.

I am posting some source code here which I yanked out of my blastcga game.
Since no one wanted to buy the source, I figured I would just post it for
free. This is not the complete game(sorry , I wrote the game stream-of-
consciousness style, and there are no comments in the code, as soon as
I find time to put some in I'll post it). Included here are the graphics 
routines for CGA/EGA boards in mono mode.


Some notes:
)you MUST compile with the large model (msc /AL)
)before you call the vector routines you MUST call graphmode or dismode(6) to
put the board into mono graphics mode (only once)
)before you call the vector routines you MUST call setxdotyadd() to init 
the array of screen address offsets (only once)
)before you call the rotate routine you MUST call init_cos() to init the
sin and cosine arrays (only once)
)you should link with a large stack segment (i.e. link /stack:30000 )

This is not a shell archive(sorry , ours is broke) you must pull it 
apart with vi.    Happy hunting.

mail questions to {voder | ihnp4}!wlbr!etn-rad!jru



figures.h
####################### cut here   ###########################

/* This is the include file that drives the blastcga game, it includes
parameters for the number of monsters and such, as well as screen limits
and stuff. It contains structures which allow an object to be stored
either as a series of x,y points or as a series of angle and radius polar
coordinates */


struct object
 {
 int x_vel;
 int y_vel;
 int x_pos;
 int y_pos;
 int num_vertices;
 int x[50];
 int y[50];
 int alive;
 int state;
 int angle;
 };
struct polar_object
 {
 int angle[50];
 int radius[50];
 };

struct object monsters[10];
struct object ship;
struct polar_object polar_ship;
struct polar_object polar_bent;
struct object specials[5];
struct polar_object polar_specials[5];
int monster_moves;
int special_moves;
int num_monsters;
int num_specials;
int num_loops;
int num_ships;
int energy;
int delay;
struct missile
 {
 int x_pos;
 int y_pos;
 int x_vel;
 int y_vel;
 int running;
 int state;
 };
struct missile missiles[20];
int num_missiles;
int next_missile;
int bounce;
int magnet;
int sound;
int max_missile;
int kill_monst;
int kill_special;
int olden;
int gen_monster;
int gen_special;
#define MAX_MISSILE 20
#define MAX_MONSTER 10
#define MAX_SPECIAL 5
#define MAX_SHIPS 3
#define X_LIMIT1 40
#define X_LIMIT2 600
#define Y_LIMIT1 15
#define Y_LIMIT2 185
#define MON_X_COL 13
#define MON_Y_COL 5
#define SPC_X_COL 12
#define SPC_Y_COL 5
#define ALIVE   999
#define NEW     777
#define BENT    555
#define MONSTER_GEN 50
#define SPECIAL_GEN 100



xorobj.c ####################### cut here   ###########################

#include "figures.h"

/* routine to exclusive or the lines of a figure with screen 
   memory John Unekis 1/18/87 */

xorobj(p)
struct object *p;
{
register int i,j,k;
i = (*p).num_vertices - 1;
for(j=0;j<i;j++)
 {                     /* negative x value means "pen up" */
 if ( ((*p).x[j] > 0) && ((*p).x[j+1] > 0))
  shortvec((*p).x[j],(*p).y[j],(*p).x[j+1],(*p).y[j+1]);
 }

}

shortvec.c ####################### cut here   ###########################

int yadd[200];
char xdot[8];
struct scrnmem {
char scrn[16636];
} ;
/* The screen memory when the CGA is in mono mode is organized as 
   one bit per pixel, 80 bytes per line gives 640 pixels per line.
   The scan lines are taken alternately from two banks of 8K memory
   each. One block of 8K for even lines, one for odd lines . The 
   screen memory begins at B800:0000  */
struct scrnmem * scrptr;
/* this routine puts the physical address offset from the beginning
   of screen memory for each screen line (in mono mode CGA) into an
   array indexed by line number. The physical address of a pixel is
   BASE OF SCREEN MEMORY + yadd[line number] + X ADDRESS /8, and the 
   pixel to set within the byte at that address is X ADDRESS mod 8  */

setxdotyadd()
{
int i,j,k;
char a,b,c;
/* start of screen memory */
scrptr = (struct scrnmem *) 0xb8000000;
/* offset to each y-line */
for(i=0;i<200;i++)
 {
 j = i & 1;
 j = j * 0x2000;
 k = i >> 1;
 k = k * 80;
 yadd[i] = j + k;
 }
/* for each bit pixel within a byte, create a byte with just that
    pixel on, to be xor'ed with byte on screen */
for(i=0;i<8;i++)
 {
 xdot[i] = 0x01 << (7 - i);
 }
}

/* Xor the screen memory with a dot at x,y (upper left is 0,0) */
xordot(x,y)
int x,y;
{
int offst;
offst = yadd[y];
offst += x >> 3;
scrptr->scrn[offst] ^= xdot[x & 7];
}

/* This routine will draw a vector up to 128 pixels long from x1,y1
   to x2,y2 on the cga screen in mono mode. It uses a fixed point 
   binary representation for the x and y offsets, where 8 bits is
   whole number and eight bits is fraction. The algorithm assumes that 
   for any given line either dx/dy is fractional, or dy/dx is fractional.
   the routine figures out which is which, then if dy/dx is fractional
   we move x by one each time, and y by dy/dx, otherwise if dx/dy is
   fractional we move y by one each time, and x by dx/dy. The dot on
   the screen is xor'ed at the whole number portion of x,y . */

shortvec(x1,y1,x2,y2)
int x1,y1,x2,y2;
{
int dx,dy,deltx,delty,i,j,k;
/* the line always moves in the positive direction */
if(x1 > x2) 
 dx = x1 - x2;
else
 dx = x2 - x1;
if(y1 > y2)
 dy = y1 - y2;
else
 dy = y2 - y1;
if(dx > dy)
 {
 delty = dy << 8;
 delty = delty / dx;
 if(y2 > y1)
  {
  if(x2 > x1) yfrac(x1,x2,1,y1,delty);
  else yfrac(x1,x2,-1,y1,delty);
  }
 else
  {
  if(x1 > x2) yfrac(x2,x1,1,y2,delty);
  else yfrac(x2,x1,-1,y2,delty);
  }
 }
else
 {
 deltx = dx << 8;
 if(dy > 0)
  deltx = deltx / dy;
 else
  deltx = 0x0100;
 if(x2 > x1)
  {
  if(y2 > y1) xfrac(x1,deltx,y1,y2,1);
  else xfrac(x1,deltx,y1,y2,-1);
  }
 else
  {
  if(y1 > y2) xfrac(x2,deltx,y2,y1,1);
  else xfrac(x2,deltx,y2,y1,-1);
  }
 }
}



xfrac.c ####################### cut here   ###########################

int yadd[200];
char xdot[8];
struct scrnmem {
char scrn[16636];
};
struct scrnmem * scrptr;
/* draw a vector on the cga screen in monochrome mode, assuming that
   y moves by one each time , and x by fractional dx/dy   */
xfrac(xstart,xdelt,ystart,yend,ydelt)
int xstart,xdelt,ystart,yend,ydelt;
{
register int loop,yoff,xrun,xpos;
loop = ystart;
xrun = 0;
while(loop != yend)
  {
  xpos = xstart + (xrun >> 8);
  yoff = yadd[loop];
  yoff += xpos >> 3;
  scrptr->scrn[yoff] ^= xdot[xpos & 7];
  loop += ydelt;
  xrun += xdelt;
  }
}

yfrac.c ####################### cut here   ###########################

int yadd[200];
char xdot[8];
struct scrnmem {
char scrn[16636];
};
struct scrnmem * scrptr;
/* draw a vector in cga mono assuming that x moves by one each time,
   and y moves by fractional dy/dx    */
yfrac(xstart,xend,xdelt,ystart,ydelt)
int xstart,xend,xdelt,ystart,ydelt;
{
register int loop,yoff,yrun;
loop = xstart;
yrun = 0;
while(loop != xend)
  {
  yoff = yadd[ystart+(yrun >> 8)];
  yoff += loop >> 3;
  scrptr->scrn[yoff] ^=  xdot[loop & 7];
  loop += xdelt;
  yrun += ydelt;
  }
}

laser.c ####################### cut here   ###########################

#include "figures.h"

/* Routine to fire ships laser        John Unekis 1/18/87 */
/* this is a long vector drawing routine from the blastcga game, it is 
used to draw the laser beam. If you ignore the code that checks for 
hits on the monsters, it shows how to draw a long fast vector , assuming
that either dx/dy or dy/dx is fractional. This routine differs from
the short vector routines in that it uses 32 bits for dx/dy and dy/dx, with
16 bits fractional and 16 bits whole number. This allows it to draw a 
line across the whole screen, but it is just a bit slower.   */

laser()
{
int x_start,y_start,x,y,i,j,k,l,m,n;
int ptx[1000],pty[1000],pts,hit,incs;
int notes;
union lll{
int ii[2];
long ll;
} il;
union lll xrun;
union lll yrun;
union lll xdelt;
union lll ydelt;

yrun.ll = 0;
xrun.ll = 0;
hit = 0;
incs = 0;
pts = 0;
x_start = ship.x_pos;
y_start = ship.y_pos;
m = ship.angle;
i = sin(m);
j = cos(m);
ydelt.ii[1] = i ;
xdelt.ii[1] = j ;
if(i > 0) k = i;
else k = -i;
if(j > 0) l = j;
else l = - j;
il.ll = 0;
if(k > l)
 il.ii[0] = k;
else
 il.ii[0] = l;
xdelt.ll = xdelt.ll / il.ll;
ydelt.ll = ydelt.ll / il.ll;
yrun.ii[1] = y_start;
xrun.ii[1] = x_start;
notes = 0;
if(sound != 0)
 high_note('G');
/* we check for hits on objects as we draw the vector */
while (hit == 0)
 {
 x = xrun.ii[1];
 y = yrun.ii[1];
 xordot(x,y);
 /* draw the point and save the x,y pair for later erasure */
 ptx[pts] = x;
 pty[pts] = y;
 pts += 1;
 incs += 1;
 if(incs >= 8)
  {
  incs = 0;
  if(((x > X_LIMIT2) || (x < X_LIMIT1))  ||
     ((y > Y_LIMIT2) || (y < Y_LIMIT1)))
   hit = 999;
  for(i=0;i<MAX_MONSTER;i++)
   {
   if(monsters[i].alive == ALIVE)
    {
    j = x - monsters[i].x_pos;
    if(j < 0) j = -j;
    k = y - monsters[i].y_pos;
    if(k < 0) k = -k;
    if((j < MON_X_COL) && (k < MON_Y_COL))
     {
     if(sound != 0) high_note('E');
     hit = 999;
     kill_monst += 1;
     boom(monsters[i].x_pos,monsters[i].y_pos);
     xorobj(&monsters[i].x_vel);
     monsters[i].alive = 0;
     if(sound != 0) note_off();
     }
    }
   }
  for(i=0;i<MAX_SPECIAL;i++)
   {
   if(specials[i].alive == ALIVE)
    {
    j = x - specials[i].x_pos;
    if(j < 0) j = -j;
    k = y - specials[i].y_pos;
    if(k < 0) k = -k;
    if((j < SPC_X_COL) && (k < SPC_Y_COL))
     {
     if(sound != 0) high_note('B');
     hit = 999;
     kill_special += 1;
     boom(specials[i].x_pos,specials[i].y_pos);
     xorobj(&specials[i].x_vel);
     specials[i].alive = 0;
     if(sound != 0) note_off();
     }
    }
   }
  }
 xrun.ll += xdelt.ll;
 yrun.ll += ydelt.ll;
 }
if(sound != 0) note_off();
/* go back and erase the line by doing a second xor on the points */
for(i=0;i<pts;i++) xordot(ptx[i],pty[i]);
}


rotobj.c ####################### cut here   ###########################

#include "figures.h"
/*  routine to rotate a vector object John Unekis  1/18/87*/
/*  This routine requires that an object be represented as 
    both a set of cartesian vectors and as a set of polar
    (angle and radius vectors). In constructing a cartesian 
    figure from the polar representation, remember two 
    things- The screen has its origin in the upper left 
    corner with increasing y values going down, so that    
    angles  are flipped, also , the screen has an aspect 
    ratio which makes each y increment equal to approx.  
    twice the distance of an x increment, so y offsets must
    be scaled accordingly */
    /* No radius of a vector should be > 32 or this
       algorithm may overflow in the trig functions. To 
       avoid this, one might divide the trig values by 10
       before using   */

rotobj(p,q,ang)
struct object *p;
struct polar_object *q;
int ang;
{
register int k,l;
int i,j,m,n;
int y_off,x_off;

(*p).angle += ang;
if( (*p).angle < 0 ) (*p).angle += 360;
(*p).angle = (*p).angle % 360;
n = (*p).num_vertices;
for(i=0;i<n;i++)
 {
 j = (*q).angle[i] + (*p).angle;
 k = sin(j);            /* trig values scaled by 1000*/
 l = cos(j);
 k = k * (*q).radius[i];
 l = l * (*q).radius[i];
 
 (*p).x[i] = (l / 1000) + (*p).x_pos;
 k = k / 10;
 k = k * 2;       /* scale the y offset, avoiding overflow*/
 k = k + 150;
 k = k / 400;
 (*p).y[i] = k + (*p).y_pos;

 }

}
 


init_cos.c ####################### cut here   ###########################

int icos[360];
int isin[360];


/* in the interest of speed, the blastcga game stores the cosin
   and sin values precalculated in integer arrays. The array is
   indexed by integer degrees, and the return value is sin or
   cos , scaled by 1000 */

init_cos()
{

   isin[   0] =     0 ;
   icos[   0] =  1000 ;
   isin[   1] =    17 ;
   icos[   1] =   999 ;
   isin[   2] =    34 ;
   icos[   2] =   999 ;
   isin[   3] =    52 ;
   icos[   3] =   998 ;
   isin[   4] =    69 ;
   icos[   4] =   997 ;
   isin[   5] =    87 ;
   icos[   5] =   996 ;
   isin[   6] =   104 ;
   icos[   6] =   994 ;
   isin[   7] =   121 ;
   icos[   7] =   992 ;
   isin[   8] =   139 ;
   icos[   8] =   990 ;
   isin[   9] =   156 ;
   icos[   9] =   987 ;
   isin[  10] =   173 ;
   icos[  10] =   984 ;
   isin[  11] =   190 ;
   icos[  11] =   981 ;
   isin[  12] =   207 ;
   icos[  12] =   978 ;
   isin[  13] =   224 ;
   icos[  13] =   974 ;
   isin[  14] =   241 ;
   icos[  14] =   970 ;
   isin[  15] =   258 ;
   icos[  15] =   965 ;
   isin[  16] =   275 ;
   icos[  16] =   961 ;
   isin[  17] =   292 ;
   icos[  17] =   956 ;
   isin[  18] =   309 ;
   icos[  18] =   951 ;
   isin[  19] =   325 ;
   icos[  19] =   945 ;
   isin[  20] =   342 ;
   icos[  20] =   939 ;
   isin[  21] =   358 ;
   icos[  21] =   933 ;
   isin[  22] =   374 ;
   icos[  22] =   927 ;
   isin[  23] =   390 ;
   icos[  23] =   920 ;
   isin[  24] =   406 ;
   icos[  24] =   913 ;
   isin[  25] =   422 ;
   icos[  25] =   906 ;
   isin[  26] =   438 ;
   icos[  26] =   898 ;
   isin[  27] =   453 ;
   icos[  27] =   891 ;
   isin[  28] =   469 ;
   icos[  28] =   882 ;
   isin[  29] =   484 ;
   icos[  29] =   874 ;
   isin[  30] =   499 ;
   icos[  30] =   866 ;
   isin[  31] =   515 ;
   icos[  31] =   857 ;
   isin[  32] =   529 ;
   icos[  32] =   848 ;
   isin[  33] =   544 ;
   icos[  33] =   838 ;
   isin[  34] =   559 ;
   icos[  34] =   829 ;
   isin[  35] =   573 ;
   icos[  35] =   819 ;
   isin[  36] =   587 ;
   icos[  36] =   809 ;
   isin[  37] =   601 ;
   icos[  37] =   798 ;
   isin[  38] =   615 ;
   icos[  38] =   788 ;
   isin[  39] =   629 ;
   icos[  39] =   777 ;
   isin[  40] =   642 ;
   icos[  40] =   766 ;
   isin[  41] =   656 ;
   icos[  41] =   754 ;
   isin[  42] =   669 ;
   icos[  42] =   743 ;
   isin[  43] =   681 ;
   icos[  43] =   731 ;
   isin[  44] =   694 ;
   icos[  44] =   719 ;
   isin[  45] =   707 ;
   icos[  45] =   707 ;
   isin[  46] =   719 ;
   icos[  46] =   694 ;
   isin[  47] =   731 ;
   icos[  47] =   681 ;
   isin[  48] =   743 ;
   icos[  48] =   669 ;
   isin[  49] =   754 ;
   icos[  49] =   656 ;
   isin[  50] =   766 ;
   icos[  50] =   642 ;
   isin[  51] =   777 ;
   icos[  51] =   629 ;
   isin[  52] =   788 ;
   icos[  52] =   615 ;
   isin[  53] =   798 ;
   icos[  53] =   601 ;
   isin[  54] =   809 ;
   icos[  54] =   587 ;
   isin[  55] =   819 ;
   icos[  55] =   573 ;
   isin[  56] =   829 ;
   icos[  56] =   559 ;
   isin[  57] =   838 ;
   icos[  57] =   544 ;
   isin[  58] =   848 ;
   icos[  58] =   529 ;
   isin[  59] =   857 ;
   icos[  59] =   515 ;
   isin[  60] =   866 ;
   icos[  60] =   500 ;
   isin[  61] =   874 ;
   icos[  61] =   484 ;
   isin[  62] =   882 ;
   icos[  62] =   469 ;
   isin[  63] =   891 ;
   icos[  63] =   453 ;
   isin[  64] =   898 ;
   icos[  64] =   438 ;
   isin[  65] =   906 ;
   icos[  65] =   422 ;
   isin[  66] =   913 ;
   icos[  66] =   406 ;
   isin[  67] =   920 ;
   icos[  67] =   390 ;
   isin[  68] =   927 ;
   icos[  68] =   374 ;
   isin[  69] =   933 ;
   icos[  69] =   358 ;
   isin[  70] =   939 ;
   icos[  70] =   342 ;
   isin[  71] =   945 ;
   icos[  71] =   325 ;
   isin[  72] =   951 ;
   icos[  72] =   309 ;
   isin[  73] =   956 ;
   icos[  73] =   292 ;
   isin[  74] =   961 ;
   icos[  74] =   275 ;
   isin[  75] =   965 ;
   icos[  75] =   258 ;
   isin[  76] =   970 ;
   icos[  76] =   241 ;
   isin[  77] =   974 ;
   icos[  77] =   224 ;
   isin[  78] =   978 ;
   icos[  78] =   207 ;
   isin[  79] =   981 ;
   icos[  79] =   190 ;
   isin[  80] =   984 ;
   icos[  80] =   173 ;
   isin[  81] =   987 ;
   icos[  81] =   156 ;
   isin[  82] =   990 ;
   icos[  82] =   139 ;
   isin[  83] =   992 ;
   icos[  83] =   121 ;
   isin[  84] =   994 ;
   icos[  84] =   104 ;
   isin[  85] =   996 ;
   icos[  85] =    87 ;
   isin[  86] =   997 ;
   icos[  86] =    69 ;
   isin[  87] =   998 ;
   icos[  87] =    52 ;
   isin[  88] =   999 ;
   icos[  88] =    34 ;
   isin[  89] =   999 ;
   icos[  89] =    17 ;
   isin[  90] =  1000 ;
   icos[  90] =     0 ;
   isin[  91] =   999 ;
   icos[  91] =   -17 ;
   isin[  92] =   999 ;
   icos[  92] =   -34 ;
   isin[  93] =   998 ;
   icos[  93] =   -52 ;
   isin[  94] =   997 ;
   icos[  94] =   -69 ;
   isin[  95] =   996 ;
   icos[  95] =   -87 ;
   isin[  96] =   994 ;
   icos[  96] =  -104 ;
   isin[  97] =   992 ;
   icos[  97] =  -121 ;
   isin[  98] =   990 ;
   icos[  98] =  -139 ;
   isin[  99] =   987 ;
   icos[  99] =  -156 ;
   isin[ 100] =   984 ;
   icos[ 100] =  -173 ;
   isin[ 101] =   981 ;
   icos[ 101] =  -190 ;
   isin[ 102] =   978 ;
   icos[ 102] =  -207 ;
   isin[ 103] =   974 ;
   icos[ 103] =  -224 ;
   isin[ 104] =   970 ;
   icos[ 104] =  -241 ;
   isin[ 105] =   965 ;
   icos[ 105] =  -258 ;
   isin[ 106] =   961 ;
   icos[ 106] =  -275 ;
   isin[ 107] =   956 ;
   icos[ 107] =  -292 ;
   isin[ 108] =   951 ;
   icos[ 108] =  -309 ;
   isin[ 109] =   945 ;
   icos[ 109] =  -325 ;
   isin[ 110] =   939 ;
   icos[ 110] =  -342 ;
   isin[ 111] =   933 ;
   icos[ 111] =  -358 ;
   isin[ 112] =   927 ;
   icos[ 112] =  -374 ;
   isin[ 113] =   920 ;
   icos[ 113] =  -390 ;
   isin[ 114] =   913 ;
   icos[ 114] =  -406 ;
   isin[ 115] =   906 ;
   icos[ 115] =  -422 ;
   isin[ 116] =   898 ;
   icos[ 116] =  -438 ;
   isin[ 117] =   891 ;
   icos[ 117] =  -453 ;
   isin[ 118] =   882 ;
   icos[ 118] =  -469 ;
   isin[ 119] =   874 ;
   icos[ 119] =  -484 ;
   isin[ 120] =   866 ;
   icos[ 120] =  -499 ;
   isin[ 121] =   857 ;
   icos[ 121] =  -515 ;
   isin[ 122] =   848 ;
   icos[ 122] =  -529 ;
   isin[ 123] =   838 ;
   icos[ 123] =  -544 ;
   isin[ 124] =   829 ;
   icos[ 124] =  -559 ;
   isin[ 125] =   819 ;
   icos[ 125] =  -573 ;
   isin[ 126] =   809 ;
   icos[ 126] =  -587 ;
   isin[ 127] =   798 ;
   icos[ 127] =  -601 ;
   isin[ 128] =   788 ;
   icos[ 128] =  -615 ;
   isin[ 129] =   777 ;
   icos[ 129] =  -629 ;
   isin[ 130] =   766 ;
   icos[ 130] =  -642 ;
   isin[ 131] =   754 ;
   icos[ 131] =  -656 ;
   isin[ 132] =   743 ;
   icos[ 132] =  -669 ;
   isin[ 133] =   731 ;
   icos[ 133] =  -681 ;
   isin[ 134] =   719 ;
   icos[ 134] =  -694 ;
   isin[ 135] =   707 ;
   icos[ 135] =  -707 ;
   isin[ 136] =   694 ;
   icos[ 136] =  -719 ;
   isin[ 137] =   681 ;
   icos[ 137] =  -731 ;
   isin[ 138] =   669 ;
   icos[ 138] =  -743 ;
   isin[ 139] =   656 ;
   icos[ 139] =  -754 ;
   isin[ 140] =   642 ;
   icos[ 140] =  -766 ;
   isin[ 141] =   629 ;
   icos[ 141] =  -777 ;
   isin[ 142] =   615 ;
   icos[ 142] =  -788 ;
   isin[ 143] =   601 ;
   icos[ 143] =  -798 ;
   isin[ 144] =   587 ;
   icos[ 144] =  -809 ;
   isin[ 145] =   573 ;
   icos[ 145] =  -819 ;
   isin[ 146] =   559 ;
   icos[ 146] =  -829 ;
   isin[ 147] =   544 ;
   icos[ 147] =  -838 ;
   isin[ 148] =   529 ;
   icos[ 148] =  -848 ;
   isin[ 149] =   515 ;
   icos[ 149] =  -857 ;
   isin[ 150] =   500 ;
   icos[ 150] =  -866 ;
   isin[ 151] =   484 ;
   icos[ 151] =  -874 ;
   isin[ 152] =   469 ;
   icos[ 152] =  -882 ;
   isin[ 153] =   453 ;
   icos[ 153] =  -891 ;
   isin[ 154] =   438 ;
   icos[ 154] =  -898 ;
   isin[ 155] =   422 ;
   icos[ 155] =  -906 ;
   isin[ 156] =   406 ;
   icos[ 156] =  -913 ;
   isin[ 157] =   390 ;
   icos[ 157] =  -920 ;
   isin[ 158] =   374 ;
   icos[ 158] =  -927 ;
   isin[ 159] =   358 ;
   icos[ 159] =  -933 ;
   isin[ 160] =   342 ;
   icos[ 160] =  -939 ;
   isin[ 161] =   325 ;
   icos[ 161] =  -945 ;
   isin[ 162] =   309 ;
   icos[ 162] =  -951 ;
   isin[ 163] =   292 ;
   icos[ 163] =  -956 ;
   isin[ 164] =   275 ;
   icos[ 164] =  -961 ;
   isin[ 165] =   258 ;
   icos[ 165] =  -965 ;
   isin[ 166] =   241 ;
   icos[ 166] =  -970 ;
   isin[ 167] =   224 ;
   icos[ 167] =  -974 ;
   isin[ 168] =   207 ;
   icos[ 168] =  -978 ;
   isin[ 169] =   190 ;
   icos[ 169] =  -981 ;
   isin[ 170] =   173 ;
   icos[ 170] =  -984 ;
   isin[ 171] =   156 ;
   icos[ 171] =  -987 ;
   isin[ 172] =   139 ;
   icos[ 172] =  -990 ;
   isin[ 173] =   121 ;
   icos[ 173] =  -992 ;
   isin[ 174] =   104 ;
   icos[ 174] =  -994 ;
   isin[ 175] =    87 ;
   icos[ 175] =  -996 ;
   isin[ 176] =    69 ;
   icos[ 176] =  -997 ;
   isin[ 177] =    52 ;
   icos[ 177] =  -998 ;
   isin[ 178] =    34 ;
   icos[ 178] =  -999 ;
   isin[ 179] =    17 ;
   icos[ 179] =  -999 ;
   isin[ 180] =     0 ;
   icos[ 180] = -1000 ;
   isin[ 181] =   -17 ;
   icos[ 181] =  -999 ;
   isin[ 182] =   -34 ;
   icos[ 182] =  -999 ;
   isin[ 183] =   -52 ;
   icos[ 183] =  -998 ;
   isin[ 184] =   -69 ;
   icos[ 184] =  -997 ;
   isin[ 185] =   -87 ;
   icos[ 185] =  -996 ;
   isin[ 186] =  -104 ;
   icos[ 186] =  -994 ;
   isin[ 187] =  -121 ;
   icos[ 187] =  -992 ;
   isin[ 188] =  -139 ;
   icos[ 188] =  -990 ;
   isin[ 189] =  -156 ;
   icos[ 189] =  -987 ;
   isin[ 190] =  -173 ;
   icos[ 190] =  -984 ;
   isin[ 191] =  -190 ;
   icos[ 191] =  -981 ;
   isin[ 192] =  -207 ;
   icos[ 192] =  -978 ;
   isin[ 193] =  -224 ;
   icos[ 193] =  -974 ;
   isin[ 194] =  -241 ;
   icos[ 194] =  -970 ;
   isin[ 195] =  -258 ;
   icos[ 195] =  -965 ;
   isin[ 196] =  -275 ;
   icos[ 196] =  -961 ;
   isin[ 197] =  -292 ;
   icos[ 197] =  -956 ;
   isin[ 198] =  -309 ;
   icos[ 198] =  -951 ;
   isin[ 199] =  -325 ;
   icos[ 199] =  -945 ;
   isin[ 200] =  -342 ;
   icos[ 200] =  -939 ;
   isin[ 201] =  -358 ;
   icos[ 201] =  -933 ;
   isin[ 202] =  -374 ;
   icos[ 202] =  -927 ;
   isin[ 203] =  -390 ;
   icos[ 203] =  -920 ;
   isin[ 204] =  -406 ;
   icos[ 204] =  -913 ;
   isin[ 205] =  -422 ;
   icos[ 205] =  -906 ;
   isin[ 206] =  -438 ;
   icos[ 206] =  -898 ;
   isin[ 207] =  -453 ;
   icos[ 207] =  -891 ;
   isin[ 208] =  -469 ;
   icos[ 208] =  -882 ;
   isin[ 209] =  -484 ;
   icos[ 209] =  -874 ;
   isin[ 210] =  -499 ;
   icos[ 210] =  -866 ;
   isin[ 211] =  -515 ;
   icos[ 211] =  -857 ;
   isin[ 212] =  -529 ;
   icos[ 212] =  -848 ;
   isin[ 213] =  -544 ;
   icos[ 213] =  -838 ;
   isin[ 214] =  -559 ;
   icos[ 214] =  -829 ;
   isin[ 215] =  -573 ;
   icos[ 215] =  -819 ;
   isin[ 216] =  -587 ;
   icos[ 216] =  -809 ;
   isin[ 217] =  -601 ;
   icos[ 217] =  -798 ;
   isin[ 218] =  -615 ;
   icos[ 218] =  -788 ;
   isin[ 219] =  -629 ;
   icos[ 219] =  -777 ;
   isin[ 220] =  -642 ;
   icos[ 220] =  -766 ;
   isin[ 221] =  -656 ;
   icos[ 221] =  -754 ;
   isin[ 222] =  -669 ;
   icos[ 222] =  -743 ;
   isin[ 223] =  -681 ;
   icos[ 223] =  -731 ;
   isin[ 224] =  -694 ;
   icos[ 224] =  -719 ;
   isin[ 225] =  -707 ;
   icos[ 225] =  -707 ;
   isin[ 226] =  -719 ;
   icos[ 226] =  -694 ;
   isin[ 227] =  -731 ;
   icos[ 227] =  -682 ;
   isin[ 228] =  -743 ;
   icos[ 228] =  -669 ;
   isin[ 229] =  -754 ;
   icos[ 229] =  -656 ;
   isin[ 230] =  -766 ;
   icos[ 230] =  -642 ;
   isin[ 231] =  -777 ;
   icos[ 231] =  -629 ;
   isin[ 232] =  -788 ;
   icos[ 232] =  -615 ;
   isin[ 233] =  -798 ;
   icos[ 233] =  -601 ;
   isin[ 234] =  -809 ;
   icos[ 234] =  -587 ;
   isin[ 235] =  -819 ;
   icos[ 235] =  -573 ;
   isin[ 236] =  -829 ;
   icos[ 236] =  -559 ;
   isin[ 237] =  -838 ;
   icos[ 237] =  -544 ;
   isin[ 238] =  -848 ;
   icos[ 238] =  -529 ;
   isin[ 239] =  -857 ;
   icos[ 239] =  -515 ;
   isin[ 240] =  -866 ;
   icos[ 240] =  -500 ;
   isin[ 241] =  -874 ;
   icos[ 241] =  -484 ;
   isin[ 242] =  -882 ;
   icos[ 242] =  -469 ;
   isin[ 243] =  -891 ;
   icos[ 243] =  -453 ;
   isin[ 244] =  -898 ;
   icos[ 244] =  -438 ;
   isin[ 245] =  -906 ;
   icos[ 245] =  -422 ;
   isin[ 246] =  -913 ;
   icos[ 246] =  -406 ;
   isin[ 247] =  -920 ;
   icos[ 247] =  -390 ;
   isin[ 248] =  -927 ;
   icos[ 248] =  -374 ;
   isin[ 249] =  -933 ;
   icos[ 249] =  -358 ;
   isin[ 250] =  -939 ;
   icos[ 250] =  -342 ;
   isin[ 251] =  -945 ;
   icos[ 251] =  -325 ;
   isin[ 252] =  -951 ;
   icos[ 252] =  -309 ;
   isin[ 253] =  -956 ;
   icos[ 253] =  -292 ;
   isin[ 254] =  -961 ;
   icos[ 254] =  -275 ;
   isin[ 255] =  -965 ;
   icos[ 255] =  -258 ;
   isin[ 256] =  -970 ;
   icos[ 256] =  -241 ;
   isin[ 257] =  -974 ;
   icos[ 257] =  -224 ;
   isin[ 258] =  -978 ;
   icos[ 258] =  -207 ;
   isin[ 259] =  -981 ;
   icos[ 259] =  -190 ;
   isin[ 260] =  -984 ;
   icos[ 260] =  -173 ;
   isin[ 261] =  -987 ;
   icos[ 261] =  -156 ;
   isin[ 262] =  -990 ;
   icos[ 262] =  -139 ;
   isin[ 263] =  -992 ;
   icos[ 263] =  -121 ;
   isin[ 264] =  -994 ;
   icos[ 264] =  -104 ;
   isin[ 265] =  -996 ;
   icos[ 265] =   -87 ;
   isin[ 266] =  -997 ;
   icos[ 266] =   -69 ;
   isin[ 267] =  -998 ;
   icos[ 267] =   -52 ;
   isin[ 268] =  -999 ;
   icos[ 268] =   -34 ;
   isin[ 269] =  -999 ;
   icos[ 269] =   -17 ;
   isin[ 270] = -1000 ;
   icos[ 270] =     0 ;
   isin[ 271] =  -999 ;
   icos[ 271] =    17 ;
   isin[ 272] =  -999 ;
   icos[ 272] =    34 ;
   isin[ 273] =  -998 ;
   icos[ 273] =    52 ;
   isin[ 274] =  -997 ;
   icos[ 274] =    69 ;
   isin[ 275] =  -996 ;
   icos[ 275] =    87 ;
   isin[ 276] =  -994 ;
   icos[ 276] =   104 ;
   isin[ 277] =  -992 ;
   icos[ 277] =   121 ;
   isin[ 278] =  -990 ;
   icos[ 278] =   139 ;
   isin[ 279] =  -987 ;
   icos[ 279] =   156 ;
   isin[ 280] =  -984 ;
   icos[ 280] =   173 ;
   isin[ 281] =  -981 ;
   icos[ 281] =   190 ;
   isin[ 282] =  -978 ;
   icos[ 282] =   207 ;
   isin[ 283] =  -974 ;
   icos[ 283] =   224 ;
   isin[ 284] =  -970 ;
   icos[ 284] =   241 ;
   isin[ 285] =  -965 ;
   icos[ 285] =   258 ;
   isin[ 286] =  -961 ;
   icos[ 286] =   275 ;
   isin[ 287] =  -956 ;
   icos[ 287] =   292 ;
   isin[ 288] =  -951 ;
   icos[ 288] =   309 ;
   isin[ 289] =  -945 ;
   icos[ 289] =   325 ;
   isin[ 290] =  -939 ;
   icos[ 290] =   342 ;
   isin[ 291] =  -933 ;
   icos[ 291] =   358 ;
   isin[ 292] =  -927 ;
   icos[ 292] =   374 ;
   isin[ 293] =  -920 ;
   icos[ 293] =   390 ;
   isin[ 294] =  -913 ;
   icos[ 294] =   406 ;
   isin[ 295] =  -906 ;
   icos[ 295] =   422 ;
   isin[ 296] =  -898 ;
   icos[ 296] =   438 ;
   isin[ 297] =  -891 ;
   icos[ 297] =   453 ;
   isin[ 298] =  -882 ;
   icos[ 298] =   469 ;
   isin[ 299] =  -874 ;
   icos[ 299] =   484 ;
   isin[ 300] =  -866 ;
   icos[ 300] =   499 ;
   isin[ 301] =  -857 ;
   icos[ 301] =   515 ;
   isin[ 302] =  -848 ;
   icos[ 302] =   529 ;
   isin[ 303] =  -838 ;
   icos[ 303] =   544 ;
   isin[ 304] =  -829 ;
   icos[ 304] =   559 ;
   isin[ 305] =  -819 ;
   icos[ 305] =   573 ;
   isin[ 306] =  -809 ;
   icos[ 306] =   587 ;
   isin[ 307] =  -798 ;
   icos[ 307] =   601 ;
   isin[ 308] =  -788 ;
   icos[ 308] =   615 ;
   isin[ 309] =  -777 ;
   icos[ 309] =   629 ;
   isin[ 310] =  -766 ;
   icos[ 310] =   642 ;
   isin[ 311] =  -754 ;
   icos[ 311] =   656 ;
   isin[ 312] =  -743 ;
   icos[ 312] =   669 ;
   isin[ 313] =  -731 ;
   icos[ 313] =   681 ;
   isin[ 314] =  -719 ;
   icos[ 314] =   694 ;
   isin[ 315] =  -707 ;
   icos[ 315] =   707 ;
   isin[ 316] =  -694 ;
   icos[ 316] =   719 ;
   isin[ 317] =  -682 ;
   icos[ 317] =   731 ;
   isin[ 318] =  -669 ;
   icos[ 318] =   743 ;
   isin[ 319] =  -656 ;
   icos[ 319] =   754 ;
   isin[ 320] =  -642 ;
   icos[ 320] =   766 ;
   isin[ 321] =  -629 ;
   icos[ 321] =   777 ;
   isin[ 322] =  -615 ;
   icos[ 322] =   788 ;
   isin[ 323] =  -601 ;
   icos[ 323] =   798 ;
   isin[ 324] =  -587 ;
   icos[ 324] =   809 ;
   isin[ 325] =  -573 ;
   icos[ 325] =   819 ;
   isin[ 326] =  -559 ;
   icos[ 326] =   829 ;
   isin[ 327] =  -544 ;
   icos[ 327] =   838 ;
   isin[ 328] =  -529 ;
   icos[ 328] =   848 ;
   isin[ 329] =  -515 ;
   icos[ 329] =   857 ;
   isin[ 330] =  -500 ;
   icos[ 330] =   866 ;
   isin[ 331] =  -484 ;
   icos[ 331] =   874 ;
   isin[ 332] =  -469 ;
   icos[ 332] =   882 ;
   isin[ 333] =  -453 ;
   icos[ 333] =   891 ;
   isin[ 334] =  -438 ;
   icos[ 334] =   898 ;
   isin[ 335] =  -422 ;
   icos[ 335] =   906 ;
   isin[ 336] =  -406 ;
   icos[ 336] =   913 ;
   isin[ 337] =  -390 ;
   icos[ 337] =   920 ;
   isin[ 338] =  -374 ;
   icos[ 338] =   927 ;
   isin[ 339] =  -358 ;
   icos[ 339] =   933 ;
   isin[ 340] =  -342 ;
   icos[ 340] =   939 ;
   isin[ 341] =  -325 ;
   icos[ 341] =   945 ;
   isin[ 342] =  -309 ;
   icos[ 342] =   951 ;
   isin[ 343] =  -292 ;
   icos[ 343] =   956 ;
   isin[ 344] =  -275 ;
   icos[ 344] =   961 ;
   isin[ 345] =  -258 ;
   icos[ 345] =   965 ;
   isin[ 346] =  -241 ;
   icos[ 346] =   970 ;
   isin[ 347] =  -224 ;
   icos[ 347] =   974 ;
   isin[ 348] =  -207 ;
   icos[ 348] =   978 ;
   isin[ 349] =  -190 ;
   icos[ 349] =   981 ;
   isin[ 350] =  -173 ;
   icos[ 350] =   984 ;
   isin[ 351] =  -156 ;
   icos[ 351] =   987 ;
   isin[ 352] =  -139 ;
   icos[ 352] =   990 ;
   isin[ 353] =  -121 ;
   icos[ 353] =   992 ;
   isin[ 354] =  -104 ;
   icos[ 354] =   994 ;
   isin[ 355] =   -87 ;
   icos[ 355] =   996 ;
   isin[ 356] =   -69 ;
   icos[ 356] =   997 ;
   isin[ 357] =   -52 ;
   icos[ 357] =   998 ;
   isin[ 358] =   -34 ;
   icos[ 358] =   999 ;
   isin[ 359] =   -17 ;
   icos[ 359] =   999 ;
}

int sin(i)
int i;
{
i = i % 360;
return(isin[i]);
}

int cos(j)
int j;
{
j = j % 360;
return(icos[j]);
}



dmode.c ####################### cut here   ###########################

/* regardless of argument, put cga into mode 6 (mono) */
graphmode(i)
int i;
{
dismode(6);
}
/* put cga back to 80 column color mode */
textmode()
{
dismode(3);
}

dismode.asm ####################### cut here   ###########################

;	Static Name Aliases
;
;   This routine will call BIOS to change the display mode of the 
;   cga or ega controller
; 
; it is called as  dismode(mode)
;
; any IBM manual should give a complete description of the display
; modes
; for now      hex 6 is mono graphics 640 x 200
;              hex 3 is 80 column text in color

	TITLE   dismode

	.287
DISMODE_TEXT	SEGMENT  BYTE PUBLIC 'CODE'
DISMODE_TEXT	ENDS
_DATA	SEGMENT  WORD PUBLIC 'DATA'
_DATA	ENDS
CONST	SEGMENT  WORD PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT  WORD PUBLIC 'BSS'
_BSS	ENDS
DGROUP	GROUP	CONST,	_BSS,	_DATA
	ASSUME  CS: DISMODE_TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
EXTRN	__chkstk:FAR
DISMODE_TEXT      SEGMENT
	PUBLIC	_dismode
_dismode	PROC FAR
	push	bp
	mov	bp,sp
	xor	ax,ax
	call	FAR PTR __chkstk
	mov	ax,[bp+6]	
     mov  ah,00h
     int  10h
	mov	sp,bp
	pop	bp
	ret	

_dismode	ENDP
DISMODE_TEXT	ENDS
END