]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/qdata/images.c
uncrustify! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / tools / quake2 / qdata / images.c
index e3b8fc1b697a2e09c9d6a4c314cff89a9d21e1fc..00f30e05701dd2389ed641576cb42f04d1e19c23 100644 (file)
-#include "qdata.h"\r
-#include "inout.h"\r
-\r
-char           mip_prefix[1024];               // directory to dump the textures in\r
-\r
-qboolean       colormap_issued;\r
-byte           colormap_palette[768];\r
-\r
-/*\r
-==============\r
-RemapZero\r
-\r
-Replaces all 0 bytes in an image with the closest palette entry.\r
-This is because NT won't let us change index 0, so any palette\r
-animation leaves those pixels untouched.\r
-==============\r
-*/\r
-void RemapZero (byte *pixels, byte *palette, int width, int height)\r
-{\r
-       int             i, c;\r
-       int             alt_zero;\r
-       int             value, best;\r
-\r
-       alt_zero = 0;\r
-       best = 9999999;\r
-       for (i=1 ; i<255 ; i++)\r
-       {\r
-               value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];\r
-               if (value < best)\r
-               {\r
-                       best = value;\r
-                       alt_zero = i;\r
-               }\r
-       }\r
-\r
-       c = width*height;\r
-       for (i=0 ; i<c ; i++)\r
-               if (pixels[i] == 0)\r
-                       pixels[i] = alt_zero;\r
-}\r
-\r
-/*\r
-==============\r
-Cmd_Grab\r
-\r
-$grab filename x y width height\r
-==============\r
-*/\r
-void Cmd_Grab (void)\r
-{\r
-       int             xl,yl,w,h,y;\r
-       byte                    *cropped;\r
-       char                    savename[1024];\r
-       char                    dest[1024];\r
-\r
-       GetToken (false);\r
-\r
-       if (token[0] == '/' || token[0] == '\\')\r
-               sprintf (savename, "%s%s.pcx", gamedir, token+1);\r
-       else\r
-               sprintf (savename, "%spics/%s.pcx", gamedir, token);\r
-\r
-       if (g_release)\r
-       {\r
-               if (token[0] == '/' || token[0] == '\\')\r
-                       sprintf (dest, "%s.pcx", token+1);\r
-               else\r
-                       sprintf (dest, "pics/%s.pcx", token);\r
-\r
-               ReleaseFile (dest);\r
-               return;\r
-       }\r
-\r
-       GetToken (false);\r
-       xl = atoi (token);\r
-       GetToken (false);\r
-       yl = atoi (token);\r
-       GetToken (false);\r
-       w = atoi (token);\r
-       GetToken (false);\r
-       h = atoi (token);\r
-\r
-       if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)\r
-               Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);\r
-\r
-       // crop it to the proper size\r
-       cropped = malloc (w*h);\r
-       for (y=0 ; y<h ; y++)\r
-       {\r
-               memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);\r
-       }\r
-\r
-       // save off the new image\r
-       printf ("saving %s\n", savename);\r
-       CreatePath (savename);\r
-       WritePCXfile (savename, cropped, w,     h, lbmpalette);\r
-\r
-       free (cropped);\r
-}\r
-\r
-/*\r
-==============\r
-Cmd_Raw\r
-\r
-$grab filename x y width height\r
-==============\r
-*/\r
-void Cmd_Raw (void)\r
-{\r
-       int             xl,yl,w,h,y;\r
-       byte                    *cropped;\r
-       char                    savename[1024];\r
-       char                    dest[1024];\r
-\r
-       GetToken (false);\r
-\r
-       sprintf (savename, "%s%s.lmp", gamedir, token);\r
-\r
-       if (g_release)\r
-       {\r
-               sprintf (dest, "%s.lmp", token);\r
-               ReleaseFile (dest);\r
-               return;\r
-       }\r
-\r
-       GetToken (false);\r
-       xl = atoi (token);\r
-       GetToken (false);\r
-       yl = atoi (token);\r
-       GetToken (false);\r
-       w = atoi (token);\r
-       GetToken (false);\r
-       h = atoi (token);\r
-\r
-       if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)\r
-               Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);\r
-\r
-       // crop it to the proper size\r
-       cropped = malloc (w*h);\r
-       for (y=0 ; y<h ; y++)\r
-       {\r
-               memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);\r
-       }\r
-\r
-       // save off the new image\r
-       printf ("saving %s\n", savename);\r
-       CreatePath (savename);\r
-\r
-       SaveFile (savename, cropped, w*h);\r
-\r
-       free (cropped);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
-COLORMAP GRABBING\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-===============\r
-BestColor\r
-===============\r
-*/\r
-byte BestColor (int r, int g, int b, int start, int stop)\r
-{\r
-       int     i;\r
-       int     dr, dg, db;\r
-       int     bestdistortion, distortion;\r
-       int     bestcolor;\r
-       byte    *pal;\r
-\r
-//\r
-// let any color go to 0 as a last resort\r
-//\r
-       bestdistortion = 256*256*4;\r
-       bestcolor = 0;\r
-\r
-       pal = colormap_palette + start*3;\r
-       for (i=start ; i<= stop ; i++)\r
-       {\r
-               dr = r - (int)pal[0];\r
-               dg = g - (int)pal[1];\r
-               db = b - (int)pal[2];\r
-               pal += 3;\r
-               distortion = dr*dr + dg*dg + db*db;\r
-               if (distortion < bestdistortion)\r
-               {\r
-                       if (!distortion)\r
-                               return i;               // perfect match\r
-\r
-                       bestdistortion = distortion;\r
-                       bestcolor = i;\r
-               }\r
-       }\r
-\r
-       return bestcolor;\r
-}\r
-\r
-\r
-/*\r
-==============\r
-Cmd_Colormap\r
-\r
-$colormap filename\r
-\r
-  the brightes colormap is first in the table (FIXME: reverse this now?)\r
-\r
-  64 rows of 256 : lightmaps\r
-  256 rows of 256 : translucency table\r
-==============\r
-*/\r
-void Cmd_Colormap (void)\r
-{\r
-       int             levels, brights;\r
-       int             l, c;\r
-       float   frac, red, green, blue;\r
-       float   range;\r
-       byte    *cropped, *lump_p;\r
-       char    savename[1024];\r
-       char    dest[1024];\r
-\r
-       colormap_issued = true;\r
-       if (!g_release)\r
-               memcpy (colormap_palette, lbmpalette, 768);\r
-\r
-       if (!TokenAvailable ())\r
-       {       // just setting colormap_issued\r
-               return;\r
-       }\r
-\r
-       GetToken (false);\r
-       sprintf (savename, "%spics/%s.pcx", gamedir, token);\r
-\r
-       if (g_release)\r
-       {\r
-               sprintf (dest, "pics/%s.pcx", token);\r
-               ReleaseFile (dest);\r
-               return;\r
-       }\r
-\r
-       range = 2;\r
-       levels = 64;\r
-       brights = 1;    // ignore 255 (transparent)\r
-\r
-       cropped = malloc((levels+256)*256);\r
-       lump_p = cropped;\r
-\r
-// shaded levels\r
-       for (l=0;l<levels;l++)\r
-       {\r
-               frac = range - range*(float)l/(levels-1);\r
-               for (c=0 ; c<256-brights ; c++)\r
-               {\r
-                       red = lbmpalette[c*3];\r
-                       green = lbmpalette[c*3+1];\r
-                       blue = lbmpalette[c*3+2];\r
-\r
-                       red = (int)(red*frac+0.5);\r
-                       green = (int)(green*frac+0.5);\r
-                       blue = (int)(blue*frac+0.5);\r
-                       \r
-//\r
-// note: 254 instead of 255 because 255 is the transparent color, and we\r
-// don't want anything remapping to that\r
-// don't use color 0, because NT can't remap that (or 255)\r
-//\r
-                       *lump_p++ = BestColor(red,green,blue, 1, 254);\r
-               }\r
-\r
-               // fullbrights allways stay the same\r
-               for ( ; c<256 ; c++)\r
-                       *lump_p++ = c;\r
-       }\r
-       \r
-// 66% transparancy table\r
-       for (l=0;l<255;l++)\r
-       {\r
-               for (c=0 ; c<255 ; c++)\r
-               {\r
-                       red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;\r
-                       green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;\r
-                       blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;\r
-\r
-                       *lump_p++ = BestColor(red,green,blue, 1, 254);\r
-               }\r
-               *lump_p++ = 255;\r
-       }\r
-       for (c=0 ; c<256 ; c++)\r
-               *lump_p++ = 255;\r
-       \r
-       // save off the new image\r
-       printf ("saving %s\n", savename);\r
-       CreatePath (savename);\r
-       WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);\r
-\r
-       free (cropped);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
-MIPTEX GRABBING\r
-\r
-=============================================================================\r
-*/\r
-\r
-byte   pixdata[256];\r
-\r
-int            d_red, d_green, d_blue;\r
-\r
-byte   palmap[32][32][32];\r
-qboolean       palmap_built;\r
-\r
-/*\r
-=============\r
-FindColor\r
-=============\r
-*/\r
-int FindColor (int r, int g, int b)\r
-{\r
-       int             bestcolor;\r
-\r
-       if (r > 255)\r
-               r = 255;\r
-       if (r < 0)\r
-               r = 0;\r
-       if (g > 255)\r
-               g = 255;\r
-       if (g < 0)\r
-               g = 0;\r
-       if (b > 255)\r
-               b = 255;\r
-       if (b < 0)\r
-               b = 0;\r
-#ifndef TABLECOLORS\r
-       bestcolor = BestColor (r, g, b, 0, 254);\r
-#else\r
-       bestcolor = palmap[r>>3][g>>3][b>>3];\r
-#endif\r
-\r
-       return bestcolor;\r
-}\r
-\r
-\r
-void BuildPalmap (void)\r
-{\r
-#ifdef TABLECOLORS\r
-       int             r, g, b;\r
-       int             bestcolor;\r
-\r
-       if (palmap_built)\r
-               return;\r
-       palmap_built = true;\r
-\r
-       for (r=4 ; r<256 ; r+=8)\r
-       {\r
-               for (g=4 ; g<256 ; g+=8)\r
-               {\r
-                       for (b=4 ; b<256 ; b+=8)\r
-                       {\r
-                               bestcolor = BestColor (r, g, b, 1, 254);\r
-                               palmap[r>>3][g>>3][b>>3] = bestcolor;\r
-                       }\r
-               }\r
-       }\r
-#endif\r
-\r
-       if (!colormap_issued)\r
-               Error ("You must issue a $colormap command first");\r
-\r
-}\r
-\r
-/*\r
-=============\r
-AveragePixels\r
-=============\r
-*/\r
-byte AveragePixels (int count)\r
-{\r
-       int             r,g,b;\r
-       int             i;\r
-       int             vis;\r
-       int             pix;\r
-       int             bestcolor;\r
-       byte    *pal;\r
-       int             fullbright;\r
-       \r
-       vis = 0;\r
-       r = g = b = 0;\r
-       fullbright = 0;\r
-       for (i=0 ; i<count ; i++)\r
-       {\r
-               pix = pixdata[i];\r
-               \r
-               r += lbmpalette[pix*3];\r
-               g += lbmpalette[pix*3+1];\r
-               b += lbmpalette[pix*3+2];\r
-               vis++;\r
-       }\r
-               \r
-       r /= vis;\r
-       g /= vis;\r
-       b /= vis;\r
-\r
-       // error diffusion\r
-       r += d_red;\r
-       g += d_green;\r
-       b += d_blue;\r
-       \r
-//\r
-// find the best color\r
-//\r
-       bestcolor = FindColor (r, g, b);\r
-\r
-       // error diffusion\r
-       pal = colormap_palette + bestcolor*3;\r
-       d_red = r - (int)pal[0];\r
-       d_green = g - (int)pal[1];\r
-       d_blue = b - (int)pal[2];\r
-\r
-       return bestcolor;\r
-}\r
-\r
-\r
-typedef enum\r
-{\r
-       pt_contents,\r
-       pt_flags,\r
-       pt_animvalue,\r
-       pt_flagvalue\r
-} parmtype_t;\r
-\r
-typedef struct\r
-{\r
-       char    *name;\r
-       int             flags;\r
-       parmtype_t      type;\r
-} mipparm_t;\r
-\r
-mipparm_t      mipparms[] =\r
-{\r
-       // utility content attributes\r
-       {"water",       CONTENTS_WATER, pt_contents},\r
-       {"slime",       CONTENTS_SLIME, pt_contents},           // mildly damaging\r
-       {"lava",        CONTENTS_LAVA, pt_contents},            // very damaging\r
-       {"window",      CONTENTS_WINDOW, pt_contents},  // solid, but doesn't eat internal textures\r
-       {"mist",        CONTENTS_MIST, pt_contents},    // non-solid window\r
-       {"origin",      CONTENTS_ORIGIN, pt_contents},  // center of rotating brushes\r
-       {"playerclip",  CONTENTS_PLAYERCLIP, pt_contents},\r
-       {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},\r
-\r
-       // utility surface attributes\r
-       {"hint",        SURF_HINT, pt_flags},\r
-       {"skip",        SURF_SKIP, pt_flags},\r
-       {"light",       SURF_LIGHT, pt_flagvalue},              // value is the light quantity\r
-\r
-       // texture chaining\r
-       {"anim",        0,                      pt_animvalue},          // value is the next animation\r
-\r
-       // server attributes\r
-       {"slick",       SURF_SLICK, pt_flags},\r
-\r
-       // drawing attributes\r
-       {"sky",         SURF_SKY, pt_flags},\r
-       {"warping",     SURF_WARP, pt_flags},           // only valid with 64x64 textures\r
-       {"trans33",     SURF_TRANS33, pt_flags},        // translucent should allso set fullbright\r
-       {"trans66",     SURF_TRANS66, pt_flags},\r
-       {"flowing",     SURF_FLOWING, pt_flags},        // flow direction towards angle 0\r
-       {"nodraw",      SURF_NODRAW, pt_flags}, // for clip textures and trigger textures\r
-\r
-       {NULL, 0, pt_contents}\r
-};\r
-\r
-\r
-\r
-/*\r
-==============\r
-Cmd_Mip\r
-\r
-$mip filename x y width height <OPTIONS>\r
-must be multiples of sixteen\r
-SURF_WINDOW\r
-==============\r
-*/\r
-void Cmd_Mip (void)\r
-{\r
-       int             x,y,xl,yl,xh,yh,w,h;\r
-       byte            *screen_p, *source;\r
-       int             linedelta;\r
-       miptex_t                *qtex;\r
-       int                             miplevel, mipstep;\r
-       int                             xx, yy, pix;\r
-       int                             count;\r
-       int                             flags, value, contents;\r
-       mipparm_t               *mp;\r
-       char                    lumpname[64];\r
-       byte                    *lump_p;\r
-       char                    filename[1024];\r
-       char                    animname[64];\r
-\r
-       GetToken (false);\r
-       strcpy (lumpname, token);\r
-       \r
-       GetToken (false);\r
-       xl = atoi (token);\r
-       GetToken (false);\r
-       yl = atoi (token);\r
-       GetToken (false);\r
-       w = atoi (token);\r
-       GetToken (false);\r
-       h = atoi (token);\r
-\r
-       if ( (w & 15) || (h & 15) )\r
-               Error ("line %i: miptex sizes must be multiples of 16", scriptline);\r
-\r
-       flags = 0;\r
-       contents = 0;\r
-       value = 0;\r
-\r
-       animname[0] = 0;\r
-\r
-       // get optional flags and values\r
-       while (TokenAvailable ())\r
-       {\r
-               GetToken (false);\r
-       \r
-               for (mp=mipparms ; mp->name ; mp++)\r
-               {\r
-                       if (!strcmp(mp->name, token))\r
-                       {\r
-                               switch (mp->type)\r
-                               {\r
-                               case pt_animvalue:\r
-                                       GetToken (false);       // specify the next animation frame\r
-                                       strcpy (animname, token);\r
-                                       break;\r
-                               case pt_flags:\r
-                                       flags |= mp->flags;\r
-                                       break;\r
-                               case pt_contents:\r
-                                       contents |= mp->flags;\r
-                                       break;\r
-                               case pt_flagvalue:\r
-                                       flags |= mp->flags;\r
-                                       GetToken (false);       // specify the light value\r
-                                       value = atoi(token);\r
-                                       break;\r
-                               }\r
-                               break;\r
-                       }\r
-               }\r
-               if (!mp->name)\r
-                       Error ("line %i: unknown parm %s", scriptline, token);\r
-       }\r
-\r
-       sprintf (filename, "%stextures/%s/%s.wal", gamedir, mip_prefix, lumpname);\r
-       if (g_release)\r
-               return; // textures are only released by $maps\r
-\r
-       xh = xl+w;\r
-       yh = yl+h;\r
-\r
-       qtex = malloc (sizeof(miptex_t) + w*h*2);\r
-       memset (qtex, 0, sizeof(miptex_t));\r
-\r
-       qtex->width = LittleLong(w);\r
-       qtex->height = LittleLong(h);\r
-       qtex->flags = LittleLong(flags);\r
-       qtex->contents = LittleLong(contents);\r
-       qtex->value = LittleLong(value);\r
-       sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);\r
-       if (animname[0])\r
-               sprintf (qtex->animname, "%s/%s", mip_prefix, animname);\r
-       \r
-       lump_p = (byte *)(&qtex->value+1);\r
-       \r
-       screen_p = byteimage + yl*byteimagewidth + xl;\r
-       linedelta = byteimagewidth - w;\r
-\r
-       source = lump_p;\r
-       qtex->offsets[0] = LittleLong(lump_p - (byte *)qtex);\r
-\r
-       for (y=yl ; y<yh ; y++)\r
-       {\r
-               for (x=xl ; x<xh ; x++)\r
-               {\r
-                       pix = *screen_p++;\r
-                       if (pix == 255)\r
-                               pix = 1;                // should never happen\r
-                       *lump_p++ = pix;\r
-               }\r
-               screen_p += linedelta;\r
-       }\r
-       \r
-//\r
-// subsample for greater mip levels\r
-//\r
-       d_red = d_green = d_blue = 0;   // no distortion yet\r
-\r
-       for (miplevel = 1 ; miplevel<4 ; miplevel++)\r
-       {\r
-               qtex->offsets[miplevel] = LittleLong(lump_p - (byte *)qtex);\r
-               \r
-               mipstep = 1<<miplevel;\r
-               for (y=0 ; y<h ; y+=mipstep)\r
-               {\r
-\r
-                       for (x = 0 ; x<w ; x+= mipstep)\r
-                       {\r
-                               count = 0;\r
-                               for (yy=0 ; yy<mipstep ; yy++)\r
-                                       for (xx=0 ; xx<mipstep ; xx++)\r
-                                       {\r
-                                               pixdata[count] = source[ (y+yy)*w + x + xx ];\r
-                                               count++;\r
-                                       }\r
-                               *lump_p++ = AveragePixels (count);\r
-                       }       \r
-               }\r
-       }\r
-\r
-//\r
-// dword align the size\r
-//\r
-       while ((int)lump_p&3)\r
-               *lump_p++ = 0;\r
-\r
-//\r
-// write it out\r
-//\r
-       printf ("writing %s\n", filename);\r
-       SaveFile (filename, (byte *)qtex, lump_p - (byte *)qtex);\r
-\r
-       free (qtex);\r
-}\r
-\r
-/*\r
-===============\r
-Cmd_Mippal\r
-===============\r
-*/\r
-void Cmd_Mippal (void)\r
-{\r
-       colormap_issued = true;\r
-       if (g_release)\r
-               return;\r
-\r
-       memcpy (colormap_palette, lbmpalette, 768);\r
-\r
-       BuildPalmap();\r
-}\r
-\r
-\r
-/*\r
-===============\r
-Cmd_Mipdir\r
-===============\r
-*/\r
-void Cmd_Mipdir (void)\r
-{\r
-       char    filename[1024];\r
-\r
-       GetToken (false);\r
-       strcpy (mip_prefix, token);\r
-       // create the directory if needed\r
-       sprintf (filename, "%stextures", gamedir, mip_prefix);\r
-       Q_mkdir (filename); \r
-       sprintf (filename, "%stextures/%s", gamedir, mip_prefix);\r
-       Q_mkdir (filename); \r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
-ENVIRONMENT MAP GRABBING\r
-\r
-Creates six pcx files from tga files without any palette edge seams\r
-also copies the tga files for GL rendering.\r
-=============================================================================\r
-*/\r
-\r
-// 3dstudio environment map suffixes\r
-char   *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};\r
-\r
-/*\r
-=================\r
-Cmd_Environment\r
-=================\r
-*/\r
-void Cmd_Environment (void)\r
-{\r
-       char    name[1024];\r
-       int             i, x, y;\r
-       byte    image[256*256];\r
-       byte    *tga;\r
-\r
-       GetToken (false);\r
-\r
-       if (g_release)\r
-       {\r
-               for (i=0 ; i<6 ; i++)\r
-               {\r
-                       sprintf (name, "env/%s%s.pcx", token, suf[i]);\r
-                       ReleaseFile (name);\r
-                       sprintf (name, "env/%s%s.tga", token, suf[i]);\r
-                       ReleaseFile (name);\r
-               }\r
-               return;\r
-       }\r
-       // get the palette\r
-       BuildPalmap ();\r
-\r
-       sprintf (name, "%senv/", gamedir);\r
-       CreatePath (name);\r
-\r
-       // convert the images\r
-       for (i=0 ; i<6 ; i++)\r
-       {\r
-               sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);\r
-               printf ("loading %s...\n", name);\r
-               LoadTGA (name, &tga, NULL, NULL);\r
-\r
-               for (y=0 ; y<256 ; y++)\r
-               {\r
-                       for (x=0 ; x<256 ; x++)\r
-                       {\r
-                               image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);\r
-                       }\r
-               }\r
-               free (tga);\r
-               sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);\r
-               if (FileTime (name) != -1)\r
-                       printf ("%s already exists, not overwriting.\n", name);\r
-               else\r
-                       WritePCXfile (name, image, 256, 256, colormap_palette);\r
-       }\r
-}\r
-\r
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "qdata.h"
+#include "inout.h"
+
+char mip_prefix[1024];              // directory to dump the textures in
+
+qboolean colormap_issued;
+byte colormap_palette[768];
+
+/*
+   ==============
+   RemapZero
+
+   Replaces all 0 bytes in an image with the closest palette entry.
+   This is because NT won't let us change index 0, so any palette
+   animation leaves those pixels untouched.
+   ==============
+ */
+void RemapZero( byte *pixels, byte *palette, int width, int height ){
+       int i, c;
+       int alt_zero;
+       int value, best;
+
+       alt_zero = 0;
+       best = 9999999;
+       for ( i = 1 ; i < 255 ; i++ )
+       {
+               value = palette[i * 3 + 0] + palette[i * 3 + 1] + palette[i * 3 + 2];
+               if ( value < best ) {
+                       best = value;
+                       alt_zero = i;
+               }
+       }
+
+       c = width * height;
+       for ( i = 0 ; i < c ; i++ )
+               if ( pixels[i] == 0 ) {
+                       pixels[i] = alt_zero;
+               }
+}
+
+/*
+   ==============
+   Cmd_Grab
+
+   $grab filename x y width height
+   ==============
+ */
+void Cmd_Grab( void ){
+       int xl,yl,w,h,y;
+       byte            *cropped;
+       char savename[1024];
+       char dest[1024];
+
+       GetToken( false );
+
+       if ( token[0] == '/' || token[0] == '\\' ) {
+               sprintf( savename, "%s%s.pcx", gamedir, token + 1 );
+       }
+       else{
+               sprintf( savename, "%spics/%s.pcx", gamedir, token );
+       }
+
+       if ( g_release ) {
+               if ( token[0] == '/' || token[0] == '\\' ) {
+                       sprintf( dest, "%s.pcx", token + 1 );
+               }
+               else{
+                       sprintf( dest, "pics/%s.pcx", token );
+               }
+
+               ReleaseFile( dest );
+               return;
+       }
+
+       GetToken( false );
+       xl = atoi( token );
+       GetToken( false );
+       yl = atoi( token );
+       GetToken( false );
+       w = atoi( token );
+       GetToken( false );
+       h = atoi( token );
+
+       if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
+               Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
+       }
+
+       // crop it to the proper size
+       cropped = malloc( w * h );
+       for ( y = 0 ; y < h ; y++ )
+       {
+               memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
+       }
+
+       // save off the new image
+       printf( "saving %s\n", savename );
+       CreatePath( savename );
+       WritePCXfile( savename, cropped, w, h, lbmpalette );
+
+       free( cropped );
+}
+
+/*
+   ==============
+   Cmd_Raw
+
+   $grab filename x y width height
+   ==============
+ */
+void Cmd_Raw( void ){
+       int xl,yl,w,h,y;
+       byte            *cropped;
+       char savename[1024];
+       char dest[1024];
+
+       GetToken( false );
+
+       sprintf( savename, "%s%s.lmp", gamedir, token );
+
+       if ( g_release ) {
+               sprintf( dest, "%s.lmp", token );
+               ReleaseFile( dest );
+               return;
+       }
+
+       GetToken( false );
+       xl = atoi( token );
+       GetToken( false );
+       yl = atoi( token );
+       GetToken( false );
+       w = atoi( token );
+       GetToken( false );
+       h = atoi( token );
+
+       if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
+               Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
+       }
+
+       // crop it to the proper size
+       cropped = malloc( w * h );
+       for ( y = 0 ; y < h ; y++ )
+       {
+               memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
+       }
+
+       // save off the new image
+       printf( "saving %s\n", savename );
+       CreatePath( savename );
+
+       SaveFile( savename, cropped, w * h );
+
+       free( cropped );
+}
+
+/*
+   =============================================================================
+
+   COLORMAP GRABBING
+
+   =============================================================================
+ */
+
+/*
+   ===============
+   BestColor
+   ===============
+ */
+byte BestColor( int r, int g, int b, int start, int stop ){
+       int i;
+       int dr, dg, db;
+       int bestdistortion, distortion;
+       int bestcolor;
+       byte    *pal;
+
+//
+// let any color go to 0 as a last resort
+//
+       bestdistortion = 256 * 256 * 4;
+       bestcolor = 0;
+
+       pal = colormap_palette + start * 3;
+       for ( i = start ; i <= stop ; i++ )
+       {
+               dr = r - (int)pal[0];
+               dg = g - (int)pal[1];
+               db = b - (int)pal[2];
+               pal += 3;
+               distortion = dr * dr + dg * dg + db * db;
+               if ( distortion < bestdistortion ) {
+                       if ( !distortion ) {
+                               return i;       // perfect match
+
+                       }
+                       bestdistortion = distortion;
+                       bestcolor = i;
+               }
+       }
+
+       return bestcolor;
+}
+
+
+/*
+   ==============
+   Cmd_Colormap
+
+   $colormap filename
+
+   the brightes colormap is first in the table (FIXME: reverse this now?)
+
+   64 rows of 256 : lightmaps
+   256 rows of 256 : translucency table
+   ==============
+ */
+void Cmd_Colormap( void ){
+       int levels, brights;
+       int l, c;
+       float frac, red, green, blue;
+       float range;
+       byte    *cropped, *lump_p;
+       char savename[1024];
+       char dest[1024];
+
+       colormap_issued = true;
+       if ( !g_release ) {
+               memcpy( colormap_palette, lbmpalette, 768 );
+       }
+
+       if ( !TokenAvailable() ) { // just setting colormap_issued
+               return;
+       }
+
+       GetToken( false );
+       sprintf( savename, "%spics/%s.pcx", gamedir, token );
+
+       if ( g_release ) {
+               sprintf( dest, "pics/%s.pcx", token );
+               ReleaseFile( dest );
+               return;
+       }
+
+       range = 2;
+       levels = 64;
+       brights = 1;    // ignore 255 (transparent)
+
+       cropped = malloc( ( levels + 256 ) * 256 );
+       lump_p = cropped;
+
+// shaded levels
+       for ( l = 0; l < levels; l++ )
+       {
+               frac = range - range * (float)l / ( levels - 1 );
+               for ( c = 0 ; c < 256 - brights ; c++ )
+               {
+                       red = lbmpalette[c * 3];
+                       green = lbmpalette[c * 3 + 1];
+                       blue = lbmpalette[c * 3 + 2];
+
+                       red = (int)( red * frac + 0.5 );
+                       green = (int)( green * frac + 0.5 );
+                       blue = (int)( blue * frac + 0.5 );
+
+//
+// note: 254 instead of 255 because 255 is the transparent color, and we
+// don't want anything remapping to that
+// don't use color 0, because NT can't remap that (or 255)
+//
+                       *lump_p++ = BestColor( red,green,blue, 1, 254 );
+               }
+
+               // fullbrights allways stay the same
+               for ( ; c < 256 ; c++ )
+                       *lump_p++ = c;
+       }
+
+// 66% transparancy table
+       for ( l = 0; l < 255; l++ )
+       {
+               for ( c = 0 ; c < 255 ; c++ )
+               {
+                       red = lbmpalette[c * 3] * 0.33 + lbmpalette[l * 3] * 0.66;
+                       green = lbmpalette[c * 3 + 1] * 0.33 + lbmpalette[l * 3 + 1] * 0.66;
+                       blue = lbmpalette[c * 3 + 2] * 0.33 + lbmpalette[l * 3 + 2] * 0.66;
+
+                       *lump_p++ = BestColor( red,green,blue, 1, 254 );
+               }
+               *lump_p++ = 255;
+       }
+       for ( c = 0 ; c < 256 ; c++ )
+               *lump_p++ = 255;
+
+       // save off the new image
+       printf( "saving %s\n", savename );
+       CreatePath( savename );
+       WritePCXfile( savename, cropped, 256, levels + 256, lbmpalette );
+
+       free( cropped );
+}
+
+/*
+   =============================================================================
+
+   MIPTEX GRABBING
+
+   =============================================================================
+ */
+
+byte pixdata[256];
+
+int d_red, d_green, d_blue;
+
+byte palmap[32][32][32];
+qboolean palmap_built;
+
+/*
+   =============
+   FindColor
+   =============
+ */
+int FindColor( int r, int g, int b ){
+       int bestcolor;
+
+       if ( r > 255 ) {
+               r = 255;
+       }
+       if ( r < 0 ) {
+               r = 0;
+       }
+       if ( g > 255 ) {
+               g = 255;
+       }
+       if ( g < 0 ) {
+               g = 0;
+       }
+       if ( b > 255 ) {
+               b = 255;
+       }
+       if ( b < 0 ) {
+               b = 0;
+       }
+#ifndef TABLECOLORS
+       bestcolor = BestColor( r, g, b, 0, 254 );
+#else
+       bestcolor = palmap[r >> 3][g >> 3][b >> 3];
+#endif
+
+       return bestcolor;
+}
+
+
+void BuildPalmap( void ){
+#ifdef TABLECOLORS
+       int r, g, b;
+       int bestcolor;
+
+       if ( palmap_built ) {
+               return;
+       }
+       palmap_built = true;
+
+       for ( r = 4 ; r < 256 ; r += 8 )
+       {
+               for ( g = 4 ; g < 256 ; g += 8 )
+               {
+                       for ( b = 4 ; b < 256 ; b += 8 )
+                       {
+                               bestcolor = BestColor( r, g, b, 1, 254 );
+                               palmap[r >> 3][g >> 3][b >> 3] = bestcolor;
+                       }
+               }
+       }
+#endif
+
+       if ( !colormap_issued ) {
+               Error( "You must issue a $colormap command first" );
+       }
+
+}
+
+/*
+   =============
+   AveragePixels
+   =============
+ */
+byte AveragePixels( int count ){
+       int r,g,b;
+       int i;
+       int vis;
+       int pix;
+       int bestcolor;
+       byte    *pal;
+       int fullbright;
+
+       vis = 0;
+       r = g = b = 0;
+       fullbright = 0;
+       for ( i = 0 ; i < count ; i++ )
+       {
+               pix = pixdata[i];
+
+               r += lbmpalette[pix * 3];
+               g += lbmpalette[pix * 3 + 1];
+               b += lbmpalette[pix * 3 + 2];
+               vis++;
+       }
+
+       r /= vis;
+       g /= vis;
+       b /= vis;
+
+       // error diffusion
+       r += d_red;
+       g += d_green;
+       b += d_blue;
+
+//
+// find the best color
+//
+       bestcolor = FindColor( r, g, b );
+
+       // error diffusion
+       pal = colormap_palette + bestcolor * 3;
+       d_red = r - (int)pal[0];
+       d_green = g - (int)pal[1];
+       d_blue = b - (int)pal[2];
+
+       return bestcolor;
+}
+
+
+typedef enum
+{
+       pt_contents,
+       pt_flags,
+       pt_animvalue,
+       pt_flagvalue
+} parmtype_t;
+
+typedef struct
+{
+       char    *name;
+       int flags;
+       parmtype_t type;
+} mipparm_t;
+
+mipparm_t mipparms[] =
+{
+       // utility content attributes
+       {"water",   CONTENTS_WATER, pt_contents},
+       {"slime",   CONTENTS_SLIME, pt_contents},       // mildly damaging
+       {"lava",    CONTENTS_LAVA, pt_contents},        // very damaging
+       {"window",  CONTENTS_WINDOW, pt_contents},  // solid, but doesn't eat internal textures
+       {"mist",    CONTENTS_MIST, pt_contents},    // non-solid window
+       {"origin",  CONTENTS_ORIGIN, pt_contents},  // center of rotating brushes
+       {"playerclip",  CONTENTS_PLAYERCLIP, pt_contents},
+       {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
+
+       // utility surface attributes
+       {"hint",    SURF_HINT, pt_flags},
+       {"skip",    SURF_SKIP, pt_flags},
+       {"light",   SURF_LIGHT, pt_flagvalue},      // value is the light quantity
+
+       // texture chaining
+       {"anim",    0,          pt_animvalue},      // value is the next animation
+
+       // server attributes
+       {"slick",   SURF_SLICK, pt_flags},
+
+       // drawing attributes
+       {"sky",     SURF_SKY, pt_flags},
+       {"warping", SURF_WARP, pt_flags},       // only valid with 64x64 textures
+       {"trans33", SURF_TRANS33, pt_flags},    // translucent should allso set fullbright
+       {"trans66", SURF_TRANS66, pt_flags},
+       {"flowing", SURF_FLOWING, pt_flags},    // flow direction towards angle 0
+       {"nodraw",  SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
+
+       {NULL, 0, pt_contents}
+};
+
+
+
+/*
+   ==============
+   Cmd_Mip
+
+   $mip filename x y width height <OPTIONS>
+   must be multiples of sixteen
+   SURF_WINDOW
+   ==============
+ */
+void Cmd_Mip( void ){
+       int x,y,xl,yl,xh,yh,w,h;
+       byte            *screen_p, *source;
+       int linedelta;
+       miptex_t        *qtex;
+       int miplevel, mipstep;
+       int xx, yy, pix;
+       int count;
+       int flags, value, contents;
+       mipparm_t       *mp;
+       char lumpname[64];
+       byte            *lump_p;
+       char filename[1024];
+       char animname[64];
+
+       GetToken( false );
+       strcpy( lumpname, token );
+
+       GetToken( false );
+       xl = atoi( token );
+       GetToken( false );
+       yl = atoi( token );
+       GetToken( false );
+       w = atoi( token );
+       GetToken( false );
+       h = atoi( token );
+
+       if ( ( w & 15 ) || ( h & 15 ) ) {
+               Error( "line %i: miptex sizes must be multiples of 16", scriptline );
+       }
+
+       flags = 0;
+       contents = 0;
+       value = 0;
+
+       animname[0] = 0;
+
+       // get optional flags and values
+       while ( TokenAvailable() )
+       {
+               GetToken( false );
+
+               for ( mp = mipparms ; mp->name ; mp++ )
+               {
+                       if ( !strcmp( mp->name, token ) ) {
+                               switch ( mp->type )
+                               {
+                               case pt_animvalue:
+                                       GetToken( false );   // specify the next animation frame
+                                       strcpy( animname, token );
+                                       break;
+                               case pt_flags:
+                                       flags |= mp->flags;
+                                       break;
+                               case pt_contents:
+                                       contents |= mp->flags;
+                                       break;
+                               case pt_flagvalue:
+                                       flags |= mp->flags;
+                                       GetToken( false );   // specify the light value
+                                       value = atoi( token );
+                                       break;
+                               }
+                               break;
+                       }
+               }
+               if ( !mp->name ) {
+                       Error( "line %i: unknown parm %s", scriptline, token );
+               }
+       }
+
+       sprintf( filename, "%stextures/%s/%s.wal", gamedir, mip_prefix, lumpname );
+       if ( g_release ) {
+               return; // textures are only released by $maps
+
+       }
+       xh = xl + w;
+       yh = yl + h;
+
+       qtex = malloc( sizeof( miptex_t ) + w * h * 2 );
+       memset( qtex, 0, sizeof( miptex_t ) );
+
+       qtex->width = LittleLong( w );
+       qtex->height = LittleLong( h );
+       qtex->flags = LittleLong( flags );
+       qtex->contents = LittleLong( contents );
+       qtex->value = LittleLong( value );
+       sprintf( qtex->name, "%s/%s", mip_prefix, lumpname );
+       if ( animname[0] ) {
+               sprintf( qtex->animname, "%s/%s", mip_prefix, animname );
+       }
+
+       lump_p = (byte *)( &qtex->value + 1 );
+
+       screen_p = byteimage + yl * byteimagewidth + xl;
+       linedelta = byteimagewidth - w;
+
+       source = lump_p;
+       qtex->offsets[0] = LittleLong( lump_p - (byte *)qtex );
+
+       for ( y = yl ; y < yh ; y++ )
+       {
+               for ( x = xl ; x < xh ; x++ )
+               {
+                       pix = *screen_p++;
+                       if ( pix == 255 ) {
+                               pix = 1;        // should never happen
+                       }
+                       *lump_p++ = pix;
+               }
+               screen_p += linedelta;
+       }
+
+//
+// subsample for greater mip levels
+//
+       d_red = d_green = d_blue = 0;   // no distortion yet
+
+       for ( miplevel = 1 ; miplevel < 4 ; miplevel++ )
+       {
+               qtex->offsets[miplevel] = LittleLong( lump_p - (byte *)qtex );
+
+               mipstep = 1 << miplevel;
+               for ( y = 0 ; y < h ; y += mipstep )
+               {
+
+                       for ( x = 0 ; x < w ; x += mipstep )
+                       {
+                               count = 0;
+                               for ( yy = 0 ; yy < mipstep ; yy++ )
+                                       for ( xx = 0 ; xx < mipstep ; xx++ )
+                                       {
+                                               pixdata[count] = source[ ( y + yy ) * w + x + xx ];
+                                               count++;
+                                       }
+                               *lump_p++ = AveragePixels( count );
+                       }
+               }
+       }
+
+//
+// dword align the size
+//
+       while ( (int)lump_p & 3 )
+               *lump_p++ = 0;
+
+//
+// write it out
+//
+       printf( "writing %s\n", filename );
+       SaveFile( filename, (byte *)qtex, lump_p - (byte *)qtex );
+
+       free( qtex );
+}
+
+/*
+   ===============
+   Cmd_Mippal
+   ===============
+ */
+void Cmd_Mippal( void ){
+       colormap_issued = true;
+       if ( g_release ) {
+               return;
+       }
+
+       memcpy( colormap_palette, lbmpalette, 768 );
+
+       BuildPalmap();
+}
+
+
+/*
+   ===============
+   Cmd_Mipdir
+   ===============
+ */
+void Cmd_Mipdir( void ){
+       char filename[1024];
+
+       GetToken( false );
+       strcpy( mip_prefix, token );
+       // create the directory if needed
+       sprintf( filename, "%stextures", gamedir, mip_prefix );
+       Q_mkdir( filename );
+       sprintf( filename, "%stextures/%s", gamedir, mip_prefix );
+       Q_mkdir( filename );
+}
+
+
+/*
+   =============================================================================
+
+   ENVIRONMENT MAP GRABBING
+
+   Creates six pcx files from tga files without any palette edge seams
+   also copies the tga files for GL rendering.
+   =============================================================================
+ */
+
+// 3dstudio environment map suffixes
+char    *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
+
+/*
+   =================
+   Cmd_Environment
+   =================
+ */
+void Cmd_Environment( void ){
+       char name[1024];
+       int i, x, y;
+       byte image[256 * 256];
+       byte    *tga;
+
+       GetToken( false );
+
+       if ( g_release ) {
+               for ( i = 0 ; i < 6 ; i++ )
+               {
+                       sprintf( name, "env/%s%s.pcx", token, suf[i] );
+                       ReleaseFile( name );
+                       sprintf( name, "env/%s%s.tga", token, suf[i] );
+                       ReleaseFile( name );
+               }
+               return;
+       }
+       // get the palette
+       BuildPalmap();
+
+       sprintf( name, "%senv/", gamedir );
+       CreatePath( name );
+
+       // convert the images
+       for ( i = 0 ; i < 6 ; i++ )
+       {
+               sprintf( name, "%senv/%s%s.tga", gamedir, token, suf[i] );
+               printf( "loading %s...\n", name );
+               LoadTGA( name, &tga, NULL, NULL );
+
+               for ( y = 0 ; y < 256 ; y++ )
+               {
+                       for ( x = 0 ; x < 256 ; x++ )
+                       {
+                               image[y * 256 + x] = FindColor( tga[( y * 256 + x ) * 4 + 0],tga[( y * 256 + x ) * 4 + 1],tga[( y * 256 + x ) * 4 + 2] );
+                       }
+               }
+               free( tga );
+               sprintf( name, "%senv/%s%s.pcx", gamedir, token, suf[i] );
+               if ( FileTime( name ) != -1 ) {
+                       printf( "%s already exists, not overwriting.\n", name );
+               }
+               else{
+                       WritePCXfile( name, image, 256, 256, colormap_palette );
+               }
+       }
+}