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