1 /*
2 
3 Founts by David Ashley
4 http://www.xdr.com/dash
5 dash@xdr.com
6 Written about May 1999
7 
8 Inspired by Eric's Cascade which is overpriced at $39. We needed a free
9 equivalent!
10 
11 This is free software released under the terms of the GPL
12 
13 */
14 
15 
16 
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include "SDL.h"
24 #include "math.h"
25 #include <fcntl.h>
26 
27 void scaninput(void);
28 void makebbm(void);
29 struct block;
30 int checkblock(struct block *);
31 
32 #define PI 3.1415926535897932
33 
34 #define VIRTX 640
35 #define VIRTY 480
36 
37 int IXSIZE=VIRTX;
38 int IYSIZE=VIRTY;
39 
40 #define NOTDOWN 0
41 #define JUSTDOWN 1
42 #define CONTDOWN 2
43 
44 #define NUMTYPES 14
45 
46 
47 #define FRACTION 8
48 #define SPEEDDELTA (1<<FRACTION-1)
49 #define SPEEDMAX (10<<FRACTION)
50 
51 #define BOTTOM 16
52 
53 #define MAXBALLS 4096
54 #define MAXHOSES 64
55 #define MAXBLOCKS 64
56 
57 #define MAXCOLORS 256
58 
59 
60 typedef unsigned char uchar;
61 
62 typedef struct gfxset
63 {
64 	uchar gs_colormap[768];
65 	uchar gs_inout[256];
66 	uchar *gs_pic;
67 	int gs_xsize;
68 	int gs_ysize;
69 } gfxset;
70 
71 
72 typedef struct list
73 {
74 	void *next;
75 } list;
76 
77 
78 #define MAXTHINGS 500
79 
80 
81 extern void initlist(void *first,int size,int num);
82 extern void freeentry(void *entry);
83 extern void addtail(void *header,void *entry);
84 extern void delink(void *header,void *entry);
85 extern void *allocentry();
86 
87 void tri(int x1,int y1,int x2,int y2,int x3,int y3,
88 		void (*func)(int,int,int,long),long color);
89 
90 
91 
92 unsigned short *dummyball,*colorballs[32],*ballarray[512];
93 
94 int gravity=8;
95 
96 #define MIXFRAC 3
97 int vals[4][(VIRTY>>MIXFRAC)*(VIRTX>>MIXFRAC)];
98 
99 unsigned char *block64;
100 
101 char pauseflag=0;
102 
103 #define REGISTERLEN (1+4+4+4+16+1)
104 
105 char mixing,dospiral,dosphere,dohide,rotating;
106 
107 int spinangle;
108 
109 int mousex,mousey;
110 int buttonstate;
111 
112 char sdlloaded=0;
113 
114 unsigned char *bbm;
115 
116 SDL_Surface *thescreen;
117 SDL_Color themap[256];
118 unsigned char mymap[3*MAXCOLORS];
119 int allocatedcolors=1;
120 int usedcolors=1;
121 int stridemult[2048];
122 int bitsperpixel;
123 
124 unsigned char redvals[]=  {255,0,0,255,0,255,255,0,64,96,128,160,192,224};
125 unsigned char greenvals[]={0,255,0,255,255,0,255,0,0,0,0,0,0,0};
126 unsigned char bluevals[]= {0,0,255,0,255,255,255,128,0,0,0,0,0,0};
127 
128 char *preset[10]={0};
129 
130 unsigned char *fractback=0;
131 
132 
133 void *things=0;
134 int thingsize,thingnum;
135 
136 int dopcx(char *name,gfxset *gs);
137 
138 int hc=0;
139 int gamemode;
140 char exitflag=0;
141 int framecount=0;
142 
143 unsigned char regpacket[64];
144 char gameversion[4]={0xda,0x01,0x00,0x01};
145 char playername[16];
146 
147 int stride;
148 unsigned char *videomem;
149 int frames;
150 
clear(void)151 void clear(void)
152 {
153 unsigned char *p1,*p2;
154 int i,w;
155 
156 	p1=videomem;
157 	p2=fractback;
158 	w=(bitsperpixel==16) ? IXSIZE<<1 : IXSIZE;
159 	for(i=0;i<IYSIZE;++i)
160 	{
161 		if(!p2)
162 			memset(p1,0,w);
163 		else
164 		{
165 			memmove(p1,p2,w);
166 			p2+=w;
167 		}
168 		p1+=stride;
169 	}
170 }
171 
drawfigure(int x,int y,unsigned short * take)172 void drawfigure(int x,int y,unsigned short *take)
173 {
174 unsigned short *p1,*p2;
175 int run;
176 int dx,dy;
177 int xsize,ysize;
178 unsigned char *pc;
179 
180 	if(!take) take=dummyball;
181 
182 	dx=*((signed short *)take);++take;
183 	dy=*((signed short *)take);++take;
184 	xsize=*take++;
185 	ysize=*take++;
186 	x+=dx;
187 	y+=dy;
188 	if(x>=0 && y>=0 && x<=IXSIZE-xsize && y<=IYSIZE-ysize)
189 	{
190 		while((run=*take++))
191 		{
192 			dx=*((signed short *)take);++take;
193 			dy=*((signed short *)take);++take;
194 			if(bitsperpixel==16)
195 			{
196 				p1=(unsigned short *)(videomem+stridemult[y+dy]+((x+dx)<<1));
197 				while(run--)
198 					*p1++=*take++;
199 			} else
200 			{
201 				pc=videomem+stridemult[y+dy]+x+dx;
202 				while(run--)
203 					*pc++=*take++;
204 			}
205 		}
206 	} else
207 	{
208 		while((run=*take++))
209 		{
210 			dx=*((signed short *)take);++take;
211 			dy=*((signed short *)take);++take;
212 			dx+=x;
213 			dy+=y;
214 			p2=take;
215 			take+=run;
216 			if(dy<0 || dy>=IYSIZE) continue;
217 			if(dx>=IXSIZE) continue;
218 			if(dx<0)
219 			{
220 				p2-=dx;
221 				run+=dx;
222 				dx=0;
223 			} else if(dx+run>IXSIZE)
224 				run=IXSIZE-dx;
225 			if(bitsperpixel==16)
226 			{
227 				p1=(unsigned short *)(videomem+stridemult[dy]+(dx<<1));
228 				while(run-->0)
229 					*p1++=*p2++;
230 			} else
231 			{
232 				pc=videomem+stridemult[dy]+dx;
233 				while(run-->0)
234 					*pc++=*p2++;
235 			}
236 		}
237 	}
238 }
239 
240 char havepulse=0;
241 
242 struct point
243 {
244 int x,y;
245 };
246 struct fpoint
247 {
248 float x,y;
249 };
250 
251 struct ball
252 {
253 	struct ball *next;
254 	int x,y;
255 	int dx,dy;
256 	char flags;
257 	unsigned char red,green,blue;
258 	int index;
259 } *balls,*firstball,*activeballs;
260 
261 
262 struct hose
263 {
264 	struct hose *next;
265 	int x,y;
266 	int angle;
267 	unsigned char red,green,blue;
268 	int index;
269 } *hoses,*firsthose,*activehoses,fakehose;
270 
271 struct block
272 {
273 	struct block *next;
274 	int x,y;
275 	int angle;
276 } *blocks,*firstblock,*activeblocks,fakeblock;
277 
278 
279 #define TAP1 250
280 #define TAP2 103
281 /*
282 #define TAP1 55
283 #define TAP2 31
284 */
285 
maprgb(int red,int green,int blue)286 int maprgb(int red,int green,int blue)
287 {
288 	if(bitsperpixel==16)
289 		return SDL_MapRGB(thescreen->format,red,green,blue);
290 	red&=0xe0;
291 	green&=0xe0;
292 	blue&=0xc0;
293 	return (red>>5) | (green>>2) | blue;
294 }
295 
296 unsigned char myrandblock[TAP1];
297 int myrandtake;
298 
makeball(int radius,uchar red,uchar green,uchar blue)299 unsigned short *makeball(int radius,uchar red,uchar green,uchar blue)
300 {
301 unsigned short *temp,*put;
302 int i,j,k,c;
303 unsigned char *p;
304 float lx,ly,lz,mag,x,y,z,y2,radius2,intensity,t;
305 unsigned char intens[4096];
306 
307 	radius=radius*IXSIZE/640;
308 	if(radius<2) radius=2;
309 	radius2=radius*radius;
310 	lx=-1.0;
311 	ly=-1.0;
312 	lz=1.5;
313 	mag=sqrt(lx*lx+ly*ly+lz*lz)*radius;
314 	lx/=mag;
315 	ly/=mag;
316 	lz/=mag;
317 
318 	put=temp=(unsigned short *)block64;
319 	*put++=-radius;
320 	*put++=-radius;
321 	*put++=radius+radius+1;
322 	*put++=radius+radius+1;
323 	memset(intens,0,sizeof(intens));
324 	for(j=0;j<radius+radius;++j)
325 	{
326 		y=j-radius+0.5;
327 		y2=y*y;
328 		p=intens+(j<<6);
329 		for(i=0;i<radius+radius;++i,++p)
330 		{
331 			x=i-radius+0.5;
332 			t=x*x+y2;
333 			if(t>radius2) continue;
334 			z=sqrt(radius2-t);
335 			intensity=(x*lx+y*ly+z*lz+1.0)/2.0;
336 			intensity*=intensity;
337 			*p=intensity*255;
338 		}
339 	}
340 	for(j=0;j<=radius+radius;++j)
341 	{
342 		p=intens+(j<<6);
343 		c=0;
344 		i=0;
345 		while(!*p && i<60)
346 		{
347 			++p;
348 			++i;
349 		}
350 		if(i>=60) continue;
351 		while(c<=radius+radius && p[c])
352 			++c;
353 		*put++=c;
354 		*put++=i;
355 		*put++=j;
356 		while(c--)
357 		{
358 			k=*p++;
359 			*put++=maprgb(red*k>>8,green*k>>8,blue*k>>8);
360 		}
361 	}
362 	*put++=0;
363 	i=(put-temp)<<1;
364 	put=malloc(i);
365 	if(put)
366 		memcpy(put,temp,i);
367 	return put;
368 }
369 
370 
myrand1()371 int myrand1()
372 {
373 int i;
374 int val;
375 
376 	i=myrandtake-TAP2;
377 	if(i<0) i+=TAP1;
378 	val=myrandblock[myrandtake++]^=myrandblock[i];
379 	if(myrandtake==TAP1) myrandtake=0;
380 	return val;
381 }
myrand()382 int myrand()
383 {
384 int v;
385 	v=myrand1();
386 	return (v<<8) | myrand1();
387 }
388 
initmyrand(void)389 void initmyrand(void)
390 {
391 int i,j;
392 unsigned char *p;
393 int msb,msk;
394 
395 	myrandtake=0;
396 	p=myrandblock;
397 	j=12345;
398 	i=TAP1;
399 	while(i--)
400 	{
401 		j=(j*1277)&0xffff;
402 		*p++=j>>8;
403 	}
404 	p=myrandblock+14;
405 	msk=0xff;
406 	msb=0x80;
407 	do
408 	{
409 		*p&=msk;
410 		*p|=msb;
411 		p+=11;
412 		msk>>=1;
413 		msb>>=1;
414 	} while(msk);
415 	i=500;
416 	while(i--) myrand();
417 
418 }
419 
420 
421 
longind(unsigned char * p)422 long longind(unsigned char *p)
423 {
424 	return (p[0]<<24L) | (p[1]<<16L) | (p[2]<<8) | p[3];
425 }
shortind(unsigned char * p)426 short shortind(unsigned char *p)
427 {
428 	return (p[0]<<8L) | p[1];
429 }
430 
closex(void)431 void closex(void)
432 {
433 	if(sdlloaded)
434 		SDL_Quit();
435 }
436 
nomem(char * str)437 void nomem(char *str)
438 {
439 	printf("No memory!!![%s]\n",str);
440 	closex();
441 	exit(1);
442 }
443 
scrlock(void)444 int scrlock(void)
445 {
446 	if(SDL_MUSTLOCK(thescreen))
447 	{
448 		if ( SDL_LockSurface(thescreen) < 0 )
449 		{
450 			fprintf(stderr, "Couldn't lock display surface: %s\n",
451 								SDL_GetError());
452 			return -1;
453 		}
454 	}
455 	return 0;
456 }
scrunlock(void)457 void scrunlock(void)
458 {
459 	if(SDL_MUSTLOCK(thescreen))
460 		SDL_UnlockSurface(thescreen);
461 	SDL_UpdateRect(thescreen, 0, 0, 0, 0);
462 }
463 
vsync(void)464 void vsync(void)
465 {
466 	scrunlock();
467 	scrlock();
468 }
469 
470 #define IBUFFLEN 1024
471 int ileft=0,ihand=0,byteswide;
472 unsigned char ibuff[IBUFFLEN],*itake;
473 
myci()474 int myci()
475 {
476 	if(!ileft)
477 	{
478 		ileft=read(ihand,ibuff,IBUFFLEN);
479 
480 		if(!ileft) return -1;
481 		itake=ibuff;
482 	}
483 	ileft--;
484 	return *itake++;
485 }
486 
487 
dopcxreal(char * name,gfxset * gs)488 int dopcxreal(char *name,gfxset *gs)
489 {
490 int xs,ys;
491 int i,j,k;
492 int totalsize;
493 int width,height;
494 unsigned char *bm,*lp;
495 char tname[256];
496 
497 
498 	memset(gs,0,sizeof(gfxset));
499 	ileft=0;
500 	sprintf(tname,"data/%s",name);
501 	ihand=open(tname,O_RDONLY);
502 	if(ihand<0)
503 	{
504 		char tname2[256];
505 		sprintf(tname2,"%s.pcx",tname);
506 		ihand=open(tname2,O_RDONLY);
507 		if(ihand<0)
508 			return 1;
509 	}
510 	if(myci()!=10) {close(ihand);return 2;} // 10=zsoft .pcx
511 	if(myci()!=5) {close(ihand);return 3;} // version 3.0
512 	if(myci()!=1) {close(ihand);return 4;} //encoding method
513 	if(myci()!=8) {close(ihand);return 5;} //bpp
514 	xs=myci();
515 	xs|=myci()<<8;
516 	ys=myci();
517 	ys|=myci()<<8;
518 	width=myci();
519 	width|=myci()<<8;
520 	height=myci();
521 	height|=myci()<<8;
522 	width=width+1-xs;
523 	height=height+1-ys;
524 	for(i=0;i<48+4;++i) myci();
525 	myci();
526 	if(myci()!=1) {close(ihand);return 6;} // # of planes
527 	byteswide=myci();
528 	byteswide|=myci()<<8;
529 	i=myci();
530 	i|=myci()<<8;
531 //	if(i!=1) {close(ihand);return 7;} // 1=color/bw,2=grey
532 	for(i=0;i<58;++i) myci();
533 	totalsize=height*byteswide;
534 	bm=malloc(totalsize+1);
535 	if(!bm) {close(ihand);return 8;} // no memory
536 	gs->gs_pic=bm;
537 	gs->gs_xsize=width;
538 	gs->gs_ysize=height;
539 	while(height--)
540 	{
541 		lp=bm;
542 		i=byteswide;
543 		while(i>0)
544 		{
545 			j=myci();
546 			if(j<0xc0)
547 			{
548 				*lp++=j;
549 				--i;
550 			} else
551 			{
552 				j&=0x3f;
553 				k=myci();
554 				while(j-- && i)
555 				{
556 					*lp++=k;
557 					--i;
558 				}
559 			}
560 		}
561 		bm+=width;
562 	}
563 	lseek(ihand,-0x300,SEEK_END);
564 	int t;
565 	t=read(ihand,gs->gs_colormap,0x300);
566 	t=t;
567 	close(ihand);
568 	return 0;
569 
570 }
571 
dopcx(char * name,gfxset * gs)572 int dopcx(char *name,gfxset *gs)
573 {
574 int err;
575 	err=dopcxreal(name,gs);
576 	if(err)
577 		printf("Error loading \"%s\":code %d\n",name,err);
578 	return err;
579 }
580 
581 #define SGN(x) ((x)==0 ? 0 : ((x)<0 ? -1 : 1))
582 
allocentry()583 void *allocentry()
584 {
585 list *entry;
586 	if(!(entry=((list *)things)->next)) return 0;
587 	((list *)things)->next=entry->next;
588 	memset(entry,0,thingsize);
589 	return entry;
590 }
freeentry(void * entry)591 void freeentry(void *entry)
592 {
593 	((list *)entry)->next=((list *)things)->next;
594 	((list *)things)->next=entry;
595 }
addtail(void * header,void * entry)596 void addtail(void *header,void *entry)
597 {
598 	while(((list *)header)->next) header=((list *)header)->next;
599 	((list *)header)->next=entry;
600 	((list *)entry)->next=0;
601 }
delink(void * header,void * entry)602 void delink(void *header,void *entry)
603 {
604 	while(((list *)header)->next != entry) header=((list *)header)->next;
605 	((list *)header)->next=((list *)entry)->next;
606 	((list *)entry)->next=0;
607 	freeentry(entry);
608 }
initlist(void * first,int size,int num)609 void initlist(void *first,int size,int num)
610 {
611 unsigned char *p;
612 int i;
613 
614 	memset(first,0,size*num);
615 	for(i=0;i<num-1;++i)
616 	{
617 		p=first;
618 		p+=size;
619 		((list *)first)->next=(void *)p;
620 		first=p;
621 	}
622 	((list *)first)->next=0;
623 }
624 
initheader(void * p)625 void initheader(void *p)
626 {
627 	memset(p,0,sizeof(list));
628 }
629 
630 char interrupted;
631 
sdlhandler(Uint32 time)632 Uint32 sdlhandler(Uint32 time)
633 {
634 	interrupted=1;
635 	hc++;
636 	return time;
637 }
pulseon()638 void pulseon()
639 {
640 	if(havepulse) return;
641 	havepulse=1;
642 	SDL_SetTimer(10,sdlhandler);
643 	hc=interrupted=0;
644 }
pulseoff()645 void pulseoff()
646 {
647 	if(!havepulse) return;
648 	havepulse=0;
649 	SDL_SetTimer(0,0);
650 
651 }
652 
initballs(void)653 void initballs(void)
654 {
655 int i;
656 	balls=malloc(MAXBALLS*sizeof(struct ball));
657 	if(!balls) nomem("initballs");
658 	for(i=0;i<MAXBALLS-1;++i)
659 		balls[i].next=balls+i+1;
660 	balls[i].next=0;
661 	firstball=balls;
662 	activeballs=0;
663 }
inithoses(void)664 void inithoses(void)
665 {
666 int i;
667 	hoses=malloc(MAXHOSES*sizeof(struct hose));
668 	if(!hoses) nomem("inithoses");
669 	for(i=0;i<MAXHOSES-1;++i)
670 		hoses[i].next=hoses+i+1;
671 	hoses[i].next=0;
672 	firsthose=hoses;
673 	activehoses=0;
674 	fakehose.x=VIRTX<<(FRACTION-4);
675 	fakehose.y=VIRTY<<(FRACTION-4);
676 	fakehose.angle=384;
677 	fakehose.red=fakehose.green=fakehose.blue=255;
678 	fakehose.index=511;
679 }
initblocks(void)680 void initblocks(void)
681 {
682 int i;
683 	blocks=malloc(MAXBLOCKS*sizeof(struct block));
684 	if(!blocks) nomem("initblocks");
685 	for(i=0;i<MAXBLOCKS-1;++i)
686 		blocks[i].next=blocks+i+1;
687 	blocks[i].next=0;
688 	firstblock=blocks;
689 	activeblocks=0;
690 	fakeblock.x=4*VIRTX<<(FRACTION-4);
691 	fakeblock.y=VIRTY<<(FRACTION-4);
692 	fakeblock.angle=0;
693 }
scanfunc(int x1,int y,int x2,long color)694 void scanfunc(int x1,int y,int x2,long color)
695 {
696 unsigned short *p1;
697 unsigned char *p;
698 int t;
699 
700 	if(x1>x2)
701 	{
702 		t=x1;
703 		x1=x2;
704 		x2=t;
705 	}
706 	if(y<0 || y>=IYSIZE || x1>=IXSIZE || x2<0) return;
707 	if(x1<0) x1=0;
708 	if(x2>=IXSIZE) x2=IXSIZE-1;
709 	x2-=x1;
710 	if(bitsperpixel==16)
711 	{
712 		p1=(unsigned short *)(videomem+stride*y+(x1<<1));
713 		while(x2-->0)
714 			*p1++=color;
715 	} else
716 	{
717 		p=videomem+stride*y+x1;
718 		while(x2-->0)
719 			*p++=color;
720 	}
721 }
722 
allocball()723 struct ball *allocball()
724 {
725 struct ball *aball;
726 	if(!firstball) return 0;
727 	aball=firstball;
728 	firstball=firstball->next;
729 	memset(aball,0,sizeof(struct ball));
730 	return aball;
731 }
freeball(struct ball * aball)732 void freeball(struct ball *aball)
733 {
734 	aball->next=firstball;
735 	firstball=aball;
736 }
allochose()737 struct hose *allochose()
738 {
739 struct hose *ahose;
740 	if(!firsthose) return 0;
741 	ahose=firsthose;
742 	firsthose=firsthose->next;
743 	memset(ahose,0,sizeof(struct hose));
744 	return ahose;
745 }
freehose(struct hose * ahose)746 void freehose(struct hose *ahose)
747 {
748 	ahose->next=firsthose;
749 	firsthose=ahose;
750 }
allocblock()751 struct block *allocblock()
752 {
753 struct block *ablock;
754 	if(!firstblock) return 0;
755 	ablock=firstblock;
756 	firstblock=firstblock->next;
757 	memset(ablock,0,sizeof(struct block));
758 	return ablock;
759 }
freeblock(struct block * ablock)760 void freeblock(struct block *ablock)
761 {
762 	ablock->next=firstblock;
763 	firstblock=ablock;
764 }
765 
766 #define VEL 2
767 #define HOSESIZE 30
768 #define BLOCKSIZE 12
769 
dohoses(void)770 void dohoses(void)
771 {
772 struct hose *ahose;
773 struct ball *aball;
774 float angle;
775 int dx,dy;
776 int side;
777 
778 	ahose=activehoses;
779 	while(ahose)
780 	{
781 		aball=allocball();
782 		if(aball)
783 		{
784 			angle=(ahose->angle+spinangle)*PI/512;
785 			dx=-(1<<FRACTION)*cos(angle);
786 			dy=-(1<<FRACTION)*sin(angle);
787 			aball->x=ahose->x+dx*HOSESIZE;
788 			aball->y=ahose->y+dy*HOSESIZE;
789 			side=((rand()&255)-127)*HOSESIZE/3;
790 			dx=dx*side>>7;
791 			dy=dy*side>>7;
792 			aball->x-=dy;
793 			aball->y+=dx;
794 
795 			aball->dx=-(VEL<<FRACTION)*cos(angle);
796 			aball->dy=-(VEL<<FRACTION)*sin(angle);
797 			aball->red=ahose->red;
798 			aball->green=ahose->green;
799 			aball->blue=ahose->blue;
800 			aball->index=ahose->index;
801 			aball->next=activeballs;
802 			activeballs=aball;
803 		}
804 		ahose=ahose->next;
805 	}
806 }
807 
hosecontrol1(struct point * p,struct hose * ahose)808 void hosecontrol1(struct point *p,struct hose *ahose)
809 {
810 	p->x=ahose->x>>FRACTION;
811 	p->y=ahose->y>>FRACTION;
812 }
hosecontrol2(struct point * p,struct hose * ahose)813 void hosecontrol2(struct point *p,struct hose *ahose)
814 {
815 float a;
816 int x,y;
817 
818 	a=(ahose->angle+spinangle)*PI/512;
819 	x=ahose->x>>FRACTION;
820 	y=ahose->y>>FRACTION;
821 	p->x=x-HOSESIZE*3/4*cos(a);
822 	p->y=y-HOSESIZE*3/4*sin(a);
823 }
near(int v1,int v2)824 int near(int v1,int v2)
825 {
826 	v1-=v2;
827 	if(v1<0) v1=-v1;
828 	return v1<8;
829 }
nearrad(int dx,int dy,int rad)830 int nearrad(int dx,int dy,int rad)
831 {
832 	return dx*dx+dy*dy<rad*rad;
833 }
makeindex(int red,int green,int blue)834 int makeindex(int red,int green,int blue)
835 {
836 	return ((red&0xe0)<<1) | ((green&0xe0)>>2) | ((blue&0xe0)>>5);
837 }
838 
addhose(int red,int green,int blue)839 struct hose *addhose(int red,int green,int blue)
840 {
841 struct hose *ahose;
842 	ahose=allochose();
843 	if(!ahose) return 0;
844 	ahose->next=activehoses;
845 	activehoses=ahose;
846 	ahose->angle=384;
847 	ahose->x=VIRTX<<(FRACTION-1);
848 	ahose->y=VIRTY<<(FRACTION-1);
849 	ahose->red=red;
850 	ahose->green=green;
851 	ahose->blue=blue;
852 	ahose->index=makeindex(red,green,blue);
853 	return ahose;
854 }
addblock()855 struct block *addblock()
856 {
857 struct block *ablock;
858 	ablock=allocblock();
859 	ablock->next=activeblocks;
860 	activeblocks=ablock;
861 	ablock->angle=0;
862 	ablock->x=VIRTX<<(FRACTION-1);
863 	ablock->y=VIRTY<<(FRACTION-1);
864 	return ablock;
865 }
866 
867 
checkhose(struct hose * ahose)868 int checkhose(struct hose *ahose)
869 {
870 struct point p;
871 	hosecontrol1(&p,ahose);
872 	if(near(p.x,mousex) && near(p.y,mousey))
873 		return 1;
874 	hosecontrol2(&p,ahose);
875 	if(near(p.x,mousex) && near(p.y,mousey))
876 		return 2;
877 	return 0;
878 }
879 struct point colorpoints[NUMTYPES];
880 int colorindexes[NUMTYPES];
881 unsigned short *colorfigs[NUMTYPES];
initcolors(void)882 void initcolors(void)
883 {
884 int i,r,g,b;
885 	for(i=0;i<NUMTYPES;++i)
886 	{
887 		colorpoints[i].y=15*VIRTY/16;
888 		colorpoints[i].x=(i+1)*VIRTX/25;
889 		r=redvals[i];
890 		g=greenvals[i];
891 		b=bluevals[i];
892 		colorindexes[i]=makeindex(r,g,b);
893 		colorfigs[i]=makeball(12,r,g,b);
894 	}
895 }
896 
897 
hosehit(void)898 void hosehit(void)
899 {
900 static struct hose *ahose;
901 static int controltype;
902 float x,y,ax,ay,d,angle;
903 int i;
904 
905 	if(buttonstate==NOTDOWN) return;
906 
907 	if(buttonstate==JUSTDOWN)
908 	{
909 		ahose=activehoses;
910 		controltype=0;
911 		while(ahose)
912 		{
913 			if((controltype=checkhose(ahose)))
914 				break;
915 			ahose=ahose->next;
916 		}
917 		if(!ahose && (controltype=checkhose(&fakehose)))
918 		{
919 			if(controltype==1)
920 				ahose=addhose(255,255,255);
921 			else
922 				controltype=0;
923 		}
924 	}
925 	if(controltype)
926 	{
927 		if(!ahose) controltype=0;
928 		switch(controltype)
929 		{
930 		case 1:
931 			ahose->x=mousex<<FRACTION;
932 			ahose->y=mousey<<FRACTION;
933 			for(i=0;i<NUMTYPES;++i)
934 			{
935 				if(nearrad(mousex-colorpoints[i].x,mousey-colorpoints[i].y,12))
936 				{
937 					ahose->red=redvals[i];
938 					ahose->green=greenvals[i];
939 					ahose->blue=bluevals[i];
940 
941 					ahose->index=colorindexes[i];
942 					break;
943 				}
944 			}
945 			break;
946 		case 2:
947 			x=(ahose->x>>FRACTION)-mousex;
948 			y=(ahose->y>>FRACTION)-mousey;
949 			if(!x && !y) break;
950 			d=sqrt(x*x+y*y);
951 			x/=d;
952 			y/=d;
953 			ax=x<0 ? -x : x;
954 			ay=y<0 ? -y : y;
955 			if(ax>ay)
956 			{
957 				angle=acos(x);
958 				if(y<0) angle=-angle;
959 			} else
960 			{
961 				angle=asin(y);
962 				if(x<0) angle=PI-angle;
963 			}
964 			angle*=512/PI;
965 			ahose->angle=angle;
966 			break;
967 		}
968 	}
969 }
blockhit(void)970 void blockhit(void)
971 {
972 static struct block *ablock;
973 static int controltype;
974 float x,y,ax,ay,d,angle;
975 int i;
976 
977 	if(buttonstate==NOTDOWN) return;
978 
979 	if(buttonstate==JUSTDOWN)
980 	{
981 		ablock=activeblocks;
982 		controltype=0;
983 		while(ablock)
984 		{
985 			if((controltype=checkblock(ablock)))
986 				break;
987 			ablock=ablock->next;
988 		}
989 		if(!ablock && (controltype=checkblock(&fakeblock)))
990 		{
991 			if(controltype==1)
992 				ablock=addblock();
993 			else
994 				controltype=0;
995 		}
996 	}
997 	if(controltype)
998 	{
999 		if(!ablock) controltype=0;
1000 		switch(controltype)
1001 		{
1002 		case 1:
1003 			ablock->x=mousex<<FRACTION;
1004 			ablock->y=mousey<<FRACTION;
1005 			for(i=0;i<NUMTYPES;++i)
1006 			{
1007 				if(near(mousex,colorpoints[i].x) &&
1008 					near(mousey,colorpoints[i].y))
1009 				{
1010 				}
1011 			}
1012 			makebbm();
1013 			break;
1014 		case 2:
1015 			x=mousex-(ablock->x>>FRACTION);
1016 			y=mousey-(ablock->y>>FRACTION);
1017 			if(!x && !y) break;
1018 			d=sqrt(x*x+y*y);
1019 			x/=d;
1020 			y/=d;
1021 			ax=x<0 ? -x : x;
1022 			ay=y<0 ? -y : y;
1023 			if(ax>ay)
1024 			{
1025 				angle=acos(x);
1026 				if(y<0) angle=-angle;
1027 			} else
1028 			{
1029 				angle=asin(y);
1030 				if(x<0) angle=PI-angle;
1031 			}
1032 			angle*=512/PI;
1033 			ablock->angle=angle;
1034 			makebbm();
1035 			break;
1036 		}
1037 	}
1038 }
1039 
1040 #define HOSERAD ((float)HOSESIZE*IXSIZE/VIRTX)
1041 
plothose(struct hose * ahose)1042 void plothose(struct hose *ahose)
1043 {
1044 int x1,y1,x2,y2,x3,y3,x,y;
1045 float a;
1046 struct point p;
1047 int angle;
1048 	angle=ahose->angle+spinangle;
1049 	x=(float)ahose->x*IXSIZE/VIRTX;
1050 	y=(float)ahose->y*IYSIZE/VIRTY;
1051 	x>>=FRACTION;
1052 	y>>=FRACTION;
1053 	a=angle*PI/512;
1054 	x1=x+HOSERAD*cos(a);
1055 	y1=y+HOSERAD*sin(a);
1056 	a+=150*PI/180;
1057 	x2=x+HOSERAD*cos(a);
1058 	y2=y+HOSERAD*sin(a);
1059 	a+=60*PI/180;
1060 	x3=x+HOSERAD*cos(a);
1061 	y3=y+HOSERAD*sin(a);
1062 	tri(x1,y1,x2,y2,x3,y3,scanfunc,maprgb(ahose->red,ahose->green,ahose->blue));
1063 	drawfigure(x,y,dummyball);
1064 	hosecontrol2(&p,ahose);
1065 	drawfigure(p.x*IXSIZE/VIRTX,p.y*IYSIZE/VIRTY,dummyball);
1066 }
1067 
plothoses(void)1068 void plothoses(void)
1069 {
1070 struct hose *ahose;
1071 
1072 	ahose=activehoses;
1073 	while(ahose)
1074 	{
1075 		plothose(ahose);
1076 		ahose=ahose->next;
1077 	}
1078 	plothose(&fakehose);
1079 }
1080 #define BLOCKRAD ((float)BLOCKSIZE*IXSIZE/VIRTX)
1081 
blockcontrol1(struct point * p,struct block * ablock)1082 void blockcontrol1(struct point *p,struct block *ablock)
1083 {
1084 	p->x=ablock->x>>FRACTION;
1085 	p->y=ablock->y>>FRACTION;
1086 }
blockcontrol2(struct point * p,struct block * ablock)1087 void blockcontrol2(struct point *p,struct block *ablock)
1088 {
1089 float a;
1090 int x,y;
1091 
1092 	a=ablock->angle*PI/512;
1093 	x=ablock->x>>FRACTION;
1094 	y=ablock->y>>FRACTION;
1095 	p->x=x+BLOCKSIZE*3*cos(a);
1096 	p->y=y+BLOCKSIZE*3*sin(a);
1097 }
checkblock(struct block * ablock)1098 int checkblock(struct block *ablock)
1099 {
1100 struct point p;
1101 	blockcontrol1(&p,ablock);
1102 	if(near(p.x,mousex) && near(p.y,mousey))
1103 		return 1;
1104 	blockcontrol2(&p,ablock);
1105 	if(near(p.x,mousex) && near(p.y,mousey))
1106 		return 2;
1107 	return 0;
1108 }
blockpoint1(struct fpoint * fp,struct block * ablock)1109 void blockpoint1(struct fpoint *fp,struct block *ablock)
1110 {
1111 float a;
1112 	a=ablock->angle*PI/512;
1113 	fp->x=BLOCKSIZE*cos(a);
1114 	fp->y=BLOCKSIZE*sin(a);
1115 }
blockpoint2(struct point * p,struct block * ablock)1116 void blockpoint2(struct point *p,struct block *ablock)
1117 {
1118 float a;
1119 	a=(ablock->angle-40)*PI/512;
1120 	p->x=BLOCKRAD*cos(a);
1121 	p->y=BLOCKRAD*sin(a);
1122 }
1123 #define BLOCKFACTOR 4
plotblock(struct block * ablock)1124 void plotblock(struct block *ablock)
1125 {
1126 int x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6,x,y;
1127 struct point p;
1128 float dx,dy;
1129 struct fpoint fp;
1130 
1131 
1132 	x=(float)ablock->x*IXSIZE/VIRTX;
1133 	y=(float)ablock->y*IYSIZE/VIRTY;
1134 	x>>=FRACTION;
1135 	y>>=FRACTION;
1136 	blockpoint1(&fp,ablock);
1137 	dx=fp.x*IXSIZE/VIRTX;
1138 	dy=fp.y*IYSIZE/VIRTY;
1139 
1140 	x1=x+BLOCKFACTOR*dx+.5;
1141 	y1=y+BLOCKFACTOR*dy+.5;
1142 	x2=x-BLOCKFACTOR*dx+.5;
1143 	y2=y-BLOCKFACTOR*dy+.5;
1144 	x3=x1+dx-dy+.5;
1145 	y3=y1+dy+dx+.5;
1146 	x4=x1+dx+dy+.5;
1147 	y4=y1+dy-dx+.5;
1148 	x5=x2-dx-dy+.5;
1149 	y5=y2-dy+dx+.5;
1150 	x6=x2-dx+dy+.5;
1151 	y6=y2-dy-dx+.5;
1152 
1153 	tri(x1,y1,x3,y3,x4,y4,scanfunc,maprgb(96,96,96));
1154 	tri(x2,y2,x5,y5,x6,y6,scanfunc,maprgb(96,96,96));
1155 
1156 	tri(x1,y1,x2,y2,x6,y6,scanfunc,maprgb(96,96,96));
1157 	tri(x1,y1,x4,y4,x6,y6,scanfunc,maprgb(96,96,96));
1158 
1159 	tri(x1,y1,x2,y2,x5,y5,scanfunc,maprgb(96,96,96));
1160 	tri(x1,y1,x3,y3,x5,y5,scanfunc,maprgb(96,96,96));
1161 
1162 	drawfigure(x,y,dummyball);
1163 	blockcontrol2(&p,ablock);
1164 	drawfigure(p.x*IXSIZE/VIRTX,p.y*IYSIZE/VIRTY,dummyball);
1165 }
clearbbm(void)1166 void clearbbm(void)
1167 {
1168 	memset(bbm,0,VIRTX*VIRTY);
1169 }
initbbm(void)1170 void initbbm(void)
1171 {
1172 	bbm=malloc(VIRTX*VIRTY);
1173 	if(!bbm)
1174 		nomem("initbitmap");
1175 	clearbbm();
1176 }
bbmscan(int x1,int y,int x2,long color)1177 void bbmscan(int x1,int y,int x2,long color)
1178 {
1179 unsigned char *p1;
1180 int t;
1181 
1182 	if(x1>x2)
1183 	{
1184 		t=x1;
1185 		x1=x2;
1186 		x2=t;
1187 	}
1188 	if(y<0 || y>=VIRTY || x1>=VIRTX || x2<0) return;
1189 	if(x1<0) x1=0;
1190 	if(x2>=VIRTX) x2=VIRTX-1;
1191 	p1=bbm+VIRTX*y+x1;
1192 	if(x2-x1)
1193 		memset(p1,color,x2-x1);
1194 }
1195 
1196 float blockangles[256];
1197 
makebbm(void)1198 void makebbm(void)
1199 {
1200 struct block *ablock;
1201 int x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6,x,y;
1202 float dx,dy;
1203 struct fpoint fp;
1204 int id;
1205 
1206 	ablock=activeblocks;
1207 	clearbbm();
1208 	id=1;
1209 	while(ablock)
1210 	{
1211 		x=ablock->x>>FRACTION;
1212 		y=ablock->y>>FRACTION;
1213 
1214 
1215 		x=(float)ablock->x;
1216 		y=(float)ablock->y;
1217 		x>>=FRACTION;
1218 		y>>=FRACTION;
1219 		blockpoint1(&fp,ablock);
1220 		dx=fp.x;
1221 		dy=fp.y;
1222 
1223 		x1=x+BLOCKFACTOR*dx+.5;
1224 		y1=y+BLOCKFACTOR*dy+.5;
1225 		x2=x-BLOCKFACTOR*dx+.5;
1226 		y2=y-BLOCKFACTOR*dy+.5;
1227 		x3=x1+dx-dy+.5;
1228 		y3=y1+dy+dx+.5;
1229 		x4=x1+dx+dy+.5;
1230 		y4=y1+dy-dx+.5;
1231 		x5=x2-dx-dy+.5;
1232 		y5=y2-dy+dx+.5;
1233 		x6=x2-dx+dy+.5;
1234 		y6=y2-dy-dx+.5;
1235 
1236 		tri(x1,y1,x3,y3,x4,y4,bbmscan,id);
1237 		blockangles[id]=ablock->angle&1023;
1238 		++id;
1239 		tri(x2,y2,x5,y5,x6,y6,bbmscan,id);
1240 		blockangles[id]=(ablock->angle-512)&1023;
1241 		++id;
1242 		tri(x1,y1,x2,y2,x6,y6,bbmscan,id);
1243 		tri(x1,y1,x4,y4,x6,y6,bbmscan,id);
1244 		blockangles[id]=(ablock->angle-256)&1023;
1245 		++id;
1246 		tri(x1,y1,x2,y2,x5,y5,bbmscan,id);
1247 		tri(x1,y1,x3,y3,x5,y5,bbmscan,id);
1248 		blockangles[id]=(ablock->angle+256)&1023;
1249 		++id;
1250 		ablock=ablock->next;
1251 	}
1252 }
1253 #define ELAST 1.7
1254 
bbmball(struct ball * aball)1255 void bbmball(struct ball *aball)
1256 {
1257 int x,y;
1258 int id;
1259 float dx,dy,v,s,c,a;
1260 
1261 	aball->x+=aball->dx;
1262 	aball->y+=aball->dy;
1263 	x=aball->x>>FRACTION;
1264 	y=aball->y>>FRACTION;
1265 
1266 	if(x<0 || x>=VIRTX || y<0 || y>=VIRTY) return;
1267 	if(!(id=bbm[y*VIRTX+x])) return;
1268 	a=blockangles[id]*PI/512;
1269 	s=sin(a);
1270 	c=cos(a);
1271 	dx=aball->dx;
1272 	dy=aball->dy;
1273 	v=dx*c+dy*s;
1274 	if(v<0)
1275 	{
1276 		dx=c*v;
1277 		dy=s*v;
1278 		aball->dx-=dx*ELAST;
1279 		aball->dy-=dy*ELAST;
1280 	}
1281 
1282 }
1283 
1284 
1285 
plotblocks(void)1286 void plotblocks(void)
1287 {
1288 struct block *ablock;
1289 
1290 	ablock=activeblocks;
1291 	while(ablock)
1292 	{
1293 		plotblock(ablock);
1294 		ablock=ablock->next;
1295 	}
1296 	plotblock(&fakeblock);
1297 }
1298 
drawcolors(void)1299 void drawcolors(void)
1300 {
1301 int x,y;
1302 int dx,dy;
1303 int i;
1304 
1305 	dx=6*IXSIZE/VIRTX;
1306 	dy=6*IYSIZE/VIRTY;
1307 
1308 	for(i=0;i<NUMTYPES;++i)
1309 	{
1310 		x=colorpoints[i].x*IXSIZE/VIRTX;
1311 		y=colorpoints[i].y*IYSIZE/VIRTY;
1312 		drawfigure(x-dx,y-dy,colorfigs[i]);
1313 	}
1314 }
1315 
1316 char disk[]={
1317 -1,-4,3,
1318 -3,-3,7,
1319 -3,-2,7,
1320 -4,-1,9,
1321 -4, 0,9,
1322 -4, 1,9,
1323 -3, 2,7,
1324 -3, 3,7,
1325 -1, 4,3,
1326 128
1327 };
1328 
drawsolid(int x,int y,char * p,uchar red,uchar green,uchar blue)1329 void drawsolid(int x,int y,char *p,uchar red,uchar green,uchar blue)
1330 {
1331 int tx,ty,tl;
1332 unsigned short *put,color;
1333 unsigned char *pc;
1334 
1335 	color=maprgb(red,green,blue);
1336 	while(*p!=-128)
1337 	{
1338 		tx=x+*p++;
1339 		ty=y+*p++;
1340 		tl=*p++;
1341 		if(ty<0 || ty>=IYSIZE) continue;
1342 		if(tx+tl<0 || tx>=IXSIZE) continue;
1343 		if(tx+tl>IXSIZE) tl=IXSIZE-tx;
1344 		if(tx<0)
1345 		{
1346 			tl+=tx;
1347 			tx=0;
1348 		}
1349 		if(bitsperpixel==16)
1350 		{
1351 			put=(unsigned short *)(videomem+ty*stride+(tx<<1));
1352 			while(tl-->0)
1353 				*put++=color;
1354 		} else
1355 		{
1356 			pc=videomem+ty*stride+tx;
1357 			while(tl-->0)
1358 				*pc++=color;
1359 		}
1360 	}
1361 }
1362 
plotballs(void)1363 void plotballs(void)
1364 {
1365 struct ball *aball;
1366 int x,y;
1367 int i,j;
1368 int tx,ty;
1369 int index;
1370 int red,green,blue;
1371 float bright;
1372 
1373 	memset(vals,0,sizeof(vals));
1374 	aball=activeballs;
1375 	while(aball)
1376 	{
1377 		x=aball->x>>FRACTION;
1378 		y=aball->y>>FRACTION;
1379 		tx=x>>MIXFRAC;
1380 		ty=y>>MIXFRAC;
1381 		x=(float)x*IXSIZE/VIRTX;
1382 		y=(float)y*IYSIZE/VIRTY;
1383 		if(mixing)
1384 		{
1385 			if(tx>=0 && tx<(VIRTX>>MIXFRAC) && ty>=0 && ty<(VIRTY>>MIXFRAC))
1386 			{
1387 				index=ty*(VIRTX>>MIXFRAC)+tx;
1388 				++vals[0][index];
1389 				vals[1][index]+=aball->red;
1390 				vals[2][index]+=aball->green;
1391 				vals[3][index]+=aball->blue;
1392 			}
1393 			drawfigure(x,y,ballarray[makeindex(aball->red,aball->green,aball->blue)]);
1394 //			drawsolid(x,y,disk,aball->red,aball->green,aball->blue);
1395 		} else
1396 			drawfigure(x,y,ballarray[aball->index]);
1397 		aball=aball->next;
1398 	}
1399 
1400 	if(mixing)
1401 	{
1402 		for(i=0;i<(VIRTX>>MIXFRAC)*(VIRTY>>MIXFRAC);++i)
1403 		{
1404 			if((j=vals[0][i]))
1405 			{
1406 				red=vals[1][i]/j;
1407 				green=vals[2][i]/j;
1408 				blue=vals[3][i]/j;
1409 				bright=red>green ? red : green;
1410 				bright=bright>blue ? bright : blue;
1411 				if(bright)
1412 				{
1413 					bright=255/bright;
1414 					vals[1][i]=red*bright;
1415 					vals[2][i]=green*bright;
1416 					vals[3][i]=blue*bright;
1417 				}
1418 			}
1419 		}
1420 		aball=activeballs;
1421 		while(aball)
1422 		{
1423 			x=aball->x>>FRACTION;
1424 			y=aball->y>>FRACTION;
1425 			tx=x>>MIXFRAC;
1426 			ty=y>>MIXFRAC;
1427 			if(tx>=0 && tx<(VIRTX>>MIXFRAC) && ty>=0 && ty<(VIRTY>>MIXFRAC))
1428 			{
1429 				index=ty*(VIRTX>>MIXFRAC)+tx;
1430 				aball->red=vals[1][index];
1431 				aball->green=vals[2][index];
1432 				aball->blue=vals[3][index];
1433 			}
1434 			aball=aball->next;
1435 		}
1436 	}
1437 }
1438 
moveballs(void)1439 void moveballs(void)
1440 {
1441 struct ball *aball;
1442 
1443 	aball=activeballs;
1444 	while(aball)
1445 	{
1446 		bbmball(aball);
1447 
1448 		aball->dy+=gravity;
1449 
1450 		aball=aball->next;
1451 	}
1452 }
1453 
cullballs(void)1454 void cullballs(void)
1455 {
1456 struct ball *aball, **aballptr;
1457 	aballptr=&activeballs;
1458 	while(*aballptr)
1459 	{
1460 		aball=*aballptr;
1461 		if(aball->y>=VIRTY<<FRACTION)
1462 		{
1463 			*aballptr=aball->next;
1464 			freeball(aball);
1465 			continue;
1466 		}
1467 		aballptr=&aball->next;
1468 	}
1469 }
1470 
1471 
tritest(void)1472 void tritest(void)
1473 {
1474 float angle1,angle2,angle3;
1475 int i;
1476 int x1,y1,x2,y2,x3,y3;
1477 
1478 #define CX (IXSIZE/2)
1479 #define CY (IYSIZE/2)
1480 #define R 192
1481 	for(i=0;i<256;++i)
1482 	{
1483 		scrlock();
1484 		angle1=i*PI/180;
1485 		angle2=(i+120)*PI/180;
1486 		angle3=(i-120)*PI/180;
1487 		x1=CX+cos(angle1)*R;
1488 		y1=CY+sin(angle1)*R;
1489 		x2=CX+cos(angle2)*R;
1490 		y2=CY+sin(angle2)*R;
1491 		x3=CX+cos(angle3)*R;
1492 		y3=CY+sin(angle3)*R;
1493 		clear();
1494 		tri(x1,y1,x2,y2,x3,y3,scanfunc,maprgb(0,0,0));
1495 		scrunlock();
1496 	}
1497 
1498 }
1499 
onetri(void)1500 void onetri(void)
1501 {
1502 float angle1,angle2,angle3;
1503 static int i;
1504 int x1,y1,x2,y2,x3,y3;
1505 
1506 	i+=1;
1507 	angle1=i*PI/180;
1508 	angle2=(i+120)*PI/180;
1509 	angle3=(i-120)*PI/180;
1510 	x1=CX+cos(angle1)*R;
1511 	y1=CY+sin(angle1)*R;
1512 	x2=CX+cos(angle2)*R;
1513 	y2=CY+sin(angle2)*R;
1514 	x3=CX+cos(angle3)*R;
1515 	y3=CY+sin(angle3)*R;
1516 	tri(CX,CY,x2,y2,x3,y3,scanfunc,maprgb(96,96,96));
1517 	tri(x1,y1,CX,CY,x3,y3,scanfunc,maprgb(96,96,96));
1518 /*
1519 	x1=CX+cos(angle1)*R*2;
1520 	y1=CY+sin(angle1)*R*2;
1521 	x2=CX+cos(angle2)*R*2;
1522 	y2=CY+sin(angle2)*R*2;
1523 */
1524 	tri(x1,y1,x2,y2,CX,CY,scanfunc,maprgb(96,96,96));
1525 
1526 }
1527 
minitri(int x,int y,int a)1528 void minitri(int x,int y,int a)
1529 {
1530 int x1,y1,x2,y2,x3,y3;
1531 int r;
1532 float da,angle;
1533 	r=9;
1534 	da=PI*3/4;
1535 	angle=a*PI/180;
1536 	angle+=PI/2;
1537 	x1=x+r*sin(angle);
1538 	y1=y+r*cos(angle);
1539 	x2=x+r*sin(angle-da);
1540 	y2=y+r*cos(angle-da);
1541 	x3=x+r*sin(angle+da);
1542 	y3=y+r*cos(angle+da);
1543 	tri(x1,y1,x2,y2,x,y,scanfunc,0);
1544 	tri(x1,y1,x3,y3,x,y,scanfunc,0);
1545 }
1546 
1547 
dots(void)1548 void dots(void)
1549 {
1550 float r,f;
1551 int x,y;
1552 int i,j,num,space;
1553 int *points;
1554 int *p1;
1555 int t;
1556 int *angles,*a2;
1557 int indexes[256];
1558 static int endmark=0;
1559 
1560 	for(i=0;i<256;++i)
1561 		indexes[i]=makeindex(rand()&255,rand()&255,rand()&255);
1562 
1563 
1564 	p1=points=malloc(1000000*sizeof(int));
1565 	if(!points) nomem("dots");
1566 	angles=a2=p1+500000;
1567 
1568 	num=0;
1569 	f=1.3;
1570 	r=5;
1571 	while(r<460)
1572 	{
1573 		x=r*sin(r/f)+IXSIZE/2;
1574 		y=r*cos(r/f)+IYSIZE/2;
1575 		*p1++=x;
1576 		*p1++=y;
1577 		*a2++=r/f*180/PI;
1578 		++num;
1579 		r=r+3/r;
1580 	}
1581 	i=0;
1582 	space=4;
1583 	while(!exitflag)
1584 	{
1585 		scaninput();
1586 		scrlock();
1587 		clear();
1588 		j=endmark-space;
1589 		t=0;
1590 		while(j>=0)
1591 		{
1592 			y=j+j;
1593 			x=points[y++];
1594 			y=points[y];
1595 			drawfigure(x,y,ballarray[indexes[t&255]]);
1596 			++t;
1597 			j-=space;
1598 		}
1599 		j=endmark<<1;
1600 		minitri(points[j],points[j+1],angles[endmark]);
1601 		++endmark;
1602 		if(endmark>=num) endmark=num-space*7;
1603 		scrunlock();
1604 		++frames;
1605 	}
1606 	exitflag=0;
1607 	dospiral=0;
1608 	free(points);
1609 }
1610 
1611 #define MAXPRESETS 10
1612 
makepresetname(char * dest,int num)1613 void makepresetname(char *dest,int num)
1614 {
1615 char *p;
1616 	p=getenv("HOME");
1617 	if(p)
1618 		sprintf(dest,"%s/.fountspreset%d",p,num);
1619 	else
1620 		sprintf(dest,"founts%d",num);
1621 }
1622 
loadpresets(void)1623 void loadpresets(void)
1624 {
1625 int i;
1626 int file,len;
1627 char temp[256];
1628 	for(i=0;i<MAXPRESETS;++i)
1629 	{
1630 		if(preset[i]) {free(preset[i]);preset[i]=0;}
1631 		makepresetname(temp,i);
1632 		file=open(temp,O_RDONLY);
1633 		if(file>=0)
1634 		{
1635 			len=read(file,block64,65535);
1636 			if(len>=0)
1637 			{
1638 				block64[len]=0;
1639 				preset[i]=malloc(len+1);
1640 				if(preset[i])
1641 					strcpy(preset[i],(void *)block64);
1642 			}
1643 			close(file);
1644 		}
1645 	}
1646 }
1647 
1648 
writepreset(unsigned int code)1649 void writepreset(unsigned int code)
1650 {
1651 struct hose *ahose;
1652 struct block *ablock;
1653 char *p;
1654 char temp[256];
1655 int file;
1656 
1657 	if(code>=MAXPRESETS) return;
1658 
1659 	makepresetname(temp,code);
1660 
1661 	p=(void *)block64;
1662 	ahose=activehoses;
1663 	while(ahose)
1664 	{
1665 		sprintf(p,"hose:%d,%d,%d,%d,%d,%d\n",ahose->x,ahose->y,ahose->angle,
1666 				ahose->red,ahose->green,ahose->blue);
1667 		p+=strlen(p);
1668 		ahose=ahose->next;
1669 	}
1670 	ablock=activeblocks;
1671 	while(ablock)
1672 	{
1673 		sprintf(p,"block:%d,%d,%d\n",ablock->x,ablock->y,ablock->angle);
1674 		p+=strlen(p);
1675 		ablock=ablock->next;
1676 	}
1677 	*p++=0;
1678 	if(preset[code]) free(preset[code]);
1679 	preset[code]=malloc((void *)p-(void *)block64);
1680 	if(preset[code])
1681 	{
1682 		strcpy(preset[code],(const char *)block64);
1683 		file=open(temp,O_WRONLY|O_CREAT|O_TRUNC,0644);
1684 		if(file>=0)
1685 		{
1686 			int t;
1687 			t=write(file,block64,(void *)p-(void *)block64-1);
1688 			t=t;
1689 			close(file);
1690 		}
1691 	}
1692 }
deleteall(void)1693 void deleteall(void)
1694 {
1695 struct hose *ahose,*ahose2;
1696 struct block *ablock,*ablock2;
1697 	ahose=activehoses;
1698 	activehoses=0;
1699 	while(ahose)
1700 	{
1701 		ahose2=ahose;
1702 		ahose=ahose->next;
1703 		freehose(ahose2);
1704 	}
1705 	ablock=activeblocks;
1706 	activeblocks=0;
1707 	while(ablock)
1708 	{
1709 		ablock2=ablock;
1710 		ablock=ablock->next;
1711 		freeblock(ablock2);
1712 	}
1713 	makebbm();
1714 }
1715 
readpreset(int code)1716 void readpreset(int code)
1717 {
1718 struct hose *ahose,*lasthose;
1719 struct block *ablock,*lastblock;
1720 char *p;
1721 int v1,v2,v3,v4,v5,v6;
1722 
1723 	if(code>=MAXPRESETS) return;
1724 	p=preset[code];
1725 	if(!p) return;
1726 	deleteall();
1727 	lasthose=0;
1728 	lastblock=0;
1729 	while(*p)
1730 	{
1731 		if(sscanf(p,"hose:%d,%d,%d,%d,%d,%d",&v1,&v2,&v3,&v4,&v5,&v6)==6)
1732 		{
1733 			ahose=allochose();
1734 			if(ahose)
1735 			{
1736 				ahose->x=v1;
1737 				ahose->y=v2;
1738 				ahose->angle=v3;
1739 				ahose->red=v4;
1740 				ahose->green=v5;
1741 				ahose->blue=v6;
1742 				ahose->index=makeindex(v4,v5,v6);
1743 				ahose->next=0;
1744 				if(lasthose)
1745 					lasthose->next=ahose;
1746 				else
1747 					activehoses=ahose;
1748 				lasthose=ahose;
1749 			}
1750 		} else
1751 		if(sscanf(p,"block:%d,%d,%d",&v1,&v2,&v3)==3)
1752 		{
1753 			ablock=allocblock();
1754 			if(ablock)
1755 			{
1756 				ablock->x=v1;
1757 				ablock->y=v2;
1758 				ablock->angle=v3;
1759 				ablock->next=0;
1760 				if(lastblock)
1761 					lastblock->next=ablock;
1762 				else
1763 					activeblocks=ablock;
1764 				lastblock=ablock;
1765 			}
1766 		}
1767 		while(*p && *p++!='\n');
1768 	}
1769 	makebbm();
1770 }
1771 
putcolors(void)1772 void putcolors(void)
1773 {
1774 static unsigned short setup=0,cmap[512],*p;
1775 int i,j,k,t,r,g,b,x,y,c;
1776 
1777 	if(!setup)
1778 	{
1779 		t=0;
1780 		for(k=0;k<8;++k)
1781 		{
1782 			r=k*36.43;
1783 			for(j=0;j<8;++j)
1784 			{
1785 				g=j*36.43;
1786 				for(i=0;i<8;++i)
1787 				{
1788 					b=i*36.43;
1789 					cmap[t++]=maprgb(r,g,b);
1790 				}
1791 			}
1792 		}
1793 		setup=1;
1794 	}
1795 	t=0;
1796 	for(k=0;k<8;++k)
1797 	{
1798 		for(j=0;j<8;++j)
1799 		{
1800 			for(i=0;i<8;++i)
1801 			{
1802 				c=cmap[t++];
1803 				for(y=0;y<3;++y)
1804 				{
1805 					p=(unsigned short *)(videomem+
1806 						stride*((k<<2)+((j&4)<<3)+y+100)+(100+((((j&3)<<5)+(i<<2))<<1)));
1807 					for(x=0;x<3;++x)
1808 						*p++=c;
1809 				}
1810 			}
1811 		}
1812 	}
1813 }
1814 
1815 
1816 #define ASQR 1025
1817 unsigned char (*fractarr)[ASQR]=0;
1818 
1819 int fmap=0;
1820 
copyfract(void)1821 void copyfract(void)
1822 {
1823 unsigned char *p,*pb;
1824 unsigned short *ps;
1825 int i,j;
1826 int rmap[256],w;
1827 int r,g,b;
1828 
1829 	if(!fractarr) return;
1830 	for(i=0;i<256;++i)
1831 	{
1832 		switch(fmap&15)
1833 		{
1834 		default:
1835 			fmap=0;
1836 		case 0:
1837 			j=i<128 ? 0 : (i-128)<<1;
1838 			r=j;
1839 			g=j;
1840 			b=j<128 ? 128 : j;
1841 			break;
1842 		case 1:
1843 			if(i<64) r=g=b=0;
1844 			else if(i<128) r=(i<<2)&255,g=0,b=0;
1845 			else if(i<192) r=255,g=(i<<2)&255,b=0;
1846 			else r=255,g=255,b=(i<<2)&255;
1847 			break;
1848 		case 2:
1849 			if((i&15)<8) r=g=b=0;
1850 			else r=g=b=255;
1851 			break;
1852 		case 3:
1853 			r=g=b=((i&15)==8) ? 0 : 255;
1854 			break;
1855 		case 4:
1856 			j=i>>5;
1857 			r=(j&1) ? 255 : 0;
1858 			g=(j&2) ? 255 : 0;
1859 			b=(j&4) ? 255 : 0;
1860 			break;
1861 		case 5:
1862 			j=i>>5;
1863 			r=(j&1) ? 255 : 0;
1864 			g=(j&2) ? 255 : 0;
1865 			b=(j&4) ? 255 : 0;
1866 			j=i&31;
1867 			if(j>=16) j=31-j;
1868 			r=r*j>>4;
1869 			g=g*j>>4;
1870 			b=b*j>>4;
1871 			break;
1872 		case 6:
1873 			j=(i&63)<<4;
1874 			if(i<64) r=0,g=0,b=64;
1875 			else if(i<128) r=j,g=0,b=0;
1876 			else if(i<192) r=0,g=j,b=0;
1877 			else r=g=b=j;
1878 			break;
1879 		case 7:
1880 			j=(i&63)<<2;
1881 			if(i<64) r=0,g=0,b=64;
1882 			else if(i<128) r=j,g=0,b=0;
1883 			else if(i<192) r=0,g=j,b=0;
1884 			else r=g=b=j;
1885 			break;
1886 		}
1887 		rmap[i]=maprgb( r,g,b);
1888 	}
1889 
1890 	w=bitsperpixel==8 ? IXSIZE : IXSIZE<<1;
1891 	if(!fractback)
1892 		fractback=malloc(IYSIZE*w);
1893 	if(!fractback)
1894 		return;
1895 
1896 	for(j=0;j<IYSIZE;++j)
1897 	{
1898 		p=fractarr[j];
1899 		pb=fractback+j*w;
1900 		ps=(unsigned short *)pb;
1901 		for(i=0;i<IXSIZE;++i)
1902 		{
1903 			if(bitsperpixel==8)
1904 				*pb++=rmap[*p++];
1905 			else
1906 				*ps++=rmap[*p++];
1907 		}
1908 	}
1909 }
1910 
changefcolors(void)1911 void changefcolors(void)
1912 {
1913 	++fmap;
1914 	copyfract();
1915 }
1916 
diamond(int x,int y1,int y2,int y,int x1,int x2,int delta)1917 void diamond(int x,int y1,int y2,int y,int x1,int x2,int delta)
1918 {
1919 int c,average;
1920 	if(x<0 || x>ASQR || y<0 || y>ASQR) return;
1921 	c=average=0;
1922 	if(y1>=0)
1923 	{
1924 		++c;
1925 		average+=fractarr[x][y1];
1926 	}
1927 	if(y2<ASQR)
1928 	{
1929 		++c;
1930 		average+=fractarr[x][y2];
1931 	}
1932 	if(x1>=0)
1933 	{
1934 		++c;
1935 		average+=fractarr[x1][y];
1936 	}
1937 	if(x2<ASQR)
1938 	{
1939 		++c;
1940 		average+=fractarr[x2][y];
1941 	}
1942 	average=average/c+rand()%delta-(delta>>1);
1943 	if(average<0) average=0;
1944 	if(average>255) average=255;
1945 	fractarr[x][y]=average;
1946 }
fcenter(int step,int delta)1947 void fcenter(int step,int delta)
1948 {
1949 int i,j;
1950 int average;
1951 int step2;
1952 	step2=step>>1;
1953 
1954 	for(j=0;j<ASQR-1;j+=step)
1955 		for(i=0;i<ASQR-1;i+=step)
1956 		{
1957 			average=(fractarr[i][j]+fractarr[i+step][j]+
1958 				fractarr[i][j+step]+fractarr[i+step][j+step])>>2;
1959 			average+=rand()%delta-(delta>>1);
1960 			if(average<0) average=0;
1961 			if(average>255) average=255;
1962 			fractarr[i+step2][j+step2]=average;
1963 		}
1964 }
fdiamond(int step,int delta)1965 void fdiamond(int step,int delta)
1966 {
1967 int i,j;
1968 int step2;
1969 	step2=step>>1;
1970 	for(j=0;j<ASQR-1;j+=step)
1971 		for(i=0;i<ASQR-1;i+=step)
1972 		{
1973 			diamond(i+step2,j-step2,j+step2,j,i,i+step,delta);
1974 			diamond(i,j,j+step,j+step2,i-step2,i+step2,delta);
1975 		}
1976 }
1977 
fractal(void)1978 void fractal(void)
1979 {
1980 int j,k;
1981 
1982 	if(!fractarr)
1983 		fractarr=malloc(ASQR*ASQR);
1984 	if(!fractarr)
1985 		return;
1986 
1987 	memset(fractarr,128,ASQR*ASQR);
1988 	j=ASQR-1;
1989 	k=1024;
1990 	while(j>1 && k>0)
1991 	{
1992 		fcenter(j,k);
1993 		fdiamond(j,k);
1994 		j>>=1;
1995 		k>>=1;
1996 	}
1997 	copyfract();
1998 }
1999 
drawsphere(int r,int bx,int by,int vx,int vy,int vz,int rt,int gt,int bt)2000 void drawsphere(int r,int bx,int by,int vx,int vy,int vz,int rt,int gt,int bt)
2001 {
2002 float x,y,y2,z,radius;
2003 int i,j,j2,k,rint,rint2;
2004 float tvx,tvy,tvz;
2005 float dot;
2006 unsigned short *p;
2007 unsigned char *pc;
2008 unsigned char red[256],green[256],blue[256];
2009 float lvx,lvy,lvz;
2010 int rr,gg,bb;
2011 int row,col;
2012 
2013 	for(i=0;i<256;++i)
2014 	{
2015 		if(i<232)
2016 		{
2017 			red[i]=224;
2018 			green[i]=224;
2019 			blue[i]=224;
2020 		}
2021 		else if(i<250)
2022 		{
2023 			red[i]=rt;
2024 			green[i]=gt;
2025 			blue[i]=bt;
2026 		} else
2027 			red[i]=green[i]=blue[i]=0;
2028 	}
2029 
2030 	lvx=-1.0;
2031 	lvy=1.0;
2032 	lvz=1.5;
2033 	radius=sqrt(lvx*lvx+lvy*lvy+lvz*lvz);
2034 	lvx/=radius;
2035 	lvy/=radius;
2036 	lvz/=radius;
2037 
2038 	tvx=vx;
2039 	tvy=vy;
2040 	tvz=vz;
2041 	radius=sqrt(tvx*tvx+tvy*tvy+tvz*tvz)/127.5;
2042 	tvx/=radius;
2043 	tvy/=radius;
2044 	tvz/=radius;
2045 
2046 
2047 	bx=bx*IXSIZE/640;
2048 	by=by*IYSIZE/480;
2049 	r=r*IXSIZE/640;
2050 
2051 	radius=r;
2052 	rint=r;
2053 	rint2=rint*rint;
2054 	row=(IYSIZE>>1)+by;
2055 	col=(IXSIZE>>1)+bx-rint;
2056 	for(j=-rint;j<=rint;++j)
2057 	{
2058 		p=(unsigned short *)(pc=videomem+stridemult[row-j])+col;
2059 		pc+=col;
2060 		y=j/radius;
2061 		y2=y*y;
2062 		j2=j*j;
2063 		for(i=-rint;i<=rint;++i,++p)
2064 		{
2065 			if(i*i+j2>=rint2) continue;
2066 			x=i/radius;
2067 			z=sqrt(1.0-x*x-y2);
2068 			k=127.5+x*tvx+y*tvy+z*tvz;
2069 			dot=(x*lvx+y*lvy+z*lvz+1)/2;
2070 			dot*=dot*dot;
2071 			rr=red[k];
2072 			gg=green[k];
2073 			bb=blue[k];
2074 
2075 			if(dot>=0.98)
2076 			{
2077 				rr=(rr+3*255)>>2;
2078 				gg=(gg+3*255)>>2;
2079 				bb=(bb+3*255)>>2;
2080 			}
2081 
2082 			rr*=dot;
2083 			gg*=dot;
2084 			bb*=dot;
2085 
2086 			*p=maprgb(rr,gg,bb);
2087 		}
2088 	}
2089 }
2090 
2091 unsigned char rt[256],bt[256],gt[256];
sphere(void)2092 void sphere(void)
2093 {
2094 int i=0;
2095 int x,y,z,u,v;
2096 int j;
2097 int k;
2098 
2099 	while(!exitflag)
2100 	{
2101 		scaninput();
2102 		scrlock();
2103 		clear();
2104 
2105 		x=mousex-VIRTX/2;
2106 		y=VIRTY/2-mousey;
2107 		z=60*5*IXSIZE/640;
2108 
2109 		k=0;
2110 
2111 /*
2112 		drawsphere(120,-120,0,x,y,z,64,0,0);
2113 		drawsphere(120,120,0,x,y,z,64,0,0);
2114 */
2115 /*
2116 
2117 		i=120;
2118 		for(j=0;j<360;j+=i)
2119 		{
2120 			a=(j+(i>>1))*3.1415927/180;
2121 			u=120*cos(a);
2122 			v=120*sin(a);
2123 			drawsphere(80,u,v,x-u,y+v,z,rt[k],gt[k],bt[k]);
2124 			++k;
2125 		}
2126 */
2127 
2128 		for(j=0;j<7;++j)
2129 		{
2130 			v=(j-3)*40;
2131 			for(i=0;i<7;++i)
2132 			{
2133 				u=(i-3)*40;
2134 				drawsphere(20,u,v,x-u,y+v,z,rt[k],gt[k],bt[k]);
2135 				++k;
2136 			}
2137 		}
2138 
2139 
2140 		drawfigure(mousex*IXSIZE/VIRTX,mousey*IYSIZE/VIRTY,dummyball);
2141 		scrunlock();
2142 		++frames;
2143 	}
2144 	exitflag=0;
2145 	dosphere=0;
2146 }
2147 
doballs(void)2148 void doballs(void)
2149 {
2150 //tritest();
2151 //return;
2152 //dots();
2153 	fractal();
2154 	initballs();
2155 	initcolors();
2156 	inithoses();
2157 	initblocks();
2158 	initbbm();
2159 	addhose(255,255,255);
2160 	readpreset(0);
2161 	pulseon();
2162 	while(!exitflag)
2163 	{
2164 		scaninput();
2165 		if(dospiral) {dots();hc=1;}
2166 		if(dosphere) {sphere();hc=1;}
2167 
2168 		scrlock();
2169 		clear();
2170 		plotballs();
2171 		if(!dohide)
2172 		{
2173 			plothoses();
2174 			plotblocks();
2175 			drawcolors();
2176 		}
2177 		drawfigure(mousex*IXSIZE/VIRTX,mousey*IYSIZE/VIRTY,dummyball);
2178 //putcolors();
2179 		scrunlock();
2180 		while(pauseflag&&!exitflag)
2181 		{
2182 			scaninput();
2183 			hc=1;
2184 		}
2185 		++frames;
2186 
2187 /*
2188 This is the UNIX style of waiting, without wasting CPU cycles. Not
2189 portable though
2190 
2191 		if(!interrupted)
2192 			pause();
2193 		interrupted=0;
2194 */
2195 
2196 		while(hc>0)
2197 		{
2198 			if(rotating) spinangle+=47;
2199 			else spinangle=0;
2200 			dohoses();
2201 			moveballs();
2202 			cullballs();
2203 			--hc;
2204 		}
2205 	}
2206 }
2207 
updatemap(void)2208 void updatemap(void)
2209 {
2210 	SDL_SetColors(thescreen, themap, 0, 256);
2211 }
2212 
initeyes(void)2213 void initeyes(void)
2214 {
2215 int i;
2216 	for(i=0;i<256;++i)
2217 	{
2218 		rt[i]=rand();
2219 		gt[i]=rand();
2220 		bt[i]=rand();
2221 	}
2222 }
2223 
makeballs(void)2224 void makeballs(void)
2225 {
2226 int i,j,k,t,r,g,b;
2227 	t=0;
2228 	for(i=0;i<8;++i)
2229 	{
2230 		r=i*36.42;
2231 		for(j=0;j<8;++j)
2232 		{
2233 			g=j*36.42;
2234 			for(k=0;k<8;++k)
2235 			{
2236 				b=k*36.42;
2237 				ballarray[t++]=makeball(7,r,g,b);
2238 			}
2239 		}
2240 	}
2241 	dummyball=makeball(3,255,255,255);
2242 }
2243 
openx(void)2244 void openx(void)
2245 {
2246 unsigned long videoflags;
2247 int i;
2248 
2249 	for(i=0;i<256;++i)
2250 	{
2251 		themap[i].r=i;
2252 		themap[i].g=i;
2253 		themap[i].b=i;
2254 
2255 	}
2256 	if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0 )
2257 	{
2258 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
2259 		exit(1);
2260 	}
2261 //	videoflags = SDL_SWSURFACE|SDL_HWPALETTE|SDL_ANYFORMAT;
2262 	videoflags = SDL_SWSURFACE; //|SDL_FULLSCREEN;
2263 
2264 	thescreen = SDL_SetVideoMode(IXSIZE, IYSIZE, 16, videoflags);
2265 	if ( thescreen == NULL )
2266 	{
2267 		fprintf(stderr, "Couldn't set display mode: %s\n",
2268 							SDL_GetError());
2269 		SDL_Quit();
2270 		exit(5);
2271 	}
2272 	sdlloaded=1;
2273 	stride=thescreen->pitch;
2274 	videomem=thescreen->pixels;
2275 	bitsperpixel=thescreen->format->BitsPerPixel;
2276 	for(i=0;i<IYSIZE;++i) stridemult[i]=i*stride;
2277 	updatemap();
2278 	SDL_ShowCursor(0);
2279 }
2280 
processkey(int key,int mod)2281 void processkey(int key,int mod)
2282 {
2283 	if(key>=SDLK_1 && key<=SDLK_9)
2284 	{
2285 		key-=SDLK_1;
2286 		if(mod&(KMOD_RSHIFT|KMOD_LSHIFT))
2287 			writepreset(key);
2288 		else
2289 			readpreset(key);
2290 		return;
2291 	}
2292 	switch(key)
2293 	{
2294 	case SDLK_m:
2295 		mixing=!mixing;
2296 		break;
2297 	case SDLK_c:
2298 		changefcolors();
2299 		break;
2300 	case SDLK_r:
2301 		rotating=!rotating;
2302 		break;
2303 	case SDLK_s:
2304 		dospiral=!dospiral;
2305 		break;
2306 	case SDLK_e:
2307 		dosphere=!dosphere;
2308 		break;
2309 	case SDLK_f:
2310 		fractal();
2311 		break;
2312 	case SDLK_h:
2313 		dohide=!dohide;
2314 		break;
2315 	case SDLK_x:
2316 		deleteall();
2317 		break;
2318 	case SDLK_p:
2319 		pauseflag=!pauseflag;
2320 		break;
2321 	}
2322 }
2323 
processmouse(void)2324 void processmouse(void)
2325 {
2326 	hosehit();
2327 	blockhit();
2328 }
2329 
scaninput(void)2330 void scaninput(void)
2331 {
2332 SDL_Event event;
2333 int key,mod;
2334 
2335 	while(SDL_PollEvent(&event))
2336 	{
2337 		switch(event.type)
2338 		{
2339 		case SDL_KEYDOWN:
2340 			key=event.key.keysym.sym;
2341 			mod=event.key.keysym.mod;
2342  			if(key==SDLK_ESCAPE)
2343 				exitflag=1;
2344 			else processkey(key,mod);
2345 			break;
2346 		case SDL_MOUSEBUTTONUP:
2347 			buttonstate=NOTDOWN;
2348 			break;
2349 		case SDL_MOUSEBUTTONDOWN:
2350 			mousex=event.button.x*VIRTX/IXSIZE;
2351 			mousey=event.button.y*VIRTY/IYSIZE;
2352 			buttonstate=JUSTDOWN;
2353 			processmouse();
2354 			break;
2355 		case SDL_MOUSEMOTION:
2356 			mousex=event.motion.x*VIRTX/IXSIZE;
2357 			mousey=event.motion.y*VIRTY/IYSIZE;
2358 			if(buttonstate==JUSTDOWN) buttonstate=CONTDOWN;
2359 			processmouse();
2360 			break;
2361 		}
2362 	}
2363 }
2364 
2365 
main(int argc,char ** argv)2366 int main(int argc,char **argv)
2367 {
2368 int i;
2369 int starttime;
2370 
2371 	initeyes();
2372 	printf("Founts by David Ashley\n");
2373 	printf("http://www.xdr.com/dash\n");
2374 	printf("dash@xdr.com\n");
2375 	printf("Use: founts [screenwidth]\n");
2376 	printf("screenwidth is optional argument 100-2048 (default 640)\n");
2377 	printf("c          Change background colors\n");
2378 	printf("e          Eye demo\n");
2379 	printf("f          New fractal background\n");
2380 	printf("h          Hide/unhide the non-ball objects\n");
2381 	printf("m          Turn on/off mixing\n");
2382 	printf("p          Pause movement\n");
2383 	printf("r          Rotate hoses\n");
2384 	printf("s          Spiral pattern (escape to exit)\n");
2385 	printf("x          Delete everything\n");
2386 	printf("1-9        Load preset\n");
2387 	printf("shift 1-9  Store preset\n");
2388 	printf("Drag the fountains over the colors to change their color\n");
2389 
2390 	if(argc>1)
2391 	{
2392 		i=atoi(argv[1]);
2393 		if(i>=100 && i<=2048)
2394 		{
2395 			IYSIZE=IYSIZE*i/IXSIZE;
2396 			IXSIZE=i;
2397 		}
2398 	}
2399 
2400 	initmyrand();
2401 
2402 	openx();
2403 	block64=malloc(65536);
2404 	if(!block64) nomem("block64");
2405 	loadpresets();
2406 	makeballs();
2407 
2408 	mixing=0;
2409 	dospiral=0;
2410 	dosphere=0;
2411 	dohide=0;
2412 	rotating=0;
2413 
2414 	framecount=0;
2415 	gamemode=0;
2416 	exitflag=0;
2417 	starttime=SDL_GetTicks();
2418 	frames=0;
2419 	doballs();
2420 	starttime=SDL_GetTicks()-starttime;
2421 	if(!starttime) starttime=1;
2422 	closex();
2423 	printf("fps = %d\n",1000*frames/starttime);
2424 	return 0;
2425 }
2426 
2427 #define TRIFRAC 16
2428 #define HALF (1<<(TRIFRAC-1))
2429 
tri(int x1,int y1,int x2,int y2,int x3,int y3,void (* func)(int,int,int,long),long color)2430 void tri(int x1,int y1,int x2,int y2,int x3,int y3,
2431 		void (*func)(int,int,int,long),long color)
2432 {
2433 int xc1,xc2,xc3,xd1,xd2,dy;
2434 int t;
2435 
2436 	if(y1>y2) {t=x1;x1=x2;x2=t;t=y1;y1=y2;y2=t;}
2437 	if(y1>y3) {t=x1;x1=x3;x3=t;t=y1;y1=y3;y3=t;}
2438 	if(y2>y3) {t=x2;x2=x3;x3=t;t=y2;y2=y3;y3=t;}
2439 	xc1=x1<<TRIFRAC;
2440 	xc3=x3<<TRIFRAC;
2441 	dy=y3-y1-1;
2442 	if(dy<2) dy=2;
2443 	xd1=(xc3-xc1)/dy;
2444 	if(y2==y1)
2445 	{
2446 		xc2=x2<<TRIFRAC;
2447 		xd2=(xc3-xc2)/dy;
2448 	} else
2449 	{
2450 		xc2=xc1;
2451 		dy=y2-y1-1;
2452 		if(dy<2) dy=2;
2453 		xd2=((x2<<TRIFRAC)-xc2)/dy;
2454 	}
2455 	while(y1<y3)
2456 	{
2457 		func((xc1+HALF)>>TRIFRAC,y1,(xc2+HALF)>>TRIFRAC,color);
2458 		xc1+=xd1;
2459 		xc2+=xd2;
2460 		++y1;
2461 		if(y1==y2)
2462 		{
2463 			xc2=x2<<TRIFRAC;
2464 			dy=y3-y2-1;
2465 			if(dy<2) dy=2;
2466 			xd2=(xc3-xc2)/dy;
2467 		}
2468 	}
2469 }
2470