1 /*****************************************************************************/
2 /*                               XFlame v1.0                                 */
3 /*****************************************************************************/
4 /* By:                                                                       */
5 /*     The Rasterman (Carsten Haitzler)                                      */
6 /*      Copyright (C) 1996                                                   */
7 /*****************************************************************************/
8 /* Ported to SDL by:                                                         */
9 /*     Sam Lantinga                                                          */
10 /*                                                                           */
11 /* This is a dirty port, just to get it working on SDL.                      */
12 /* Improvements left to the reader:                                          */
13 /* 	Use depth-specific code to optimize HiColor/TrueColor display        */
14 /* 	Fix the delta code -- it's broken -- shame on Rasterman ;-)          */
15 /*                                                                           */
16 /*****************************************************************************/
17 /* Modified for use in Atris by:
18  * 	Wes Weimer
19  *****************************************************************************/
20 /*****************************************************************************/
21 /* This code is Freeware. You may copy it, modify it or do with it as you    */
22 /* please, but you may not claim copyright on any code wholly or partly      */
23 /* based on this code. I accept no responisbility for any consequences of    */
24 /* using this code, be they proper or otherwise.                             */
25 /*****************************************************************************/
26 /* Okay, now all the legal mumbo-jumbo is out of the way, I will just say    */
27 /* this: enjoy this program, do with it as you please and watch out for more */
28 /* code releases from The Rasterman running under X... the only way to code. */
29 /*****************************************************************************/
30 
31 
32 /* INCLUDES! */
33 #include <config.h>
34 #include "atris.h"
35 #include "options.h"
36 #include <stdlib.h>
37 #include <stdio.h>
38 
39 /* DEFINES */
40 #define GEN 500
41 #define MAX 300
42 #define WID 80
43 #define HIH 60
44 #define HSPREAD 26
45 #define VSPREAD 78
46 #define VFALLOFF 14
47 #define VARIANCE 5
48 #define VARTREND 2
49 #define RESIDUAL 68
50 
51 #define NONE 0x00
52 #define CMAP 0x02
53 #define DELT 0x08		/* Delta code is broken -- Rasterman? */
54 #define BLOK 0x20
55 #define LACE 0x40
56 /*This structure contains all of the "Global" variables for my program so */
57 /*that I just pass a pointer to my functions, not a million parameters */
58 struct globaldata
59 {
60   Uint32 flags;
61   SDL_Surface *screen;
62   int nrects;
63   SDL_Rect *rects;
64 };
65 
powerof(unsigned int n)66 int powerof(unsigned int n)
67 {
68   /* This returns the power of a number (eg powerof(8)==3, powerof(256)==8, */
69   /* powerof(1367)==11, powerof(2568)==12) */
70   int p;
71   if (n<=0x00000001) p=0;
72   else if (n<=0x00000002) p=1;
73   else if (n<=0x00000004) p=2;
74   else if (n<=0x00000008) p=3;
75   else if (n<=0x00000010) p=4;
76   else if (n<=0x00000020) p=5;
77   else if (n<=0x00000040) p=6;
78   else if (n<=0x00000080) p=7;
79   else if (n<=0x00000100) p=8;
80   else if (n<=0x00000200) p=9;
81   else if (n<=0x00000400) p=10;
82   else if (n<=0x00000800) p=11;
83   else if (n<=0x00001000) p=12;
84   else if (n<=0x00002000) p=13;
85   else if (n<=0x00004000) p=14;
86   else if (n<=0x00008000) p=15;
87   else if (n<=0x00010000) p=16;
88   else if (n<=0x00020000) p=17;
89   else if (n<=0x00040000) p=18;
90   else if (n<=0x00080000) p=19;
91   else if (n<=0x00100000) p=20;
92   else if (n<=0x00200000) p=21;
93   else if (n<=0x00400000) p=22;
94   else if (n<=0x00800000) p=23;
95   else if (n<=0x01000000) p=24;
96   else if (n<=0x02000000) p=25;
97   else if (n<=0x04000000) p=26;
98   else if (n<=0x08000000) p=27;
99   else if (n<=0x10000000) p=28;
100   else if (n<=0x20000000) p=29;
101   else if (n<=0x40000000) p=30;
102   else if (n<=0x80000000) p=31;
103   else p = 32;
104   return p;
105 }
106 
107 static void
SetFlamePalette(struct globaldata * gb,int f,int * ctab)108 SetFlamePalette(struct globaldata *gb, int f,int *ctab)
109 {
110   /*This function sets the flame palette */
111   int r,g,b,i;
112   SDL_Color cmap[MAX];
113 
114   /* This step is only needed on palettized screens */
115   r = g = b = 0;
116   for (i=0; (r != 255) || (g != 255) || (b != 255); i++)
117     {
118       r=i*3;
119       g=(i-80)*3;
120       b=(i-160)*3;
121       if (r<0) r=0;
122       if (r>255) r=255;
123       if (g<0) g=0;
124       if (g>255) g=255;
125       if (b<0) b=0;
126       if (b>255) b=255;
127       cmap[i].r = r;
128       cmap[i].g = g;
129       cmap[i].b = b;
130     }
131   SDL_SetColors(gb->screen, cmap, 0, i);
132 
133   /* This step is for all depths */
134   for (i=0;i<MAX;i++)
135     {
136       r=i*3;
137       g=(i-80)*3;
138       b=(i-160)*3;
139       if (r<0) r=0;
140       if (r>255) r=255;
141       if (g<0) g=0;
142       if (g>255) g=255;
143       if (b<0) b=0;
144       if (b>255) b=255;
145       ctab[i]=SDL_MapRGB(gb->screen->format, (Uint8)r, (Uint8)g, (Uint8)b);
146     }
147 }
148 
149 static void
XFSetRandomFlameBase(int * f,int w,int ws,int h)150 XFSetRandomFlameBase(int *f, int w, int ws, int h)
151 {
152   /*This function sets the base of the flame to random values */
153   int x,y,*ptr;
154 
155   /* initialize a random number seed from the time, so we get random */
156   /* numbers each time */
157   SeedRandom(0);
158   y=h-1;
159   for (x=0;x<w;x++)
160     {
161       ptr=f+(y<<ws)+x;
162       *ptr = FastRandom(MAX);
163     }
164 }
165 
166 static void
XFModifyFlameBase(int * f,int w,int ws,int h)167 XFModifyFlameBase(int *f, int w, int ws, int h)
168 {
169   /*This function modifies the base of the flame with random values */
170   int x,y,*ptr,val;
171 
172   y=h-1;
173   for (x=0;x<w;x++)
174     {
175       ptr=f+(y<<ws)+x;
176       *ptr+=((FastRandom(VARIANCE))-VARTREND);
177       val=*ptr;
178       if (val>MAX) *ptr=0;
179       if (val<0) *ptr=0;
180     }
181 }
182 
183 static void
XFProcessFlame(int * f,int w,int ws,int h,int * ff)184 XFProcessFlame(int *f, int w, int ws, int h, int *ff)
185 {
186   /*This function processes entire flame array */
187   int x,y,*ptr,*p,tmp,val;
188 
189   for (y=(h-1);y>=2;y--)
190     {
191       for (x=1;x<(w-1);x++)
192 	{
193 	  ptr=f+(y<<ws)+x;
194 	  val=(int)*ptr;
195 	  if (val>MAX) *ptr=(int)MAX;
196 	  val=(int)*ptr;
197 	  if (val>0)
198 	    {
199 	      tmp=(val*VSPREAD)>>8;
200 	      p=ptr-(2<<ws);
201 	      *p=*p+(tmp>>1);
202 	      p=ptr-(1<<ws);
203 	      *p=*p+tmp;
204 	      tmp=(val*HSPREAD)>>8;
205 	      p=ptr-(1<<ws)-1;
206 	      *p=*p+tmp;
207 	      p=ptr-(1<<ws)+1;
208 	      *p=*p+tmp;
209 	      p=ptr-1;
210 	      *p=*p+(tmp>>1);
211 	      p=ptr+1;
212 	      *p=*p+(tmp>>1);
213 	      p=ff+(y<<ws)+x;
214 	      *p=val;
215 	      if (y<(h-1)) *ptr=(val*RESIDUAL)>>8;
216 	    }
217 	}
218     }
219 }
220 
221 static void
XFDrawFlameBLOK(struct globaldata * g,int * f,int w,int ws,int h,int * ctab)222 XFDrawFlameBLOK(struct globaldata *g,int *f, int w, int ws, int h, int *ctab)
223 {
224   /*This function copies & displays the flame image in one large block */
225   int x,y,*ptr,xx,yy,cl,cl1,cl2,cl3,cl4;
226   unsigned char *cptr,*im,*p;
227 
228   /* get pointer to the image data */
229   if ( SDL_LockSurface(g->screen) < 0 )
230     return;
231 
232   /* copy the calculated flame array to the image buffer */
233   im=(unsigned char *)g->screen->pixels;
234   for (y=0;y<(h-1);y++)
235     {
236       for (x=0;x<(w-1);x++)
237 	{
238 	  xx=x<<1;
239 	  yy=y<<1;
240 	  ptr=f+(y<<ws)+x;
241 	  cl1=cl=(int)*ptr;
242 	  ptr=f+(y<<ws)+x+1;
243 	  cl2=(int)*ptr;
244 	  ptr=f+((y+1)<<ws)+x+1;
245 	  cl3=(int)*ptr;
246 	  ptr=f+((y+1)<<ws)+x;
247 	  cl4=(int)*ptr;
248 	  cptr=im+yy*g->screen->pitch+xx;
249 	  *cptr=(unsigned char)ctab[cl%MAX];
250 	  p=cptr+1;
251 	  *p=(unsigned char)ctab[((cl1+cl2)>>1)%MAX];
252 	  p=cptr+1+g->screen->pitch;
253 	  *p=(unsigned char)ctab[((cl1+cl3)>>1)%MAX];
254 	  p=cptr+g->screen->pitch;
255 	  *p=(unsigned char)ctab[((cl1+cl4)>>1)%MAX];
256 	}
257     }
258   SDL_UnlockSurface(g->screen);
259 
260   /* copy the image to the screen in one large chunk */
261   SDL_Flip(g->screen);
262 }
263 
264 static void
XFUpdate(struct globaldata * g)265 XFUpdate(struct globaldata *g)
266 {
267 	if ( (g->screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
268 		SDL_Flip(g->screen);
269 	} else {
270 	    int i;
271 	    extern SDL_Surface * screen, * widget_layer, *flame_layer;
272 	    for (i=0; i<g->nrects; i++) {
273 		SDL_BlitSurface(flame_layer, &g->rects[i],
274 			screen, &g->rects[i]);
275 		SDL_BlitSurface(widget_layer, &g->rects[i],
276 			screen, &g->rects[i]);
277 	    }
278 	    SDL_UpdateRects(screen, g->nrects, g->rects);
279 	}
280 }
281 
282 static void
XFDrawFlameLACE(struct globaldata * g,int * f,int w,int ws,int h,int * ctab)283 XFDrawFlameLACE(struct globaldata *g,int *f, int w, int ws, int h, int *ctab)
284 {
285   /*This function copies & displays the flame image in interlaced fashion */
286   /*that it, it first processes and copies the even lines to the screen, */
287   /* then is processes and copies the odd lines of the image to the screen */
288   int x,y,*ptr,xx,yy,cl,cl1,cl2,cl3,cl4;
289   unsigned char *cptr,*im,*p;
290 
291   /* get pointer to the image data */
292   if ( SDL_LockSurface(g->screen) < 0 )
293     return;
294 
295   /* copy the calculated flame array to the image buffer */
296   im=(unsigned char *)g->screen->pixels;
297   for (y=0;y<(h-1);y++)
298     {
299       for (x=0;x<(w-1);x++)
300 	{
301 	  xx=x<<1;
302 	  yy=y<<1;
303 	  ptr=f+(y<<ws)+x;
304 	  cl1=cl=(int)*ptr;
305 	  ptr=f+(y<<ws)+x+1;
306 	  cl2=(int)*ptr;
307 	  ptr=f+((y+1)<<ws)+x+1;
308 	  cl3=(int)*ptr;
309 	  ptr=f+((y+1)<<ws)+x;
310 	  cl4=(int)*ptr;
311 	  cptr=im+yy*g->screen->pitch+xx;
312 	  *cptr=(unsigned char)ctab[cl%MAX];
313 	  p=cptr+1;
314 	  *p=(unsigned char)ctab[((cl1+cl2)>>1)%MAX];
315 	  p=cptr+1+g->screen->pitch;
316 	  *p=(unsigned char)ctab[((cl1+cl3)>>1)%MAX];
317 	  p=cptr+g->screen->pitch;
318 	  *p=(unsigned char)ctab[((cl1+cl4)>>1)%MAX];
319 	}
320     }
321   SDL_UnlockSurface(g->screen);
322 
323   /* copy the even lines to the screen */
324   w <<= 1;
325   h <<= 1;
326   g->nrects = 0;
327   for (y=0;y<(h-1);y+=4)
328     {
329       g->rects[g->nrects].x = 0;
330       g->rects[g->nrects].y = y;
331       g->rects[g->nrects].w = w;
332       g->rects[g->nrects].h = 1;
333       ++g->nrects;
334     }
335   XFUpdate(g);
336   /* copy the odd lines to the screen */
337   g->nrects = 0;
338   for (y=2;y<(h-1);y+=4)
339     {
340       g->rects[g->nrects].x = 0;
341       g->rects[g->nrects].y = y;
342       g->rects[g->nrects].w = w;
343       g->rects[g->nrects].h = 1;
344       ++g->nrects;
345     }
346   XFUpdate(g);
347   /* copy the even lines to the screen */
348   g->nrects = 0;
349   for (y=1;y<(h-1);y+=4)
350     {
351       g->rects[g->nrects].x = 0;
352       g->rects[g->nrects].y = y;
353       g->rects[g->nrects].w = w;
354       g->rects[g->nrects].h = 1;
355       ++g->nrects;
356     }
357   XFUpdate(g);
358   /* copy the odd lines to the screen */
359   g->nrects = 0;
360   for (y=3;y<(h-1);y+=4)
361     {
362       g->rects[g->nrects].x = 0;
363       g->rects[g->nrects].y = y;
364       g->rects[g->nrects].w = w;
365       g->rects[g->nrects].h = 1;
366       ++g->nrects;
367     }
368   XFUpdate(g);
369 }
370 
371 static void
XFDrawFlame(struct globaldata * g,int * f,int w,int ws,int h,int * ctab)372 XFDrawFlame(struct globaldata *g,int *f, int w, int ws, int h, int *ctab)
373 {
374   /*This function copies & displays the flame image in interlaced fashion */
375   /*that it, it first processes and copies the even lines to the screen, */
376   /* then is processes and copies the odd lines of the image to the screen */
377   int x,y,*ptr,xx,yy,cl,cl1,cl2,cl3,cl4;
378   unsigned char *cptr,*im,*p;
379 
380   /* get pointer to the image data */
381   if ( SDL_LockSurface(g->screen) < 0 )
382     return;
383 
384   /* copy the calculated flame array to the image buffer */
385   im=(unsigned char *)g->screen->pixels;
386   for (y=0;y<(h-1);y++)
387     {
388       for (x=0;x<(w-1);x++)
389 	{
390 	  xx=x<<1;
391 	  yy=y<<1;
392 	  ptr=f+(y<<ws)+x;
393 	  cl1=cl=(int)*ptr;
394 	  ptr=f+(y<<ws)+x+1;
395 	  cl2=(int)*ptr;
396 	  ptr=f+((y+1)<<ws)+x+1;
397 	  cl3=(int)*ptr;
398 	  ptr=f+((y+1)<<ws)+x;
399 	  cl4=(int)*ptr;
400 	  cptr=im+yy*g->screen->pitch+xx;
401 	  *cptr=(unsigned char)ctab[cl%MAX];
402 	  p=cptr+1;
403 	  *p=(unsigned char)ctab[((cl1+cl2)>>1)%MAX];
404 	  p=cptr+1+g->screen->pitch;
405 	  *p=(unsigned char)ctab[((cl1+cl3)>>1)%MAX];
406 	  p=cptr+g->screen->pitch;
407 	  *p=(unsigned char)ctab[((cl1+cl4)>>1)%MAX];
408 	}
409     }
410   SDL_UnlockSurface(g->screen);
411 
412   /* copy the even lines to the screen */
413   w <<= 1;
414   h <<= 1;
415   g->nrects = 0;
416   for (y=0;y<(h-1);y+=2)
417     {
418       g->rects[g->nrects].x = 0;
419       g->rects[g->nrects].y = y;
420       g->rects[g->nrects].w = w;
421       g->rects[g->nrects].h = 1;
422       ++g->nrects;
423     }
424   XFUpdate(g);
425   /* copy the odd lines to the screen */
426   g->nrects = 0;
427   for (y=1;y<(h-1);y+=2)
428     {
429       g->rects[g->nrects].x = 0;
430       g->rects[g->nrects].y = y;
431       g->rects[g->nrects].w = w;
432       g->rects[g->nrects].h = 1;
433       ++g->nrects;
434     }
435   XFUpdate(g);
436 }
437 
438 
439 static int *flame,flamesize,ws,flamewidth,flameheight,*flame2;
440 static struct globaldata *g;
441 static int w, h, f, *ctab;
442 
443 /***************************************************************************
444  *********************************************************************PROTO*/
445 void
atris_run_flame(void)446 atris_run_flame(void)
447 {
448     if (!Options.flame_wanted) return;
449 
450     /* modify the bas of the flame */
451     XFModifyFlameBase(flame,w>>1,ws,h>>1);
452     /* process the flame array, propagating the flames up the array */
453     XFProcessFlame(flame,w>>1,ws,h>>1,flame2);
454     /* if the user selected BLOCK display method, then display the flame */
455     /* all in one go, no fancy upating techniques involved */
456     if (f&BLOK)
457     {
458 	XFDrawFlameBLOK(g,flame2,w>>1,ws,h>>1,ctab);
459     }
460     else if (f&LACE)
461 	/* the default of displaying the flames INTERLACED */
462     {
463 	XFDrawFlameLACE(g,flame2,w>>1,ws,h>>1,ctab);
464     }
465     else
466     {
467 	XFDrawFlame(g,flame2,w>>1,ws,h>>1,ctab);
468     }
469 }
470 
Xflame(struct globaldata * _g,int _w,int _h,int _f,int * _ctab)471 static int Xflame(struct globaldata *_g,int _w, int _h, int _f, int *_ctab)
472 {
473 
474   g = _g; w = _w; h = _h; f = _f; ctab = _ctab;
475 
476   /*This function is the hub of XFlame.. it initialises the flame array, */
477   /*processes the array, genereates the flames and displays them */
478 
479   /* workout the size needed for the flame array */
480   flamewidth=w>>1;
481   flameheight=h>>1;
482   ws=powerof(flamewidth);
483   flamesize=(1<<ws)*flameheight*sizeof(int);
484   /* allocate the memory for the flame array */
485   flame=(int *)malloc(flamesize);
486   /* if we didn't get the memory, return 0 */
487   if (!flame) return 0;
488   memset(flame, 0, flamesize);
489   /* allocate the memory for the second flame array */
490   flame2=(int *)malloc(flamesize);
491   /* if we didn't get the memory, return 0 */
492   if (!flame2) return 0;
493   memset(flame2, 0, flamesize);
494   if (f&BLOK)
495     {
496       g->rects = NULL;
497     }
498   else if (f&LACE)
499     {
500       /* allocate the memory for update rectangles */
501       g->rects=(SDL_Rect *)malloc((h>>2)*sizeof(SDL_Rect));
502       /* if we couldn't get the memory, return 0 */
503       if (!g->rects) return 0;
504     }
505   else
506     {
507       /* allocate the memory for update rectangles */
508       g->rects=(SDL_Rect *)malloc((h>>1)*sizeof(SDL_Rect));
509       /* if we couldn't get the memory, return 0 */
510       if (!g->rects) return 0;
511     }
512   /* set the base of the flame to something random */
513   XFSetRandomFlameBase(flame,w>>1,ws,h>>1);
514   /* now loop, generating and displaying flames */
515 #if 0
516   for (done=0; !done; )
517     {
518     }
519     return(done);
520 #endif
521     return 0;
522 }
523 
524 static struct globaldata glob;
525 static int flags;
526 static int colortab[MAX];
527 
528 /***************************************************************************
529  *********************************************************************PROTO*/
530 void
atris_xflame_setup(void)531 atris_xflame_setup(void)
532 {
533     extern SDL_Surface *flame_layer;
534 
535     memset(&glob, 0, sizeof(glob));
536     /*
537     glob.flags |= SDL_HWSURFACE;
538     */
539     glob.flags |= SDL_HWPALETTE;
540     glob.screen = flame_layer;
541 
542     SetFlamePalette(&glob,flags,colortab);
543     Xflame(&glob,glob.screen->w,glob.screen->h,flags,colortab);
544 }
545 
546