ftp://ftp.krokus.ru/pub/OpenBSD/distfiles/xscreensaver-4.22.tar.gz
[xscreensaver] / hacks / fireworkx.c
index 78a4e9017c7bf08674cafe5a0d930eb4a3cabb83..e8c27b5dc4604f2a03b9eda2295cec7611ddfe1e 100644 (file)
@@ -1,7 +1,9 @@
 /*
- * Fireworkx 1.3 - pyrotechnics simulation program
- * Copyright (c) 1999-2004 Rony B Chandran <ronybc@asia.com>
+ * Fireworkx 1.5 - pyrotechnics simulation program
+ * Copyright (c) 1999-2005 Rony B Chandran <ronybc@asia.com>
  *
+ * From Kerala, INDIA
+ * 
  * url: http://www.ronybc.8k.com
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * Fixed array access problems by beating on it with a large hammer.
  * Nicholas Miell <nmiell@gmail.com>
  *
+ * Freed 'free'ing up of memory by adding the forgotten 'XSync's
+ * Renuka S <renuka@local.net>
+ *
  */
 
 #include <math.h>
 #include "screenhack.h"
 #include <X11/Xutil.h>
 
-#define FWXVERSION "1.3"
+#define FWXVERSION "1.5"
 
-#define WIDTH 640
-#define HEIGHT 480
-#define SHELLCOUNT 3
+#define SHELLCOUNT 3                   /* 3 or 5  */
 #define PIXCOUNT 500                   /* 500     */
-#define RNDLIFE0 250                   /* violent */
-#define RNDLIFE1 1200                  /* 1200    */
-#define MINLIFE0 50                    /* violent */
-#define MINLIFE1 500                   /* 500     */
 #define POWER 5                        /* 5       */
 #define FTWEAK 12                      /* 12      */
 
+#if HAVE_X86_MMX
+void mmx_blur(char *a, int b, int c, int d); 
+void mmx_glow(char *a, int b, int c, int d, char *e);
+#endif
+
+#define rnd(x) ((int)(random() % (x)))
+
 static int depth;
 static int bigendian;
-static Bool light_on = True;
-static Bool fade_on  = False;
-static Bool shoot    = False;
-static Bool verbose  = False;
-static int delay     = 0;
-static int fsc_width = 0;
-static int fsc_height= 0;
-static int rndlife = RNDLIFE1;
-static int minlife = MINLIFE1;
-static float light_fade = 0.99;
-static unsigned char *real_palaka1 = NULL;
-static unsigned char *real_palaka2 = NULL;
+static Bool flash_on   = True;
+static Bool glow_on    = True;
+static Bool verbose    = False;
+static Bool shoot      = False;
+static int width;
+static int height;
+static int rndlife;
+static int minlife;
+static int delay = 0;
+static float flash_fade = 0.99;
 static unsigned char *palaka1=NULL;
 static unsigned char *palaka2=NULL;
 static XImage *xim=NULL;
@@ -67,49 +71,43 @@ typedef struct {
   float yv;}firepix;
 
 typedef struct {
+  unsigned int cx,cy;
   unsigned int life;
   unsigned int color;
-  unsigned int cx,cy;
   unsigned int special;
   unsigned int cshift;
   unsigned int vgn,shy;
-  float air,lum;
+  float air,flash;
   firepix *fpix; }fireshell;
 
