[comp.sources.atari.st] v00i025: mwc:low: forever.c - linea example & pretty picture gen

atari-sources-request@daisy.UUCP (08/09/87)

Submitted by: <sun!hplabs!tektronix!dadla.TEK.COM!jrb>
comp.sources.atari.st: Volume 0, Issue 25
Archive-name: forever

=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
[Ed.'s Note]
aside from drawing pretty pictures, this is an example of how to use
linea, the cksm is:

bytes =     5985(     6407)   cksm = 2353   kalidascope.c

=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

I would like to submit the following which is a simple
kalleidoscope program for the st. I am interesting in getting
ahold of some non-trivial programming examples in C that
manipulate linea primitives.

			Jim Binkley
			jrb@dadla.tek.com



/*
 * forever.c - Atari st graphics kalleidoscope
 *
 * Any character to quit.
 *
 * Should be run in low rez.
 *
 * Uses linea routines. Mark Williams 2.0 C.
 */

#include <osbind.h>
#include <linea.h>

static int color;
#define setColor(x) (color = x)
#define setpixel(x,y)	((PTSIN[0]=x), (PTSIN[1]=y),(INTIN[0]=color),linea1())

#define WHITE 0x777
#define BLACK 0x000
#define BLUE  0x007
#define GREEN 0x070
#define RED   0x700

int bluePal[] =
{
0x0777, 0x0124, 0x0214, 0x0324,
0x0424, 0x0417, 0x0336, 0x0517,
0x0437, 0x0716, 0x0727, 0x0700,
0x0704, 0x0705, 0x0706, 0x0707
};

static int gemPal[16];

/* assume 320 by 200
*/
#define CENTERX  160
#define CENTERY	 100

/* per "process" pen info
*/

static 
struct pp {
	int color;
	int howfat;
} pi[4] = {
	1,0,
	1,0,
	1,0,
	1,0,
};

/* per "process" coords
*/
static
struct chaninfo {
	int cx,cy;
	int opType;
	int xdir,ydir;
} ci[4];

main()
{
	extern int bluePal[];
	int count=0;
	int doit;
	int pal1,pal2;
	int palstate=0;
 
	openScreen();
	newPal(bluePal);
	pal1 = 2;
	pal2 = 12;
	
	/* loop while no keyboard input
	*/
	for ( ; Cconis() == 0;count++ ) {
		drunkWalk(0);
		drunkWalk(1);
		drunkWalk(2);
		drunkWalk(3);

		if ( count == 500 )
			if ((rand()%2)==0)
				doit = 1;
			else { 
				
				shufflePal(bluePal);
				doit = 0;
			}

		if ( count > 600 &&
		     count < 1000 ){
			if(doit) {
				if(palstate%2) {
					pal1 = rand() % 16;
					pal2 = rand() % 16;
					twopal(bluePal,pal1,pal2);
				}
				else {
					pal1++;
					pal2++;
					if (pal1 > 15)
						pal1 = 1;
					if (pal2 > 15)
						pal2 = 1;
					twopal(bluePal,pal1,pal2);
				}
			}
		}

		if ( count > 1000){
			palstate++;
			damage(bluePal);
			count=0;
		}
	}
	closeScreen();
}


/*
 * drunkWalk
 *
 * implements drunken walk. 
 *
 * i is integer index to indicate which mos channel
 * is requesting graphics
 *
 * CALLS:
 *	rand - random number generator.
 *	kplot - plot current drunken walk graphics
 */

static
drunkWalk(i)
{
	register int n,s,t;
	struct chaninfo *cpt;

	cpt = &ci[i];
	cpt->opType = 1;

	/* pick starting delta x,y
	*/
	cpt->cx = rand() % 160;
	cpt->cy = rand() % 100;

	n = rand()%127;
	t = rand()%127;
	/* walk change according to note mod 8, mod 12??
	*/
	switch(n % 8) {
	case 0:
		cpt->xdir = 1;
		break;
	case 1:
		cpt->xdir = 1;
		cpt->ydir = -1;
		break;
	case 2:
		cpt->xdir = -1;
		break;
	case 3:
		cpt->xdir = -1;
		cpt->ydir = -1;
		break;
	case 4:
		cpt->xdir = 1;
		cpt->ydir = 1;
		break;
	case 5:
		cpt->ydir = 1;
		break;
	case 6:
		cpt->ydir = -1;
		cpt->ydir = 1;
		break;
	case 7:
		cpt->xdir = -1;
		break;
	}

	kplot(t, i, cpt->cx += cpt->xdir, cpt->cy += cpt->ydir);
	kplot(t, i, cpt->cx += cpt->xdir, cpt->cy += cpt->ydir);
	/* boundary check. If at boundary, we rerandomize
	*/
	if ( cpt->cx >= 160 || cpt->cx < 0 )
		cpt->cx = rand() % 30;
	if (cpt->cy >= 100 || cpt->cy < 0 )
			cpt->cy = rand() % 40;
}

/* do graphics work on one pixel. four dots are drawn,
 * one per quadrant.
 */
static
kplot(t, i, deltax,deltay)
int t;       /* event time */
register int i;       /* per coroutine index */
register int deltax,deltay;
{
	register int x,y;
	int chowfat;

	/* randomly switch pen thickness and color
	*/
	if ( (rand() % 80) == 20 ) {

		pi[i].howfat = (rand() >> 4) % 4;

		/* randomly choose pen color
		*/
		if ( (rand() % 2) == 0 )
			color = t % 16;
		else
			color = rand() % 16;
		if ( color == 0 )
			color++;

	}
	chowfat = pi[i].howfat;

	x = CENTERX+deltax;
	y = CENTERY+deltay;
	setpixel(x,y);
	switch(chowfat) {
	case 0:
		break;

	case 1:
		setpixel(x-1,y);
		setpixel(x+1,y);
		break;

	case 2:
		setpixel(x+1,y);
		setpixel(x+1,y+1);
		setpixel(x+1,y-1);
		setpixel(x,y+1);
		setpixel(x,y);
		setpixel(x-1,y);
		setpixel(x,y-1);
		setpixel(x,y-2);
		break;

	case 3:
		setpixel(x,y-1);
		setpixel(x,y-2);
		break;
	}

	x = CENTERX+deltax;
	y = CENTERY-deltay;

	setpixel(x,y);
	switch(chowfat) {
	case 0:
		break;

	case 1:
		setpixel(x-1,y);
		setpixel(x+1,y);
		break;

	case 2:
		setpixel(x+1,y);
		setpixel(x+1,y+1);
		setpixel(x+1,y-1);
		setpixel(x,y+1);
		setpixel(x,y);
		setpixel(x-1,y);
		setpixel(x,y-2);
		setpixel(x,y-1);
		break;
	case 3:
		setpixel(x,y-1);
		setpixel(x,y-2);
		break;
	}
	x = CENTERX-deltax;
	y = CENTERY+deltay;
	setpixel(x,y);
	switch(chowfat) {
	case 0:
		break;

	case 1:
		setpixel(x-1,y);
		setpixel(x+1,y);
		break;

	case 2:
		setpixel(x+1,y);
		setpixel(x+1,y+1);
		setpixel(x+1,y-1);
		setpixel(x,y+1);
		setpixel(x,y);
		setpixel(x-1,y);
		setpixel(x,y-2);
		setpixel(x,y-1);
		break;
	case 3:
		setpixel(x,y-1);
		setpixel(x,y-2);
		break;
	}
	x = CENTERX-deltax;
	y = CENTERY-deltay;
	setpixel(x,y);
	switch(chowfat) {
	case 0:
		break;

	case 1:
		setpixel(x-1,y);
		setpixel(x+1,y);
		break;

	case 2:
		setpixel(x+1,y);
		setpixel(x+1,y+1);
		setpixel(x+1,y-1);
		setpixel(x,y+1);
		setpixel(x,y);
		setpixel(x-1,y);
		setpixel(x,y-2);
		setpixel(x,y-1);
		break;
	case 3:
		setpixel(x,y-1);
		setpixel(x,y-2);
		break;
	}
}

openScreen()
{
	linea0();
	lineaa();
	Cconws("\033E\033f");    /* erase screen */
}

closeScreen()
{
	Cconin();
	Cconws("\033e\n");
}



/* shift pallete positions. First position remains white.
*/
shufflePal(pal)
int pal[];
{
	int first;
	int index;

	first = pal[1];
	for ( index = 1; index < 15; index++)
		pal[index] = pal[index+1];
	pal[15] = first;
	pal[0] = WHITE;
	newPal(pal);
}

twopal(pal,one,two)
int pal[]; 
{
	int tmp;
	tmp = pal[one];
	pal[one] = pal[two];
	pal[two] = tmp;
	newPal(pal);
}

/* do something kinky to pal
*/
damage(pal)
int pal[];
{
	register int n;
	register int r,g,b;
	n = rand() % 16;
	r = rand() % 0x7;
	g = rand() % 0x7;
	b = rand() % 0x7;
	pal[n] = b | (g << 4) |  (r << 8 );
}


/* get default pallete
*/
openPal()
{
	register int i;

	/* get original pallete
	*/
	for (i = 0; i < 16; i++)
		gemPal[i] = Setcolor(i, -1);
}

/* restore original pallete
*/
closePal()
{
	Setpallete(gemPal);
}

/* write new pallete
*/
newPal(pal)
int pal[];
{
	Setpallete(pal);
}