From http://www.jwz.org/xscreensaver/xscreensaver-5.39.tar.gz
[xscreensaver] / hacks / glx / glforestfire.c
index 589ed6172ddf19981f904a2f9aa641c7430e7612..bcc9ed7fd47f76daae13d3b3a4cc169d8a61015a 100644 (file)
@@ -75,25 +75,15 @@ static const char sccsid[] = "@(#)fire.c    5.02 2001/09/26 xlockmore";
 
 
 #ifdef STANDALONE      /* xscreensaver mode */
-#define PROGCLASS      "Fire"
-#define HACK_INIT      init_fire
-#define HACK_DRAW      draw_fire
-#define HACK_RESHAPE   reshape_fire
-#define fire_opts      xlockmore_opts
 #define DEFAULTS "*delay:     10000 \n" \
                "*count:        800 \n" \
                "*size:           0 \n" \
-               "*trees:          5 \n" \
                "*showFPS:    False \n" \
-               "*trackmouse: False \n" \
-               "*wander:      True \n" \
                "*wireframe:  False \n" \
-               "*fog:        False \n" \
-               "*shadows:     True \n" \
-               "*texture:     True \n"
 
 #define MODE_fire
 #include "xlockmore.h"         /* from the xscreensaver distribution */
+#include "gltrackball.h"
 #else                          /* !STANDALONE */
 #include "xlock.h"             /* from the xlockmore distribution */
 #include "visgl.h"
@@ -103,22 +93,13 @@ static const char sccsid[] = "@(#)fire.c   5.02 2001/09/26 xlockmore";
 
 #define MINSIZE 32
 
-#include <GL/gl.h>
-#include <GL/glx.h>
-#include <GL/glu.h>
-
-#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined( HAVE_XPM )
+#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined(STANDALONE)
 /* USE_XPM & USE_XPMINC in xlock mode ; HAVE_XPM in xscreensaver mode */
-#include "xpm-ximage.h"
+#include "ximage-loader.h"
 #define I_HAVE_XPM
 
-#ifdef STANDALONE
-#include "../images/ground.xpm"
-#include "../images/tree.xpm"
-#else /* !STANDALONE */
-#include "pixmaps/ground.xpm"
-#include "pixmaps/tree.xpm"
-#endif /* !STANDALONE */
+#include "images/gen/ground_png.h"
+#include "images/gen/tree_png.h"
 #endif /* HAVE_XPM */
 
 /* vector utility macros */
@@ -166,17 +147,14 @@ static const char sccsid[] = "@(#)fire.c  5.02 2001/09/26 xlockmore";
 #define DEF_FOG                "False"
 #define DEF_SHADOWS    "True"
 #define DEF_FRAMERATE  "False"
-#define DEF_TRACKMOUSE  "False"
 #define DEF_WANDER     "True"
 #define DEF_TREES      "5"
 #define MAX_TREES      20
 static Bool do_texture;
 static Bool do_fog;
 static Bool do_shadows;
-static Bool do_trackmouse;
 static Bool do_wander;
 static int num_trees;