-int seed = 2387776;
-int rnd(int x)
-{   /* xscreensaver */
-  if ((seed = seed % 44488 * 48271 - seed / 44488 * 3399) < 0)
-  seed += 2147483647;
-  return (seed-1) % x;
-}
-
 int explode(fireshell *fs)
 {
-  float air,adg = 0.001;     /* gravity */
+  float air,adg = 0.001;         /* gravity */
   unsigned int n,c;
-  unsigned int h = fsc_height;
-  unsigned int w = fsc_width;
+  unsigned int h = height;
+  unsigned int w = width;
   unsigned int *prgb;
   unsigned char *palaka = palaka1;
   firepix *fp = fs->fpix;
   if(fs->vgn){
     if(--fs->cy == fs->shy){  
-      fs->vgn = 0;
-      fs->lum = 20000;}    /* millions of jouls..! */
+      fs->vgn   = 0;
+      fs->flash = rnd(30000)+15000;}
     else{  
-      fs->lum = 50+(fs->cy - fs->shy)*2;
+      fs->flash = 50+(fs->cy - fs->shy)*2;
+      prgb=(unsigned int *)(palaka + (fs->cy * w + fs->cx + rnd(5)-2)*4);
+     *prgb=(rnd(8)+8)*0x000f0f10;
       return(1);}}    
   if(fs->cshift) --fs->cshift;
   if((fs->cshift+1)%50==0) fs->color = ~fs->color;
   c = fs->color;
   air = fs->air;
-  fs->lum *= light_fade;
+  fs->flash *= flash_fade;
   for(n=PIXCOUNT;n;n--){
   if(fp->burn){ --fp->burn; 
   if(fs->special){
   fp->x += fp->xv = fp->xv * air + (float)(rnd(200)-100)/2000;
-  fp->y += fp->yv = fp->yv * air + (float)(rnd(200)-100)/2000 +adg; }
+  fp->y += fp->yv = fp->yv * air + (float)(rnd(200)-100)/2000 + adg; }
   else{
   fp->x += fp->xv = fp->xv * air + (float)(rnd(200)-100)/20000;
   fp->y += fp->yv = fp->yv * air + adg; }
@@ -120,8 +118,7 @@ int explode(fireshell *fs)
      prgb = (unsigned int *)(palaka + ((int)fp->y * w + (int)fp->x)*4);
     *prgb = c; }
   } fp++;
-  } return(--(fs->life));
-}
+  } return(--fs->life); }
 
 void recycle(fireshell *fs,int x,int y)
 {
@@ -130,15 +127,17 @@ void recycle(fireshell *fs,int x,int y)
   fs->vgn = shoot;
   fs->shy = y;
   fs->cx = x;
-  fs->cy = shoot ? fsc_height : y ;
+  fs->cy = shoot ? height : y ;
   fs->color = (rnd(155)+100) <<16 |
               (rnd(155)+100) <<8  |
                rnd(255);
   fs->life = rnd(rndlife)+minlife;
   fs->air  = 1-(float)(rnd(200))/10000;
-  fs->lum  = 20000;
+  fs->flash   = rnd(30000)+15000;        /* million jouls */
   fs->cshift  = !rnd(5) ? 120:0; 
   fs->special = !rnd(10) ? 1:0; 
+  if(verbose)
+  printf("recycle(): color = %x air = %f life = %d \n",fs->color,fs->air,fs->life);
   pixlife = rnd(fs->life)+fs->life/10+1;    /* ! */
   for(n=0;n<PIXCOUNT;n++){
   fp->burn = rnd(pixlife)+32;
@@ -147,55 +146,76 @@ void recycle(fireshell *fs,int x,int y)
                (float)(rnd(20000)-10000)/10000;
   fp->x = x;
   fp->y = y; 
-  fp++;             }
-}
+  fp++;             }}
 
