updated URL of forum and table in readme file
[neverball] / share / mapc.c
index 4283932..06eaedc 100644 (file)
@@ -1,4 +1,4 @@
-/*   
+/*
  * Copyright (C) 2003 Robert Kooima
  *
  * NEVERBALL is  free software; you can redistribute  it and/or modify
@@ -33,7 +33,6 @@
 #include <math.h>
 
 #include "vec3.h"
-#include "glext.h"
 #include "solid.h"
 #include "base_config.h"
 
 
 /* Ohhhh... arbitrary! */
 
-#define MAXM   256
+#define MAXM    256
 #define MAXV    32767
-#define MAXE   32767
-#define MAXS   32767
-#define MAXT   32767
-#define MAXG   32767
-#define MAXL   1024
-#define MAXN   1024
-#define MAXP   512
-#define MAXB   512
-#define MAXC   1024
+#define MAXE    32767
+#define MAXS    32767
+#define MAXT    32767
+#define MAXG    32767
+#define MAXL    1024
+#define MAXN    1024
+#define MAXP    512
+#define MAXB    512
+#define MAXH    1024
 #define MAXZ    16
-#define MAXJ   32
-#define MAXX   16
-#define MAXR   1024
-#define MAXU   16
+#define MAXJ    32
+#define MAXX    16
+#define MAXR    1024
+#define MAXU    16
 #define MAXW    32
 #define MAXD    128
-#define MAXA   8192
-#define MAXI   32767
+#define MAXA    8192
+#define MAXI    32767
 
 static int overflow(const char *s)
 {
@@ -132,9 +131,9 @@ static int incb(struct s_file *fp)
     return (fp->bc < MAXB) ? fp->bc++ : overflow("body");
 }
 
-static int incc(struct s_file *fp)
+static int inch(struct s_file *fp)
 {
-    return (fp->cc < MAXC) ? fp->cc++ : overflow("coin");
+    return (fp->hc < MAXH) ? fp->hc++ : overflow("item");
 }
 
 static int incz(struct s_file *fp)
@@ -184,7 +183,7 @@ static void init_file(struct s_file *fp)
     fp->nc = 0;
     fp->pc = 0;
     fp->bc = 0;
-    fp->cc = 0;
+    fp->hc = 0;
     fp->zc = 0;
     fp->jc = 0;
     fp->xc = 0;
@@ -204,7 +203,7 @@ static void init_file(struct s_file *fp)
     fp->nv = (struct s_node *) calloc(MAXN, sizeof (struct s_node));
     fp->pv = (struct s_path *) calloc(MAXP, sizeof (struct s_path));
     fp->bv = (struct s_body *) calloc(MAXB, sizeof (struct s_body));
-    fp->cv = (struct s_coin *) calloc(MAXC, sizeof (struct s_coin));
+    fp->hv = (struct s_item *) calloc(MAXH, sizeof (struct s_item));
     fp->zv = (struct s_goal *) calloc(MAXZ, sizeof (struct s_goal));
     fp->jv = (struct s_jump *) calloc(MAXJ, sizeof (struct s_jump));
     fp->xv = (struct s_swch *) calloc(MAXX, sizeof (struct s_swch));
@@ -295,10 +294,31 @@ static void targets(struct s_file *fp)
  * regardless of the number of surfaces refering to it.
  */
 
-static char *image_s[MAXM];
-static int   image_w[MAXM];
-static int   image_h[MAXM];
-static int   image_n;
+struct _imagedata
+{
+    char *s;
+    int w, h;
+};
+
+static struct _imagedata *imagedata = NULL;
+static int image_n = 0;
+static int image_alloc = 0;
+
+#define IMAGE_REALLOC 32
+
+static void free_imagedata()
+{
+    int i;
+
+    if (imagedata)
+    {
+        for (i = 0; i < image_n; i++)
+            free(imagedata[i].s);
+        free(imagedata);
+    }
+
+    image_n = image_alloc = 0;
+}
 
 static int size_load(const char *file, int *w, int *h)
 {
@@ -323,14 +343,15 @@ static void size_image(const char *name, int *w, int *h)
     char png[MAXSTR];
     int i;
 
-    for (i = 0; i < image_n; i++)
-        if (strncmp(image_s[i], name, MAXSTR) == 0)
-        {
-            *w = image_w[i];
-            *h = image_h[i];
+    if (imagedata)
+        for (i = 0; i < image_n; i++)
+            if (strncmp(imagedata[i].s, name, MAXSTR) == 0)
+            {
+                *w = imagedata[i].w;
+                *h = imagedata[i].h;
 
-            return;
-        }
+                return;
+            }
 
     *w = 0;
     *h = 0;
@@ -343,11 +364,30 @@ static void size_image(const char *name, int *w, int *h)
         size_load(config_data(tga), w, h) ||
         size_load(config_data(jpg), w, h))
     {
-        image_s[image_n] = (char *) calloc(strlen(name) + 1, 1);
-        image_w[image_n] = *w;
-        image_h[image_n] = *h;
 
-        strcpy(image_s[image_n], name);
+        if (image_n + 1 >= image_alloc)
+        {
+            struct _imagedata *tmp =
+                (struct _imagedata *) malloc(sizeof(struct _imagedata) * (image_alloc + IMAGE_REALLOC));
+            if (!tmp)
+            {
+                printf("malloc error\n");
+                exit(1);
+            }
+            if (imagedata)
+            {
+                (void) memcpy(tmp, imagedata, sizeof(struct _imagedata) * image_alloc);
+                free(imagedata);
+            }
+            imagedata = tmp;
+            image_alloc += IMAGE_REALLOC;
+        }
+
+        imagedata[image_n].s = (char *) calloc(strlen(name) + 1, 1);
+        imagedata[image_n].w = *w;
+        imagedata[image_n].h = *h;
+        strcpy(imagedata[image_n].s, name);
+
         image_n++;
     }
 }