-static int frame = 0;
 static XFontStruct *mode_font = None;
 
 static XrmOptionDescRec opts[] = {
@@ -186,8 +164,6 @@ static XrmOptionDescRec opts[] = {
     {"+fog", ".fire.fog", XrmoptionNoArg, "off"},
     {"-shadows", ".fire.shadows", XrmoptionNoArg, "on"},
     {"+shadows", ".fire.shadows", XrmoptionNoArg, "off"},
-    {"-trackmouse", ".fire.trackmouse", XrmoptionNoArg, "on"},
-    {"+trackmouse", ".fire.trackmouse", XrmoptionNoArg, "off"},
     {"-wander", ".fire.wander", XrmoptionNoArg, "on"},
     {"+wander", ".fire.wander", XrmoptionNoArg, "off"},
     {"-trees", ".fire.trees", XrmoptionSepArg, 0},
@@ -199,7 +175,6 @@ static argtype vars[] = {
     {&do_texture,    "texture",    "Texture",    DEF_TEXTURE,    t_Bool},
     {&do_fog,        "fog",        "Fog",        DEF_FOG,        t_Bool},
     {&do_shadows,    "shadows",    "Shadows",    DEF_SHADOWS,    t_Bool},
-    {&do_trackmouse, "trackmouse", "TrackMouse", DEF_TRACKMOUSE, t_Bool},
     {&do_wander,     "wander",     "Wander",     DEF_WANDER,     t_Bool},
     {&num_trees,     "trees",      "Trees",      DEF_TREES,      t_Int},
 };
@@ -208,12 +183,11 @@ static OptionStruct desc[] = {
     {"-/+texture", "turn on/off texturing"},
     {"-/+fog", "turn on/off fog"},
     {"-/+shadows", "turn on/off shadows"},
-    {"-/+trackmouse", "turn on/off the tracking of the mouse"},
     {"-/+wander", "turn on/off wandering"},
     {"-trees num", "number of trees (0 disables)"},
 };
 
-ModeSpecOpt fire_opts =
+ENTRYPOINT ModeSpecOpt fire_opts =
  { sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc };
 
 #ifdef USE_MODULES
@@ -257,13 +231,13 @@ typedef struct {
 } rain;
 
 /* colors */
-static float black[3]    = { 0.0, 0.0, 0.0 }; /* shadow color */
-static float partcol1[3] = { 1.0, 0.2, 0.0 }; /* initial color: red-ish */
-static float partcol2[3] = { 1.0, 1.0, 0.0 }; /* blending color: yellow-ish */
-static float fogcolor[4] = { 0.9, 0.9, 1.0, 1.0 };
+static const GLfloat black[3]    = { 0.0, 0.0, 0.0 }; /* shadow color */
+static const GLfloat partcol1[3] = { 1.0, 0.2, 0.0 }; /* initial color: red-ish */
+static const GLfloat partcol2[3] = { 1.0, 1.0, 0.0 }; /* blending color: yellow-ish */
+static const GLfloat fogcolor[4] = { 0.9, 0.9, 1.0, 1.0 };
 
 /* ground */
-static float q[4][3] = {
+static const float q[4][3] = {
     {-DIMP, 0.0, -DIMP},
     {DIMP, 0.0, -DIMP},
     {DIMP, 0.0, DIMP},
@@ -271,7 +245,7 @@ static float q[4][3] = {
 };
 
 /* ground texture */
-static float qt[4][2] = {
+static const float qt[4][2] = {
     {-DIMTP, -DIMTP},
     {DIMTP, -DIMTP},
     {DIMTP, DIMTP},
@@ -321,6 +295,11 @@ typedef struct {
     float v;                   /* observer velocity */
     float alpha;               /* observer angles */
     float beta;
+
+    trackball_state *trackball;
+    Bool button_down_p;
+    int frame;
+
 } firestruct;
 
 /* array of firestruct indexed by screen number */
@@ -369,7 +348,8 @@ static float vrnd(void)
 /* initialise new fire particle */
 static void setnewpart(firestruct * fs, part * p)
 {
-    float a, vi[3], *c;
+    float a, vi[3];
+    const float *c;
 
     p->age = 0;
 
@@ -480,8 +460,9 @@ static void setpartrain(firestruct * fs, rain * r, float dt)
 }
 
 /* draw a tree */
-static void drawtree(float x, float y, float z)
+static int drawtree(float x, float y, float z)
 {
+    int polys = 0;
     glBegin(GL_QUADS);
     glTexCoord2f(0.0,0.0);
     glVertex3f(x-1.5,y+0.0,z);
@@ -494,6 +475,7 @@ static void drawtree(float x, float y, float z)
 
     glTexCoord2f(0.0,1.0);
     glVertex3f(x-1.5,y+3.0,z);
+    polys++;
 
 
     glTexCoord2f(0.0,0.0);
@@ -507,9 +489,11 @@ static void drawtree(float x, float y, float z)
 
     glTexCoord2f(0.0,1.0);
     glVertex3f(x,y+3.0,z-1.5);
+    polys++;
 
     glEnd();
 
+    return polys;
 }
 
 /* calculate observer position : modified only if trackmouse is used */
@@ -531,44 +515,6 @@ static void calcposobs(firestruct * fs)
     }
 }
 
-/* track the mouse in a joystick manner : not perfect but it works */
-static void trackmouse(ModeInfo * mi)
-{
-    firestruct *fs = &fire[MI_SCREEN(mi)];
-    /* we keep static values (not per screen) for the mouse stuff: in general you have only one mouse :-> */
-    static int max[2] = { 0, 0 };
-    static int min[2] = { 0x7fffffff, 0x7fffffff }, center[2];
-    Window r, c;
-    int rx, ry, cx, cy;
-    unsigned int m;
-
-    (void) XQueryPointer(MI_DISPLAY(mi), MI_WINDOW(mi),
-                        &r, &c, &rx, &ry, &cx, &cy, &m);
-
-    if (max[0] < cx)
-       max[0] = cx;
-    if (min[0] > cx)
-       min[0] = cx;
-    center[0] = (max[0] + min[0]) / 2;
-
-    if (max[1] < cy)
-       max[1] = cy;
-    if (min[1] > cy)
-       min[1] = cy;
-    center[1] = (max[1] + min[1]) / 2;
-
-    if (fabs(center[0] - (float) cx) > 0.1 * (max[0] - min[0]))
-       fs->alpha += 2.5 * (center[0] - (float) cx) / (max[0] - min[0]);
-    if (fabs(center[1] - (float) cy) > 0.1 * (max[1] - min[1]))
-       fs->beta += 2.5 * (center[1] - (float) cy) / (max[1] - min[1]);
-
-    /* oops: can't get those buttons */
-    if (m & Button4Mask)
-       fs->v += 0.01;
-    if (m & Button5Mask)
-       fs->v -= 0.01;
-
-}
 
 /* initialise textures */
 static void inittextures(ModeInfo * mi)
@@ -583,8 +529,10 @@ static void inittextures(ModeInfo * mi)
        glBindTexture(GL_TEXTURE_2D, fs->groundid);
 #endif /* HAVE_GLBINDTEXTURE */
 
-        if ((fs->gtexture = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
-                        MI_COLORMAP(mi), ground)) == None) {
+        if ((fs->gtexture = image_data_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
+                                                 ground_png,
+                                                 sizeof(ground_png)))
+            == None) {
            (void) fprintf(stderr, "Error reading the ground texture.\n");
            glDeleteTextures(1, &fs->groundid);
             do_texture = False;
@@ -597,10 +545,7 @@ static void inittextures(ModeInfo * mi)
     clear_gl_error();
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                  fs->gtexture->width, fs->gtexture->height, 0,
-                 GL_RGBA,
-                 /* GL_UNSIGNED_BYTE, */
-                 GL_UNSIGNED_INT_8_8_8_8_REV,
-                 fs->gtexture->data);
+                 GL_RGBA, GL_UNSIGNED_BYTE, fs->gtexture->data);
     check_gl_error("texture");
 
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
@@ -617,8 +562,11 @@ static void inittextures(ModeInfo * mi)
 #ifdef HAVE_GLBINDTEXTURE
            glBindTexture(GL_TEXTURE_2D,fs->treeid);
 #endif /* HAVE_GLBINDTEXTURE */
-            if ((fs->ttexture = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
-                        MI_COLORMAP(mi), tree)) == None) {
+            if ((fs->ttexture = image_data_to_ximage(MI_DISPLAY(mi),
+                                                     MI_VISUAL(mi),
+                                                     tree_png,
+                                                     sizeof(tree_png)))
+                == None) {
              (void)fprintf(stderr,"Error reading tree texture.\n");
              glDeleteTextures(1, &fs->treeid);
              fs->treeid    = 0;
@@ -629,10 +577,7 @@ static void inittextures(ModeInfo * mi)
         clear_gl_error();
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                      fs->ttexture->width, fs->ttexture->height, 0,
-                     GL_RGBA,
-                     /* GL_UNSIGNED_BYTE, */
-                     GL_UNSIGNED_INT_8_8_8_8_REV,
-                     fs->ttexture->data);
+                     GL_RGBA, GL_UNSIGNED_BYTE, fs->ttexture->data);
         check_gl_error("texture");
 
            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
@@ -669,13 +614,15 @@ static Bool inittree(ModeInfo * mi)
                return False;
     }
     /* initialise positions */