-void blur_best(void)
+void glow(void)
 {
-  int n;
-  unsigned int w = fsc_width;
-  unsigned int h = fsc_height;
-  unsigned char *pa, *pb, *pm;
+  unsigned int n,q;
+  unsigned int w = width;
+  unsigned int h = height;
+  unsigned char *pa, *pb, *pm, *po;
   pm = palaka1;
-  for(n=0;n<w*4;n++) pm[n]=0;    /* clean first line */
-  pm+=n;
-  h-=2; 
+  po = palaka2;
+  for(n=0;n<w*4;n++) 
+  {pm[n]=0; po[n]=0;}    /* clean first line */
+  pm+=n; po+=n; h-=2; 
   pa = pm-(w*4);
   pb = pm+(w*4);
-  if(fade_on){
-  for(n=0;n<w*h*4;n++){
-  pm[n]=(pm[n-4] + pm[n] + pm[n+4] + 
+  for(n=4;n<w*h*4-4;n++){
+  q    = pm[n-4] + (pm[n]*8) + pm[n+4] + 
          pa[n-4] + pa[n] + pa[n+4] + 
-         pb[n-4] + pb[n] + pb[n+4] +
-         pm[n] + pm[n] + (pm[n]<<2))/ 16;}}
-  else{
-  for(n=0;n<w*h*4;n++){
-  pm[n]=(pm[n-4] + pm[n] + pm[n+4] + 
+         pb[n-4] + pb[n] + pb[n+4];
+  q    -= q>8 ? 8:q;
+  pm[n] = q/16;
+  q     = q/8;
+  if(q>255) q=255;
+  po[n] = q;}
+  pm+=n; po+=n;
+  for(n=0;n<w*4;n++)
+  {pm[n]=0; po[n]=0;}}   /* clean last line */
+
+void blur(void)
+{
+  unsigned int n,q;
+  unsigned int w = width;
+  unsigned int h = height;
+  unsigned char *pa, *pb, *pm;
+  pm = palaka1;
+  pm += w*4; h-=2;  /* line 0&h */
+  pa = pm-(w*4);
+  pb = pm+(w*4);
+  for(n=4;n<w*h*4-4;n++){
+  q    = pm[n-4] + (pm[n]*8) + pm[n+4] + 
          pa[n-4] + pa[n] + pa[n+4] + 
-         pb[n-4] + pb[n] + pb[n+4])/ 9;}}
-  pm+=n;
-  for(n=0;n<w*4;n++) pm[n]=0;    /* clean last line */
-}
+         pb[n-4] + pb[n] + pb[n+4];
+  q    -= q>8 ? 8:q;
+  pm[n] = q>>4;}
+  pm += n-4;    /* last line */
+  for(n=0;n<w*4+4;n++) pm[n]=0;
+  pm = palaka1; /* first line */
+  for(n=0;n<w*4+4;n++) pm[n]=pm[n+w*4]; }
 
 void light_2x2(fireshell *fss)
 {
   unsigned int l,t,n,x,y;
   float s;
-  int w = fsc_width;
-  int h = fsc_height;
+  int w = width;
+  int h = height;
   unsigned char *dim = palaka2;
   unsigned char *sim = palaka1;
   int nl = w*4;
   fireshell *f;
+  if(glow_on) sim=dim;
   for(y=0;y<h;y+=2){
   for(x=0;x<w;x+=2){
   f = fss; s = 0;
   for(n=SHELLCOUNT;n;n--,f++){
-  s += f->lum / ( 1 + sqrt((f->cx - x)*(f->cx - x)+(f->cy - y)*(f->cy - y))); }
+  s += f->flash/(sqrt(1+(f->cx - x)*(f->cx - x)+
+                        (f->cy - y)*(f->cy - y)));}
   l = s;
 
   t = l + sim[0];
-  dim[0] = (t > 255 ? 255 : t);         /* cmov's */
+  dim[0] = (t > 255 ? 255 : t);        
   t = l + sim[1];
   dim[1] = (t > 255 ? 255 : t);
   t = l + sim[2];
@@ -222,42 +242,40 @@ void light_2x2(fireshell *fss)
   t = l + sim[nl+6];
   dim[nl+6] = (t > 255 ? 255 : t);
 
-  sim += 8; dim += 8; } sim += nl; dim += nl;}
-}
+  sim += 8; dim += 8; } sim += nl; dim += nl;}}
 
 void resize(Display *display, Window win)
 {
   XWindowAttributes xwa;
   XGetWindowAttributes (display, win, &xwa);
-  xwa.width  -= xwa.width % 4;
-  xwa.height -= xwa.height % 4;
-  if(xwa.height != fsc_height || xwa.width != fsc_width) {
-  fsc_width  = xwa.width;
-  fsc_height = xwa.height;
+  xwa.width  -= xwa.width % 2;
+  xwa.height -= xwa.height % 2;
+  if(xwa.height != height || xwa.width != width) {
+  width  = xwa.width;
+  height = xwa.height;
+  if (verbose)
+  printf("sky size: %dx%d ------------------------------\n",width,height);
+  XSync(display,0);
   if (xim) {
   if (xim->data==(char *)palaka2) xim->data=NULL;  
   XDestroyImage(xim);
-  if (palaka2!=palaka1) free(real_palaka2);
-  free(real_palaka1); 
+  XSync(display,0);
+  if (palaka2!=palaka1) free(palaka2 - 8);
+  free(palaka1 - 8); 
   }
-  palaka1 = NULL;     
-  palaka2 = NULL; 
+  palaka1 = NULL;
+  palaka2 = NULL;
   xim = XCreateImage(display, xwa.visual, xwa.depth, ZPixmap, 0, 0,
-                    fsc_width, fsc_height, 32, 0);
-  real_palaka1 = calloc(xim->height + 4,xim->width*4);
-  palaka1 = real_palaka1 + xim->width * 4 * 2;
-  if(light_on) {
-       real_palaka2 = calloc(xim->height + 4,xim->width*4);
-       palaka2 = real_palaka2 + xim->width * 4 * 2;
-  } else {
-       palaka2 = palaka1;
-  }
+                    width, height, 8, 0);
+  palaka1 = (unsigned char *) calloc(xim->height+1,xim->width*4) + 8;
+  if(flash_on|glow_on)
+  palaka2 = (unsigned char *) calloc(xim->height+1,xim->width*4) + 8;
+  else
+  palaka2 = palaka1;
   if (depth>=24)
   xim->data = (char *)palaka2;
   else
-  xim->data = calloc(xim->height,xim->bytes_per_line);       
- }
-}
+  xim->data = calloc(xim->height,xim->bytes_per_line); }}
 
 void put_image(Display *display, Window win, GC gc, XImage *xim)
 {
@@ -319,8 +337,7 @@ void put_image(Display *display, Window win, GC gc, XImage *xim)
      xim->data[i++] = (((7*g)/256)*36)+(((6*r)/256)*6)+((6*b)/256);
      }
   }