@@ -498,7 +538,7 @@ static void read_f(struct s_file *fp, const char *line,
     gp->si += (s0 - 1);
     gp->sj += (s0 - 1);
     gp->sk += (s0 - 1);
-    
+
     gp->mi  = mi;
 }
 
@@ -590,7 +630,7 @@ static void make_plane(int pi, int x0, int y0, int z0,
 
     v_crs(plane_n[pi], u, v);
     v_nrm(plane_n[pi], plane_n[pi]);
-       
+
     plane_d[pi] = v_dot(plane_n[pi], p1);
 
     for (i = 0; i < 6; i++)
@@ -790,22 +830,22 @@ static void make_body(struct s_file *fp,
         if (strcmp(k[i], "targetname") == 0)
             make_sym(v[i], bi);
 
-       else if (strcmp(k[i], "target") == 0)
+        else if (strcmp(k[i], "target") == 0)
             make_ref(v[i], &bp->pi);
 
-       else if (strcmp(k[i], "model") == 0)
+        else if (strcmp(k[i], "model") == 0)
             read_obj(fp, v[i]);
 
-       else if (strcmp(k[i], "origin") == 0)
+        else if (strcmp(k[i], "origin") == 0)
             sscanf(v[i], "%d %d %d", &x, &y, &z);
 
-       else if (strcmp(k[i], "classname") != 0)
+        else if (strcmp(k[i], "classname") != 0)
         {
-           /* Considers other strings as metadata */
+            /* Considers other strings as metadata */
             strcat(fp->av, k[i]);
             strcat(fp->av, "=");
             strcat(fp->av, v[i]);
-           strcat(fp->av, "\n");
+            strcat(fp->av, "\n");
             fp->ac += (int) (strlen(v[i]) + (strlen(k[i])) + 2);
         }
     }
@@ -826,23 +866,35 @@ static void make_body(struct s_file *fp,
         v_add(fp->vv[i].p, fp->vv[i].p, p);
 }
 
-static void make_coin(struct s_file *fp,
+static void make_item(struct s_file *fp,
                       char k[][MAXSTR],
                       char v[][MAXSTR], int c)
 {
-    int i, ci = incc(fp);
+    int i, hi = inch(fp);
+
+    struct s_item *hp = fp->hv + hi;
 
-    struct s_coin *cp = fp->cv + ci;
+    hp->p[0] = 0.f;
+    hp->p[1] = 0.f;
+    hp->p[2] = 0.f;
 
-    cp->p[0] = 0.f;
-    cp->p[1] = 0.f;
-    cp->p[2] = 0.f;
-    cp->n    = 1;
+    hp->t = ITEM_NONE;
+    hp->n = 0;
 
     for (i = 0; i < c; i++)
     {
+        if (strcmp(k[i], "classname") == 0)
+        {
+            if (strcmp(v[i], "light") == 0)
+                hp->t = ITEM_COIN;
+            else if (strcmp(v[i], "item_health_large") == 0)
+                hp->t = ITEM_GROW;
+            else if (strcmp(v[i], "item_health_small") == 0)
+                hp->t = ITEM_SHRINK;
+        }
+
         if (strcmp(k[i], "light") == 0)
-            sscanf(v[i], "%d", &cp->n);
+            sscanf(v[i], "%d", &hp->n);
 
         if (strcmp(k[i], "origin") == 0)
         {
@@ -850,9 +902,9 @@ static void make_coin(struct s_file *fp,
 
             sscanf(v[i], "%d %d %d", &x, &y, &z);
 
-            cp->p[0] = +(float) x / SCALE;
-            cp->p[1] = +(float) z / SCALE;
-            cp->p[2] = -(float) y / SCALE;
+            hp->p[0] = +(float) x / SCALE;
+            hp->p[1] = +(float) z / SCALE;
+            hp->p[2] = -(float) y / SCALE;
         }
     }
 }
@@ -928,11 +980,17 @@ static void make_goal(struct s_file *fp,
     zp->p[1] = 0.f;
     zp->p[2] = 0.f;
     zp->r    = 0.75;
+    zp->s    = 0;
+    zp->c    = 0;
 
     for (i = 0; i < c; i++)
     {
         if (strcmp(k[i], "radius") == 0)
             sscanf(v[i], "%f", &zp->r);
+        if (strcmp(k[i], "skip") == 0)
+            sscanf(v[i], "%d", &zp->s);
+        if (strcmp(k[i], "special") == 0)
+            sscanf(v[i], "%d", &zp->c);
 
         if (strcmp(k[i], "origin") == 0)
         {
@@ -1034,6 +1092,7 @@ static void make_swch(struct s_file *fp,
     xp->t    = 0;
     xp->f0   = 0;
     xp->f    = 0;
+    xp->i    = 0;
 
     for (i = 0; i < c; i++)
     {
@@ -1049,6 +1108,9 @@ static void make_swch(struct s_file *fp,
         if (strcmp(k[i], "state") == 0)
             xp->f = atoi(v[i]);
 
+        if (strcmp(k[i], "invisible") == 0)
+            xp->i = atoi(v[i]);
+
         if (strcmp(k[i], "origin") == 0)
         {
             int x = 0, y = 0, z = 0;
@@ -1164,7 +1226,9 @@ static void read_ent(struct s_file *fp, FILE *fin)
         if (t == T_END) break;
     }
 
-    if (!strcmp(v[i], "light"))                    make_coin(fp, k, v, c);
+    if (!strcmp(v[i], "light"))                    make_item(fp, k, v, c);
+    if (!strcmp(v[i], "item_health_large"))        make_item(fp, k, v, c);
+    if (!strcmp(v[i], "item_health_small"))        make_item(fp, k, v, c);
     if (!strcmp(v[i], "info_camp"))                make_swch(fp, k, v, c);
     if (!strcmp(v[i], "info_null"))                make_bill(fp, k, v, c);
     if (!strcmp(v[i], "path_corner"))              make_path(fp, k, v, c);
@@ -1259,7 +1323,7 @@ static void clip_vert(struct s_file *fp,
 
     m_basis(M, fp->sv[si].n, fp->sv[sj].n, fp->sv[sk].n);
     m_xps(X, M);
-       
+
     if (m_inv(I, X))
     {
         m_vxfm(p, I, d);
@@ -1945,7 +2009,7 @@ static int node_node(struct s_file *fp, int l0, int lc)
             }
 
         /* Sort all lumps in the range by their flag values. */
-        
+
         for (li = 1; li < lc; li++)
             for (lj = 0; lj < li; lj++)
                 if (fp->lv[l0 + li].fl < fp->lv[l0 + lj].fl)
@@ -2000,10 +2064,20 @@ static void node_file(struct s_file *fp)
 
 static void dump_file(struct s_file *p, const char *name)
 {
+    /* FIXME:  Count visible geoms.
+     *
+     * I'm afraid items break this (not sure though) so leaving it out.
+     */
+
+#if 0
     int i, j;
+#endif
+    int i;
     int c = 0;
     int n = 0;
+#if 0
     int m = p->rc + p->cc * 128 + (p->zc * p->jc + p->xc) * 32;
+#endif
 
     /* Count the number of solid lumps. */
 
@@ -2011,6 +2085,7 @@ static void dump_file(struct s_file *p, const char *name)
         if ((p->lv[i].fl & 1) == 0)
             n++;
 
+#if 0
     /* Count the number of visible geoms. */
 
     for (i = 0; i < p->bc; i++)
@@ -2019,26 +2094,39 @@ static void dump_file(struct s_file *p, const char *name)
             m += p->lv[p->bv[i].l0 + j].gc;
         m += p->bv[i].gc;
     }
+#endif
 
     /* Count the total value of all coins. */
 
-    for (i = 0; i < p->cc; i++)
-        c += p->cv[i].n;
+    for (i = 0; i < p->hc; i++)
+        if (p->hv[i].t == ITEM_COIN)
+            c += p->hv[i].n;
 
+#if 0
     printf("%s (%d/%d/$%d)\n"
+#endif
+    printf("%s (%d/$%d)\n"
            "  mtrl  vert  edge  side  texc"
            "  geom  lump  path  node  body\n"
            "%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d\n"
-           "  coin  goal  view  jump  swch"
+           "  item  goal  view  jump  swch"
            "  bill  ball  char  indx\n"
            "%6d%6d%6d%6d%6d%6d%6d%6d%6d\n",
+#if 0
            name, n, m, c,
+#endif
+           name, n, c,
            p->mc, p->vc, p->ec, p->sc, p->tc,
            p->gc, p->lc, p->pc, p->nc, p->bc,
-           p->cc, p->zc, p->wc, p->jc, p->xc,
+           p->hc, p->zc, p->wc, p->jc, p->xc,
            p->rc, p->uc, p->ac, p->ic);
 }
 
+/* Skip the ugly SDL main substitution since we only need sdl_image. */
+#ifdef main
+#    undef main
+#endif
+
 int main(int argc, char *argv[])
 {
     char src[MAXSTR];
@@ -2076,6 +2164,8 @@ int main(int argc, char *argv[])
                 sol_stor(&f, dst);
 
                 fclose(fin);
+
+                free_imagedata();
             }
         }
         else fprintf(stderr, "Failure to establish data directory\n");