-    for(i=0;i<fs->num_trees;i++)
-       do {
-           fs->treepos[i].x =vrnd()*TREEOUTR*2.0-TREEOUTR;
-           fs->treepos[i].y =0.0;
-           fs->treepos[i].z =vrnd()*TREEOUTR*2.0-TREEOUTR;
-           dist=sqrt(fs->treepos[i].x *fs->treepos[i].x +fs->treepos[i].z *fs->treepos[i].z );
-        } while((dist<TREEINR) || (dist>TREEOUTR));
+    for(i=0;i<fs->num_trees;i++) {
+      do {
+        fs->treepos[i].x =vrnd()*TREEOUTR*2.0-TREEOUTR;
+        fs->treepos[i].y =0.0;
+        fs->treepos[i].z =vrnd()*TREEOUTR*2.0-TREEOUTR;
+        dist = sqrt(fs->treepos[i].x * fs->treepos[i].x +
+                    fs->treepos[i].z * fs->treepos[i].z);
+      } while((dist<TREEINR) || (dist>TREEOUTR));
+    }
        return True;
 }
 
@@ -687,11 +634,7 @@ static Bool inittree(ModeInfo * mi)
  *-----------------------------------------------------------------------------
  */
 
-#ifndef STANDALONE
-static void Reshape(ModeInfo * mi)
-#else
-void reshape_fire(ModeInfo * mi, int width, int height)
-#endif
+ENTRYPOINT void reshape_fire(ModeInfo * mi, int width, int height)
 {
 
     firestruct *fs = &fire[MI_SCREEN(mi)];
@@ -723,20 +666,19 @@ static void DrawFire(ModeInfo * mi)
     firestruct *fs = &fire[MI_SCREEN(mi)];
     Bool wire = MI_IS_WIREFRAME(mi);
 
-    if (do_trackmouse && !MI_IS_ICONIC(mi))
-       trackmouse(mi);
+    mi->polygon_count = 0;
 
-    if (do_wander)
+    if (do_wander && !fs->button_down_p)
     {
        GLfloat x, y, z;
 
 #       define SINOID(SCALE,SIZE) \
-        ((((1 + sin((frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
+        ((((1 + sin((fs->frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
 
         x = SINOID(0.031, 0.85);
         y = SINOID(0.017, 0.25);
         z = SINOID(0.023, 0.85);
-        frame++;
+        fs->frame++;
         fs->obs[0] = x + DEF_OBS[0];
         fs->obs[1] = y + DEF_OBS[1];
         fs->obs[2] = z + DEF_OBS[2];
@@ -756,11 +698,16 @@ static void DrawFire(ModeInfo * mi)
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
     glPushMatrix();
+
     calcposobs(fs);
-    gluLookAt(fs->obs[0], fs->obs[1], fs->obs[2],
-             fs->obs[0] + fs->dir[0], fs->obs[1] + fs->dir[1],
-             fs->obs[2] + fs->dir[2], 0.0, 1.0, 0.0);
 
+    gltrackball_rotate (fs->trackball);
+
+    gluLookAt(fs->obs[0], fs->obs[1], fs->obs[2],
+              fs->obs[0] + fs->dir[0], 
+              fs->obs[1] + fs->dir[1],
+              fs->obs[2] + fs->dir[2],
+              0.0, 1.0, 0.0);
 
     glEnable(GL_TEXTURE_2D);
 
@@ -782,6 +729,7 @@ static void DrawFire(ModeInfo * mi)
     glVertex3fv(q[2]);
     glTexCoord2fv(qt[3]);
     glVertex3fv(q[3]);
+    mi->polygon_count++;
     glEnd();
 
     glAlphaFunc(GL_GEQUAL, 0.9);
@@ -793,7 +741,7 @@ static void DrawFire(ModeInfo * mi)
        glBindTexture(GL_TEXTURE_2D,fs->treeid);
 #endif /* HAVE_GLBINDTEXTURE */
        for(j=0;j<fs->num_trees;j++)
-           drawtree(fs->treepos[j].x ,fs->treepos[j].y ,fs->treepos[j].z );
+      mi->polygon_count += drawtree(fs->treepos[j].x ,fs->treepos[j].y ,fs->treepos[j].z );
        glDisable(GL_ALPHA_TEST);
     }
     glDisable(GL_TEXTURE_2D);
@@ -811,6 +759,7 @@ static void DrawFire(ModeInfo * mi)
 
            glColor4f(black[0], black[1], black[2], fs->p[j].c[2][3]);
            glVertex3f(fs->p[j].p[2][0], 0.1, fs->p[j].p[2][2]);
+        mi->polygon_count++;
        }
        glEnd();
     }
@@ -826,6 +775,7 @@ static void DrawFire(ModeInfo * mi)
 
        glColor4fv(fs->p[j].c[2]);
        glVertex3fv(fs->p[j].p[2]);
+    mi->polygon_count++;
 
        setpart(fs, &fs->p[j]);
     }
@@ -844,6 +794,7 @@ static void DrawFire(ModeInfo * mi)
            glColor4f(0.3f,0.7f,1.0f,1.0f);
            glVertex3fv(fs->r[j].pos);
            setpartrain(fs, &fs->r[j],timeused);
+        mi->polygon_count++;
        }
        glEnd();
        glShadeModel(GL_FLAT);
@@ -897,23 +848,6 @@ static Bool Init(ModeInfo * mi)
                       fs->eject_r, fs->ridtri);
     }
 
-    glShadeModel(GL_FLAT);
-    glEnable(GL_DEPTH_TEST);
-
-    /* makes particles blend with background */
-    if (!MI_IS_WIREFRAME(mi)||(!fs->np))
-    {
-       glEnable(GL_BLEND);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    }
-
-    /* fog stuff */
-    glEnable(GL_FOG);
-    glFogi(GL_FOG_MODE, GL_EXP);
-    glFogfv(GL_FOG_COLOR, fogcolor);
-    glFogf(GL_FOG_DENSITY, 0.03);
-    glHint(GL_FOG_HINT, GL_NICEST);
-
     /* initialise particles and trees */
     for (i = 0; i < fs->np; i++) {
        setnewpart(fs, &(fs->p[i]));
@@ -946,9 +880,11 @@ static Bool Init(ModeInfo * mi)
  */
 
 
-static void
-free_fire(firestruct *fs)
+ENTRYPOINT void
+free_fire(ModeInfo * mi)
 {
+       firestruct *fs = &fire[MI_SCREEN(mi)];
+
        if (mode_font != None && fs->fontbase != None) {
                glDeleteLists(fs->fontbase, mode_font->max_char_or_byte2 -
                        mode_font->min_char_or_byte2 + 1);
@@ -985,19 +921,12 @@ free_fire(firestruct *fs)
  *-----------------------------------------------------------------------------
  */
 
-void
+ENTRYPOINT void
 init_fire(ModeInfo * mi)
 {
     firestruct *fs;
 
-    /* allocate the main fire table if needed */
-    if (fire == NULL) {
-       if ((fire = (firestruct *) calloc(MI_NUM_SCREENS(mi),
-                                         sizeof(firestruct))) == NULL)
-           return;
-    }
-
-    /* initialise the per screen fire structure */
+    MI_INIT (mi, fire);
     fs = &fire[MI_SCREEN(mi)];
     fs->np = MI_COUNT(mi);
     fs->fog = do_fog;
@@ -1005,14 +934,14 @@ init_fire(ModeInfo * mi)
     /* initialise fire particles if any */
     if ((fs->np)&&(fs->p == NULL)) {
        if ((fs->p = (part *) calloc(fs->np, sizeof(part))) == NULL) {
-           free_fire(fs);
+           free_fire(mi);
            return;
        }
     }
     else if (fs->r == NULL) {
         /* initialise rain particles if no fire particles */
        if ((fs->r = (rain *) calloc(NUMPART, sizeof(part))) == NULL) {
-           free_fire(fs);
+           free_fire(mi);
            return;
        }
     }
@@ -1023,8 +952,7 @@ init_fire(ModeInfo * mi)
     else
        fs->num_trees = 0;
 
-    /* check wander/trackmouse */
-    if (do_trackmouse && do_wander) do_wander = 0;
+    fs->trackball = gltrackball_init (False);
 
     /* xlock GL stuff */
     if ((fs->glx_context = init_GL(mi)) != NULL) {
@@ -1036,7 +964,7 @@ init_fire(ModeInfo * mi)
 #endif
        glDrawBuffer(GL_BACK);
        if (!Init(mi)) {
-               free_fire(fs);
+               free_fire(mi);
                return;
        }
     } else {
@@ -1049,7 +977,7 @@ init_fire(ModeInfo * mi)
  *    Called by the mainline code periodically to update the display.
  *-----------------------------------------------------------------------------
  */
-void draw_fire(ModeInfo * mi)
+ENTRYPOINT void draw_fire(ModeInfo * mi)
 {
     firestruct *fs = &fire[MI_SCREEN(mi)];
 
@@ -1062,7 +990,28 @@ void draw_fire(ModeInfo * mi)
        return;
 
     glXMakeCurrent(display, window, *(fs->glx_context));
+
+    glShadeModel(GL_FLAT);
+    glEnable(GL_DEPTH_TEST);
+
+    /* makes particles blend with background */
+    if (!MI_IS_WIREFRAME(mi)||(!fs->np))
+    {
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    }
+
+    /* fog stuff */
+    glEnable(GL_FOG);
+    glFogi(GL_FOG_MODE, GL_EXP);
+    glFogfv(GL_FOG_COLOR, fogcolor);
+    glFogf(GL_FOG_DENSITY, 0.03);
+    glHint(GL_FOG_HINT, GL_NICEST);
+
+    glPushMatrix();
+    glRotatef(current_device_rotation(), 0, 0, 1);
     DrawFire(mi);
+    glPopMatrix();
 #ifndef STANDALONE
     Reshape(mi); /* xlock mode */
 #else
@@ -1082,15 +1031,8 @@ void draw_fire(ModeInfo * mi)
  *-----------------------------------------------------------------------------
  */
 
-void release_fire(ModeInfo * mi)
+ENTRYPOINT void release_fire(ModeInfo * mi)
 {
-    if (fire != NULL) {
-    int screen;
-       for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-               free_fire(&fire[screen]);
-       (void) free((void *) fire);
-       fire = (firestruct *) NULL;
-    }
     if (mode_font != None)
     {
        /* only free-ed when there are no more screens used */
@@ -1100,7 +1042,22 @@ void release_fire(ModeInfo * mi)
     FreeAllGL(mi);
 }
 
-void change_fire(ModeInfo * mi)
+ENTRYPOINT Bool
+fire_handle_event (ModeInfo *mi, XEvent *event)
+{
+  firestruct *fs = &fire[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, fs->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &fs->button_down_p))
+    return True;
+
+  return False;
+}
+
+
+#ifndef STANDALONE
+ENTRYPOINT void change_fire(ModeInfo * mi)
 {
     firestruct *fs = &fire[MI_SCREEN(mi)];
 
@@ -1133,4 +1090,8 @@ void change_fire(ModeInfo * mi)
                       fs->eject_r, fs->ridtri);
     }
 }
+#endif /* !STANDALONE */
+
+XSCREENSAVER_MODULE_2 ("GLForestFire", glforestfire, fire)
+
 #endif /* MODE_fire */