-  XPutImage(display,win,gc,xim,0,0,0,0,xim->width,xim->height); 
-}
+  XPutImage(display,win,gc,xim,0,0,0,0,xim->width,xim->height); }
 
 void sniff_events(Display *dis, Window win, fireshell *fss)
 {
@@ -329,8 +346,7 @@ void sniff_events(Display *dis, Window win, fireshell *fss)
   XNextEvent (dis, &e);
   if (e.type == ConfigureNotify) resize(dis,win);
   if (e.type == ButtonPress)     recycle(fss,e.xbutton.x, e.xbutton.y);
-  screenhack_handle_event(dis,&e);}
-}
+  screenhack_handle_event(dis,&e); }}
 
 
 char *progclass = "Fireworkx";
@@ -338,10 +354,10 @@ char *progclass = "Fireworkx";
 char *defaults [] = {
   ".background:        black",
   ".foreground:        white",
-  "*delay:     5000",
-  "*maxlife:   1200",
-  "*light:     True",
-  "*fade:      False",
+  "*delay:     10000",  /* never default to zero! */
+  "*maxlife:   2000",
+  "*flash:     True",
+  "*glow:      True",
   "*shoot:     False",
   "*verbose:   False",
   0
@@ -350,8 +366,8 @@ char *defaults [] = {
 XrmOptionDescRec options [] = {
   { "-delay",          ".delay",       XrmoptionSepArg, 0 },
   { "-maxlife",                ".maxlife",     XrmoptionSepArg, 0 },
-  { "-nolight",                ".light",       XrmoptionNoArg, "False" },
-  { "-fade",           ".fade",        XrmoptionNoArg, "True" },
+  { "-noflash",                ".flash",       XrmoptionNoArg, "False" },
+  { "-noglow",         ".glow",        XrmoptionNoArg, "False" },
   { "-shoot",          ".shoot",       XrmoptionNoArg, "True" },
   { "-verbose",                ".verbose",     XrmoptionNoArg, "True" },
   { 0, 0, 0, 0 }
@@ -367,21 +383,20 @@ screenhack (Display *display, Window win)
   XWindowAttributes xwa;
   GC gc;
   XGCValues gcv;
-  firepix *fpixs, *fpix;
-  fireshell *fshells, *fshell;
-  fade_on  = get_boolean_resource("fade"    , "Boolean");
-  light_on = get_boolean_resource("light"   , "Boolean");
+  firepix *fpix, *ffpix;
+  fireshell *fshell, *ffshell;
+  glow_on  = get_boolean_resource("glow"    , "Boolean");
+  flash_on = get_boolean_resource("flash"   , "Boolean");
   shoot    = get_boolean_resource("shoot"   , "Boolean");
   verbose  = get_boolean_resource("verbose" , "Boolean");
   rndlife  = get_integer_resource("maxlife" , "Integer");
   delay    = get_integer_resource("delay"   , "Integer");
   minlife  = rndlife/4;
-  if(rndlife<1000) light_fade=0.98;
-  if(rndlife<500) light_fade=0.97;
-  if(fade_on) light_fade=0.97;
+  if(rndlife<1000) flash_fade=0.98;
+  if(rndlife<500) flash_fade=0.97;
   if(verbose){
   printf("Fireworkx %s - pyrotechnics simulation program \n", FWXVERSION);
-  printf("Copyright (c) 1999-2004 Rony B Chandran <ronybc@asia.com> \n\n");
+  printf("Copyright (c) 1999-2005 Rony B Chandran <ronybc@asia.com> \n\n");
   printf("url: http://www.ronybc.8k.com \n\n");}
 
   XGetWindowAttributes(display,win,&xwa);
@@ -392,7 +407,7 @@ screenhack (Display *display, Window win)
  
   if(depth==8){
   if(verbose){
-  printf("Pseudocolor color: use '-fade' & '-nolight' for better results.\n");}
+  printf("Pseudocolor color: use '-noflash' for better results.\n");}
   colors = (XColor *) calloc(sizeof(XColor),ncolors+1);
   writable = False;
   make_smooth_colormap(display, vi, cmap, colors, &ncolors,
@@ -401,30 +416,38 @@ screenhack (Display *display, Window win)
   gc = XCreateGC(display, win, 0, &gcv);
 
   resize(display,win);   /* initialize palakas */ 
-  seed += time(0);
   
-  fpixs = malloc(sizeof(firepix) * PIXCOUNT * SHELLCOUNT);
-  fshells = malloc(sizeof(fireshell) * SHELLCOUNT);
-  fshell = fshells;
-  fpix = fpixs;
+  ffpix = malloc(sizeof(firepix) * PIXCOUNT * SHELLCOUNT);
+  ffshell = malloc(sizeof(fireshell) * SHELLCOUNT);
+  fshell = ffshell;
+  fpix = ffpix;
   for (n=0;n<SHELLCOUNT;n++){
   fshell->fpix = fpix;
-  recycle (fshell,rnd(fsc_width),rnd(fsc_height));
+  recycle (fshell,rnd(width),rnd(height));
   fshell++; 
   fpix += PIXCOUNT; }
   
   while(1) {
   for(q=FTWEAK;q;q--){
-  fshell=fshells;
+  fshell=ffshell;
   for(n=SHELLCOUNT;n;n--){
   if (!explode(fshell)){
-       recycle(fshell,rnd(fsc_width),rnd(fsc_height)); }
+       recycle(fshell,rnd(width),rnd(height)); }
        fshell++; }}
-  if(light_on) light_2x2(fshells);
+#if HAVE_X86_MMX
+  if(glow_on) mmx_glow(palaka1,width,height,8,palaka2);
+#else
+  if(glow_on) glow();
+#endif
+  if(flash_on) light_2x2(ffshell);
   put_image(display,win,gc,xim);
   usleep(delay);
   XSync(display,0);
-  sniff_events(display, win, fshells);
-  blur_best();}
+  sniff_events(display, win, ffshell);
+#if HAVE_X86_MMX
+  if(!glow_on) mmx_blur(palaka1,width,height,8);
+#else
+  if(!glow_on) blur();
+#endif
 
-}
+}}