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