]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/qdata_heretic2/tmix.c
Merge branch 'master' into divVerent/farplanedist-sky-fix
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / tmix.c
index ad1d1902e051b6b4fc80291cf409eb18f6f55df1..75674a017c93e491c009355bbca76bd6a70338f1 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-\r
-#include "qdata.h"\r
-#include "flex.h"\r
-\r
-#define                MAXFILES        2048\r
-\r
-typedef        struct\r
-{\r
-       int                     x;\r
-       int                     y;\r
-       int                     w;\r
-       int                     h;\r
-       int                     cw;\r
-       int                     ch;\r
-       int                     rw;\r
-       int                     index;\r
-       int                     depth;\r
-       int                     col;\r
-       int                     baseline;\r
-       char            name[128];\r
-} Coords;\r
-\r
-int                            filenum;\r
-int                            valid;\r
-Coords                         in[MAXFILES];\r
-Coords                 out;\r
-char                   outscript[256];\r
-char                   sourcedir[256];\r
-char                   outusage[256];\r
-char                   root[32];\r
-\r
-int                            destsize = 0;\r
-byte                   *pixels = NULL;                         // Buffer to load image\r
-long                   *outpixels = NULL;                      // Buffer to store combined textures\r
-long                   *usagemap = NULL;                       // Buffer of usage map\r
-void                   *bmptemp = NULL;                        // Buffer of usage map\r
-byte                   *map = NULL;\r
-\r
-int                            xcharsize;\r
-int                            ycharsize;\r
-int                            dosort = 0;\r
-int                            missed = 0;\r
-int                            overlap = 0;\r
-int                            nobaseline = 0;\r
-int                            percent;\r
-\r
-//////////////////////////////////////////////////\r
-// Setting the char based usage map                            //\r
-//////////////////////////////////////////////////\r
-\r
-byte   TryPlace(Coords *coord)\r
-{\r
-       int             x, y;\r
-       byte    entry = 0;\r
-       byte    *mapitem;\r
-       \r
-       mapitem = map + (coord->x / xcharsize) + ((coord->y / ycharsize) * out.cw);\r
-\r
-       for (y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw)\r
-       {\r
-               for (x = 0; x < coord->cw; x++)\r
-               {\r
-                       if (entry |= *mapitem++ & 8)\r
-                       {\r
-                               return(entry);\r
-                       }\r
-               }\r
-       }\r
-       return(entry);\r
-}\r
-\r
-void   SetMap(Coords *coord)\r
-{\r
-       int             x, y;\r
-       byte    *mapitem;\r
-\r
-       mapitem = map + (coord->x / xcharsize) + ((coord->y / ycharsize) * out.cw);\r
-\r
-       for (y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw)\r
-               for (x = 0; x < coord->cw; x++)\r
-                       *mapitem++ |= 8;\r
-}\r
-\r
-//////////////////////////////////////////////////\r
-// Setting the pixel based usage map                   //\r
-//////////////////////////////////////////////////\r
-\r
-void   CheckOverlap(Coords *coord)\r
-{\r
-       int                     x;\r
-       int                     y;\r
-       long            *dest;\r
-\r
-       x = coord->x;\r
-       y = coord->y;\r
-\r
-       dest = (long *)(usagemap + x + (y * out.w));\r
-\r
-       for (y = 0; y < coord->h; y++, dest += out.w - coord->w)\r
-       {\r
-               for (x = 0; x < coord->w; x++)\r
-               {\r
-                       if (*dest++)\r
-                       {\r
-                               overlap++;\r
-                               return;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void   SetUsageMap(Coords *coord)\r
-{\r
-       int                     x;\r
-       int                     y;\r
-       long            *dest;\r
-\r
-       x = coord->x;\r
-       y = coord->y;\r
-\r
-       dest = (long *)(usagemap + x + (y * out.w));\r
-\r
-       for (y = 0; y < coord->h; y++, dest += out.w - coord->w)\r
-       {\r
-               for (x = 0; x < coord->w; x++)\r
-               {\r
-                       *dest++ = coord->col;\r
-               }\r
-       }\r
-}\r
-\r
-//////////////////////////////////////////////////\r
-// Flips the BMP image to the correct way up   //\r
-//////////////////////////////////////////////////\r
-\r
-void   CopyLine(byte *dest, byte *src, int size)\r
-{\r
-       int             x;\r
-       \r
-       for (x = 0; x < size; x++)\r
-               *dest++ = *src++;\r
-}\r
-\r
-/****************************************************/\r
-/* Printing headers etc                                                                */\r
-/****************************************************/\r
-\r
-void RemoveLeading(char *name)\r
-{\r
-       int             i;\r
-       char    temp[128];\r
-\r
-       for(i = strlen(name) - 1; i > 0; i--)\r
-       {\r
-               if((name[i] == '\\') || (name[i] == '/'))\r
-               {\r
-                       strcpy(temp, name + i + 1);\r
-                       strcpy(name, temp);\r
-                       return;\r
-               }\r
-       }\r
-}\r
-\r
-void RemoveExt(char *name)\r
-{\r
-       while ((*name != '.') && *name)\r
-               name++;\r
-       *name = 0;\r
-}\r
-\r
-/****************************************************/\r
-/* Misc calcualtions                                                           */\r
-/****************************************************/\r
-\r
-int    TotalArea()\r
-{\r
-       int             i;\r
-       int             total = 0;\r
-\r
-       for (i = 0; i < (filenum + 2); i++)\r
-               total += in[i].w * in[i].h;\r
-\r
-       return(total);\r
-}\r
-\r
-/****************************************************/\r
-/* Setup and checking of all info                                      */\r
-/****************************************************/\r
-\r
-void   InitVars()\r
-{\r
-       filenum = 0;\r
-       valid = 0;\r
-       dosort = 0;\r
-       missed = 0;\r
-       overlap = 0;\r
-       nobaseline = 0;\r
-       \r
-       memset(outscript, 0, sizeof(outscript));\r
-       memset(outscript, 0, sizeof(sourcedir));\r
-       memset(outscript, 0, sizeof(outusage));\r
-       memset(outscript, 0, sizeof(root));\r
-\r
-       memset(in, 0, sizeof(in));\r
-       memset(&out, 0, sizeof(out));\r
-}\r
-void Cleanup()\r
-{\r
-       if (pixels)\r
-               free(pixels);\r
-       if (usagemap)\r
-               free(usagemap);\r
-       if (outpixels)\r
-               free(outpixels);\r
-       if (bmptemp)\r
-               free(bmptemp);\r
-       if (map)\r
-               free(map);\r
-}\r
-\r
-typedef struct glxy_s\r
-{\r
-       float   xl, yt, xr, yb;\r
-       int             w, h, baseline;\r
-} glxy_t;\r
-\r
-int    SaveScript(char *name)\r
-{\r
-       FILE            *fp;\r
-       int                     i, j;\r
-       glxy_t          buff;\r
-       \r
-       if(fp = fopen(name, "wb"))\r
-       {\r
-               for (j = 0; j < filenum; j++)\r
-               {\r
-                       for (i = 0; i < filenum; i++)\r
-                       {\r
-                               if (in[i].index == j)\r
-                               {\r
-                                       if (in[i].depth)\r
-                                       {\r
-                                               buff.xl = (float)in[i].x / (float)out.w;\r
-                                               buff.yt = (float)in[i].y / (float)out.h;\r
-                                               buff.xr = ((float)in[i].w + (float)in[i].x) / (float)out.w;\r
-                                               buff.yb = ((float)in[i].h + (float)in[i].y) / (float)out.h;\r
-                                               buff.w = in[i].w;\r
-                                               buff.h = in[i].h;\r
-                                               buff.baseline = in[i].baseline;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               memset(&buff, 0, sizeof(glxy_t));\r
-                                       }\r
-                                       fwrite(&buff, 1, sizeof(glxy_t), fp);\r
-                                       i = filenum;\r
-                               }\r
-                       }\r
-               }\r
-               fclose(fp);\r
-               return(true);\r
-       }\r
-       else\r
-               return(false);\r
-}\r
-\r
-int            GetScriptInfo(char *name)\r
-{\r
-       FILE            *fp;\r
-       char            buffer[256];\r
-       char            tempbuff[256];\r
-       char            delims[] = {" \t,\n"};\r
-\r
-       printf("Opening script file %s.\n", name);\r
-\r
-       if (fp = fopen(name, "r"))\r
-       {\r
-               while(fgets(buffer, 256, fp))\r
-               {\r
-                       if (strncmp(buffer, "//", 2) && strncmp(buffer, "\n", 1))\r
-                       {\r
-                               strupr(buffer);\r
-                               strcpy(tempbuff, buffer);\r
-                               if (strcmp(strtok(tempbuff, delims), "OUTPUT") == 0)\r
-                               {\r
-                                       strcpy(out.name, strtok(NULL, delims));\r
-                                       strlwr(out.name);\r
-                               }\r
-\r
-                               strcpy(tempbuff, buffer);\r
-                               if (strcmp(strtok(tempbuff, delims), "SOURCEDIR") == 0)\r
-                               {\r
-                                       strcpy(tempbuff, strtok(NULL, delims));\r
-                                       strcpy(sourcedir, ExpandPathAndArchive(tempbuff));\r
-                               }\r
-\r
-                               strcpy(tempbuff, buffer);\r
-                               if (strcmp(strtok(tempbuff, delims), "DOSORT") == 0)\r
-                                       dosort = 1;\r
-\r
-                               strcpy(tempbuff, buffer);\r
-                               if (strcmp(strtok(tempbuff, delims), "XCHARSIZE") == 0)\r
-                                       xcharsize = strtol(strtok(NULL, delims), NULL, 0);\r
-\r
-                               strcpy(tempbuff, buffer);\r
-                               if (strcmp(strtok(tempbuff, delims), "YCHARSIZE") == 0)\r
-                                       ycharsize = strtol(strtok(NULL, delims), NULL, 0);\r
-\r
-                               strcpy(tempbuff, buffer);\r
-                               if (strcmp(strtok(tempbuff, delims), "OUTSCRIPT") == 0)\r
-                               {\r
-                                       strcpy(outscript, strtok(NULL, delims));\r
-                                       strlwr(outscript);\r
-                               }\r
-\r
-                               strcpy(tempbuff, buffer);\r
-                               if (strcmp(strtok(tempbuff, delims), "OUTUSAGE") == 0)\r
-                                       strcpy(outusage, strtok(NULL, delims));\r
-\r
-                               strcpy(tempbuff, buffer);\r
-                               if (strcmp(strtok(tempbuff, delims), "POS") == 0)\r
-                               {\r
-                                       out.w = strtol(strtok(NULL, delims), NULL, 0);\r
-                                       out.h = strtol(strtok(NULL, delims), NULL, 0);\r
-                               }\r
-\r
-                               strcpy(tempbuff, buffer);\r
-                               if (strcmp(strtok(tempbuff, delims), "FILE") == 0)\r
-                               {\r
-                                       strcpy(in[filenum].name, strtok(NULL, delims));\r
-                                       in[filenum].x = strtol(strtok(NULL, delims), NULL, 0);\r
-                                       in[filenum].y = strtol(strtok(NULL, delims), NULL, 0);\r
-                                       in[filenum].col = strtol(strtok(NULL, delims), NULL, 0);\r
-                                       filenum++;\r
-                               }\r
-                       }\r
-               }\r
-               fclose(fp);\r
-               return(true);\r
-       }\r
-       else\r
-       {\r
-               printf("ERROR : Could not open script file.\n");\r
-               return(false);\r
-       }\r
-}\r
-\r
-int    CheckVars()\r
-{\r
-       int             i;\r
-\r
-        if (out.name[0] == 0)\r
-        {\r
-               printf("ERROR : No output name specified.\n");\r
-               return(false);\r
-       }\r
-       if ((out.w <= 0) || (out.h <= 0))\r
-       {\r
-               printf("ERROR : Invalid VRAM coordinates.\n");\r
-               return(false);\r
-       }\r
-       if (filenum == 0)\r
-       {\r
-               printf("ERROR : No input files specified.\n");\r
-               return(false);\r
-       }\r
-       for (i = 0; i < filenum; i++)\r
-               if (in[i].name[0] == 0)\r
-               {\r
-                       printf("ERROR : Input filename invalid.\n");\r
-                       return(false);\r
-               }\r
-       return(true);\r
-}\r
-\r
-// Makes sure texture is totally within the output area\r
-\r
-int    CheckCoords(Coords *coord)\r
-{\r
-       if ((coord->x + coord->w) > out.w)\r
-               return(false);\r
-       if ((coord->y + coord->h) > out.h)\r
-               return(false);\r
-\r
-       return(true);\r
-}\r
-// Gets the width, height, palette width and palette height of each BMP file\r
-\r
-int            GetFileDimensions()\r
-{\r
-       int                     i;\r
-       int                     width, height;\r
-       char            name[128];\r
-\r
-       for (i = 0; i < filenum; i++)\r
-       {\r
-               in[i].index = i;\r
-\r
-               strcpy(name, sourcedir);\r
-               strcat(name, in[i].name);\r
-               printf("Getting file dimensions, file : %s        \r", in[i].name);\r
-               if(FileExists(name))\r
-               {\r
-                       LoadAnyImage(name, NULL, NULL, &width, &height);\r
-                       in[i].depth = 32;\r
-                       in[i].rw = width;\r
-                       in[i].w = width;                                                // makes it width in \r
-                       in[i].h = height;\r
-                       in[i].cw = (in[i].w + (xcharsize - 1)) / xcharsize;\r
-                       in[i].ch = (in[i].h + (ycharsize - 1)) / ycharsize;\r
-\r
-                       if (!CheckCoords(&in[i]) && (in[i].x >= 0))\r
-                       {\r
-                               printf("Error : texture %s out of bounds.\n", in[i].name);\r
-                               return(false);\r
-                       }\r
-                       valid++;\r
-               }\r
-               else\r
-               {\r
-                       in[i].depth = 0;\r
-                       in[i].x = -1;\r
-                       in[i].y = -1;\r
-                       in[i].w = 0;\r
-                       in[i].h = 0;\r
-               }\r
-       }\r
-       printf("\n\n");\r
-       return(true);\r
-}\r
-\r
-// Sorts files into order for optimal space finding\r
-// Fixed position ones first, followed by the others in descending size\r
-// The theory being that it is easier to find space for smaller textures.\r
-// size = (width + height)\r
-// For space finding it is easier to place a 32x32 than a 128x2\r
-\r
-#define        WEIGHT  0x8000\r
-\r
-void   Swap(Coords *a, Coords *b)\r
-{\r
-       Coords          c;\r
-\r
-       c = *a;\r
-       *a = *b;\r
-       *b = c;\r
-}\r
-\r
-void   SortInNames()\r
-{\r
-       int             i, j;\r
-       int             largest, largcount;\r
-       int             size;\r
-\r
-       printf("Sorting filenames by size.\n\n");\r
-\r
-       for (j = 0; j < filenum; j++)\r
-       {\r
-               largest = -1;\r
-               largcount = -1;\r
-\r
-               for (i = j; i < filenum; i++)\r
-               {\r
-                       if (in[i].depth)\r
-                       {\r
-                               size = in[i].w + in[i].h;\r
-               \r
-                               if ((in[i].x < 0) && (size > largest))\r
-                               {\r
-                                       largcount = i;\r
-                                       largest = size;\r
-                               }\r
-                       }\r
-               }\r
-               if ((largcount >= 0) && (largcount != j))\r
-                       Swap(&in[j], &in[largcount]);\r
-       }\r
-}\r
-\r
-int    SetVars(char *name)\r
-{\r
-       if (!GetScriptInfo(name))\r
-               return(false);\r
-\r
-       if (!CheckVars())\r
-               return(false);\r
-\r
-       destsize = out.w * out.h;\r
-\r
-       out.cw = out.w / xcharsize;\r
-       out.ch = out.h / ycharsize;\r
-\r
-       if ((usagemap = (long *)SafeMalloc(destsize * 4, "")) == NULL)\r
-               return(false);\r
-       if ((outpixels = (long *)SafeMalloc(destsize * 4, "")) == NULL)\r
-               return(false); \r
-       if ((bmptemp = (void *)SafeMalloc(destsize * 4, "")) == NULL)\r
-               return(false);\r
-       if ((map = (byte *)SafeMalloc(destsize / (xcharsize * ycharsize), "")) == NULL)\r
-               return(false);\r
-\r
-       if (GetFileDimensions() == false)\r
-               return(false);\r
-\r
-       if (dosort)\r
-               SortInNames();\r
-\r
-       return(true);\r
-}\r
-/****************************************************/\r
-/* Actual copying routines                                                     */\r
-/****************************************************/\r
-\r
-int FindCoords(Coords *coord)\r
-{\r
-       int             tx, ty;\r
-\r
-       if (coord->x >= 0)\r
-       {       \r
-               SetMap(coord);\r
-               return(true);\r
-       }\r
-       else\r
-       {\r
-               for (ty = 0; ty < out.ch; ty++)\r
-               {\r
-                       for (tx = 0; tx < out.cw; tx++)\r
-                       {\r
-                               coord->x = (tx * xcharsize);\r
-                               coord->y = (ty * ycharsize);\r
-       \r
-                               if (CheckCoords(coord) && !TryPlace(coord))\r
-                               {\r
-                                       SetMap(coord);\r
-                                       return(true);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       coord->x = -1;\r
-       coord->y = -1;\r
-\r
-       return(false);\r
-}\r
-\r
-void CheckBaseline(int i)\r
-{\r
-       int             y;\r
-       long    *pix;\r
-\r
-       in[i].baseline = -1;\r
-       pix = (long *)pixels;\r
-\r
-       for(y = 0; y < in[i].h; y++, pix += in[i].w)\r
-       {\r
-               if((*pix & 0x00ffffff) == 0x00ff00ff)\r
-               {\r
-                       in[i].baseline = y;\r
-                       break;\r
-               }\r
-       }\r
-       pix = (long *)pixels;\r
-       for(y = 0; y < in[i].w * in[i].h; y++, pix++)\r
-       {\r
-               if((*pix & 0x00ffffff) == 0x00ff00ff)\r
-               {\r
-                       *pix = 0;\r
-               }\r
-       }\r
-\r
-       if(in[i].baseline == -1)\r
-       {\r
-               printf("\nERROR : %s has no baseline\n", in[i].name);\r
-               nobaseline++;\r
-       }\r
-}\r
-\r
-void   CopyToMain32(Coords *coord)\r
-{\r
-       int                     x;\r
-       int                     y;\r
-       long            *source;\r
-       long            *dest;\r
-\r
-       x = coord->x;\r
-       y = coord->y;\r
-\r
-       source = (long *)pixels;\r
-       dest = (long *)(outpixels + x + (y * out.w));\r
-\r
-       for (y = 0; y < coord->h; y++, dest += out.w - coord->w)\r
-       {\r
-               for (x = 0; x < coord->w; x++)\r
-               {\r
-                       *dest++ = *source++;\r
-               }\r
-       }\r
-}\r
-\r
-void CreateMain()\r
-{\r
-       int                     i, count;\r
-       int                     width, height;\r
-       char            name[128];\r
-       \r
-       for (i = 0, count = 0; i < filenum; i++)\r
-       {\r
-               if (in[i].depth)\r
-               {\r
-                       printf("\rProcessing %d of %d (%d missed, %d overlapping, %d nobase)\r", count + 1, valid, missed, overlap, nobaseline);\r
-                       count++;\r
-                       if (!FindCoords(&in[i]))\r
-                               missed++;\r
-                       else\r
-                       {\r
-                               strcpy(name, sourcedir);\r
-                               strcat(name, in[i].name);\r
-                               LoadAnyImage(name, &pixels, NULL, &width, &height);\r
-                               CheckBaseline(i);\r
-                               CheckOverlap(&in[i]);\r
-                               CopyToMain32(&in[i]);\r
-                               SetUsageMap(&in[i]);\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void Cmd_TextureMix()\r
-{\r
-       miptex32_t              *qtex32;\r
-       char                    filename[1024];\r
-       int                             size;\r
-\r
-       InitVars();\r
-\r
-       GetScriptToken (false);\r
-\r
-       strcpy(root, token);\r
-       RemoveExt(root);\r
-       RemoveLeading(root);\r
-\r
-       strcpy(filename, ExpandPathAndArchive(token));\r
-       if (SetVars(filename))\r
-       {\r
-               // Create combined texture\r
-               percent = ((TotalArea() * 100) / (out.w * out.h));\r
-               printf("Total area consumed : %d%%\n", percent);\r
-               printf("Texture resolution  : %dx%d pixels.\n", xcharsize, ycharsize);\r
-               CreateMain();\r
-\r
-               // Save image as m32\r
-               sprintf (filename, "%spics/misc/%s.m32", gamedir, out.name);\r
-               qtex32 = CreateMip32((unsigned *)outpixels, out.w, out.h, &size, false);\r
-\r
-               qtex32->contents = 0;\r
-               qtex32->value = 0;\r
-               qtex32->scale_x = 1.0;\r
-               qtex32->scale_y = 1.0;\r
-               sprintf (qtex32->name, "misc/%s", out.name);\r
-\r
-               printf ("\n\nwriting %s\n", filename);\r
-               SaveFile (filename, (byte *)qtex32, size);\r
-               free (qtex32);\r
-\r
-               // Save out script file\r
-               sprintf (filename, "%spics/misc/%s.fnt", gamedir, outscript);\r
-               printf("Writing %s as script file\n", filename);\r
-               if (!SaveScript(filename))\r
-               {\r
-                       printf("Unable to save output script.\n");\r
-               }\r
-       }\r
-       printf("Everythings groovy.\n");\r
-       Cleanup();\r
-}\r
-\r
-// end\r
-\r
+/*
+   Copyright (C) 1999-2006 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 "flex.h"
+
+#define     MAXFILES    2048
+
+typedef struct
+{
+       int x;
+       int y;
+       int w;
+       int h;
+       int cw;
+       int ch;
+       int rw;
+       int index;
+       int depth;
+       int col;
+       int baseline;
+       char name[128];
+} Coords;
+
+int filenum;
+int valid;
+Coords in[MAXFILES];
+Coords out;
+char outscript[256];
+char sourcedir[256];
+char outusage[256];
+char root[32];
+
+int destsize = 0;
+byte            *pixels = NULL;             // Buffer to load image
+long            *outpixels = NULL;          // Buffer to store combined textures
+long            *usagemap = NULL;           // Buffer of usage map
+void            *bmptemp = NULL;            // Buffer of usage map
+byte            *map = NULL;
+
+int xcharsize;
+int ycharsize;
+int dosort = 0;
+int missed = 0;
+int overlap = 0;
+int nobaseline = 0;
+int percent;
+
+//////////////////////////////////////////////////
+// Setting the char based usage map                            //
+//////////////////////////////////////////////////
+
+byte    TryPlace( Coords *coord ){
+       int x, y;
+       byte entry = 0;
+       byte    *mapitem;
+
+       mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw );
+
+       for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw )
+       {
+               for ( x = 0; x < coord->cw; x++ )
+               {
+                       if ( entry |= *mapitem++ & 8 ) {
+                               return( entry );
+                       }
+               }
+       }
+       return( entry );
+}
+
+void    SetMap( Coords *coord ){
+       int x, y;
+       byte    *mapitem;
+
+       mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw );
+
+       for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw )
+               for ( x = 0; x < coord->cw; x++ )
+                       *mapitem++ |= 8;
+}
+
+//////////////////////////////////////////////////
+// Setting the pixel based usage map                   //
+//////////////////////////////////////////////////
+
+void    CheckOverlap( Coords *coord ){
+       int x;
+       int y;
+       long        *dest;
+
+       x = coord->x;
+       y = coord->y;
+
+       dest = (long *)( usagemap + x + ( y * out.w ) );
+
+       for ( y = 0; y < coord->h; y++, dest += out.w - coord->w )
+       {
+               for ( x = 0; x < coord->w; x++ )
+               {
+                       if ( *dest++ ) {
+                               overlap++;
+                               return;
+                       }
+               }
+       }
+}
+
+void    SetUsageMap( Coords *coord ){
+       int x;
+       int y;
+       long        *dest;
+
+       x = coord->x;
+       y = coord->y;
+
+       dest = (long *)( usagemap + x + ( y * out.w ) );
+
+       for ( y = 0; y < coord->h; y++, dest += out.w - coord->w )
+       {
+               for ( x = 0; x < coord->w; x++ )
+               {
+                       *dest++ = coord->col;
+               }
+       }
+}
+
+//////////////////////////////////////////////////
+// Flips the BMP image to the correct way up   //
+//////////////////////////////////////////////////
+
+void    CopyLine( byte *dest, byte *src, int size ){
+       int x;
+
+       for ( x = 0; x < size; x++ )
+               *dest++ = *src++;
+}
+
+/****************************************************/
+/* Printing headers etc                                                                */
+/****************************************************/
+
+void RemoveLeading( char *name ){
+       int i;
+       char temp[128];
+
+       for ( i = strlen( name ) - 1; i > 0; i-- )
+       {
+               if ( ( name[i] == '\\' ) || ( name[i] == '/' ) ) {
+                       strcpy( temp, name + i + 1 );
+                       strcpy( name, temp );
+                       return;
+               }
+       }
+}
+
+void RemoveExt( char *name ){
+       while ( ( *name != '.' ) && *name )
+               name++;
+       *name = 0;
+}
+
+/****************************************************/
+/* Misc calcualtions                                                           */
+/****************************************************/
+
+int TotalArea(){
+       int i;
+       int total = 0;
+
+       for ( i = 0; i < ( filenum + 2 ); i++ )
+               total += in[i].w * in[i].h;
+
+       return( total );
+}
+
+/****************************************************/
+/* Setup and checking of all info                                      */
+/****************************************************/
+
+void    InitVars(){
+       filenum = 0;
+       valid = 0;
+       dosort = 0;
+       missed = 0;
+       overlap = 0;
+       nobaseline = 0;
+
+       memset( outscript, 0, sizeof( outscript ) );
+       memset( outscript, 0, sizeof( sourcedir ) );
+       memset( outscript, 0, sizeof( outusage ) );
+       memset( outscript, 0, sizeof( root ) );
+
+       memset( in, 0, sizeof( in ) );
+       memset( &out, 0, sizeof( out ) );
+}
+void Cleanup(){
+       if ( pixels ) {
+               free( pixels );
+       }
+       if ( usagemap ) {
+               free( usagemap );
+       }
+       if ( outpixels ) {
+               free( outpixels );
+       }
+       if ( bmptemp ) {
+               free( bmptemp );
+       }
+       if ( map ) {
+               free( map );
+       }
+}
+
+typedef struct glxy_s
+{
+       float xl, yt, xr, yb;
+       int w, h, baseline;
+} glxy_t;
+
+int SaveScript( char *name ){
+       FILE        *fp;
+       int i, j;
+       glxy_t buff;
+
+       if ( fp = fopen( name, "wb" ) ) {
+               for ( j = 0; j < filenum; j++ )
+               {
+                       for ( i = 0; i < filenum; i++ )
+                       {
+                               if ( in[i].index == j ) {
+                                       if ( in[i].depth ) {
+                                               buff.xl = (float)in[i].x / (float)out.w;
+                                               buff.yt = (float)in[i].y / (float)out.h;
+                                               buff.xr = ( (float)in[i].w + (float)in[i].x ) / (float)out.w;
+                                               buff.yb = ( (float)in[i].h + (float)in[i].y ) / (float)out.h;
+                                               buff.w = in[i].w;
+                                               buff.h = in[i].h;
+                                               buff.baseline = in[i].baseline;
+                                       }
+                                       else
+                                       {
+                                               memset( &buff, 0, sizeof( glxy_t ) );
+                                       }
+                                       fwrite( &buff, 1, sizeof( glxy_t ), fp );
+                                       i = filenum;
+                               }
+                       }
+               }
+               fclose( fp );
+               return( true );
+       }
+       else{
+               return( false );
+       }
+}
+
+int     GetScriptInfo( char *name ){
+       FILE        *fp;
+       char buffer[256];
+       char tempbuff[256];
+       char delims[] = {" \t,\n"};
+
+       printf( "Opening script file %s.\n", name );
+
+       if ( fp = fopen( name, "r" ) ) {
+               while ( fgets( buffer, 256, fp ) )
+               {
+                       if ( strncmp( buffer, "//", 2 ) && strncmp( buffer, "\n", 1 ) ) {
+                               strupr( buffer );
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "OUTPUT" ) == 0 ) {
+                                       strcpy( out.name, strtok( NULL, delims ) );
+                                       strlwr( out.name );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "SOURCEDIR" ) == 0 ) {
+                                       strcpy( tempbuff, strtok( NULL, delims ) );
+                                       strcpy( sourcedir, ExpandPathAndArchive( tempbuff ) );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "DOSORT" ) == 0 ) {
+                                       dosort = 1;
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "XCHARSIZE" ) == 0 ) {
+                                       xcharsize = strtol( strtok( NULL, delims ), NULL, 0 );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "YCHARSIZE" ) == 0 ) {
+                                       ycharsize = strtol( strtok( NULL, delims ), NULL, 0 );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "OUTSCRIPT" ) == 0 ) {
+                                       strcpy( outscript, strtok( NULL, delims ) );
+                                       strlwr( outscript );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "OUTUSAGE" ) == 0 ) {
+                                       strcpy( outusage, strtok( NULL, delims ) );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "POS" ) == 0 ) {
+                                       out.w = strtol( strtok( NULL, delims ), NULL, 0 );
+                                       out.h = strtol( strtok( NULL, delims ), NULL, 0 );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "FILE" ) == 0 ) {
+                                       strcpy( in[filenum].name, strtok( NULL, delims ) );
+                                       in[filenum].x = strtol( strtok( NULL, delims ), NULL, 0 );
+                                       in[filenum].y = strtol( strtok( NULL, delims ), NULL, 0 );
+                                       in[filenum].col = strtol( strtok( NULL, delims ), NULL, 0 );
+                                       filenum++;
+                               }
+                       }
+               }
+               fclose( fp );
+               return( true );
+       }
+       else
+       {
+               printf( "ERROR : Could not open script file.\n" );
+               return( false );
+       }
+}
+
+int CheckVars(){
+       int i;
+
+       if ( out.name[0] == 0 ) {
+               printf( "ERROR : No output name specified.\n" );
+               return( false );
+       }
+       if ( ( out.w <= 0 ) || ( out.h <= 0 ) ) {
+               printf( "ERROR : Invalid VRAM coordinates.\n" );
+               return( false );
+       }
+       if ( filenum == 0 ) {
+               printf( "ERROR : No input files specified.\n" );
+               return( false );
+       }
+       for ( i = 0; i < filenum; i++ )
+               if ( in[i].name[0] == 0 ) {
+                       printf( "ERROR : Input filename invalid.\n" );
+                       return( false );
+               }
+       return( true );
+}
+
+// Makes sure texture is totally within the output area
+
+int CheckCoords( Coords *coord ){
+       if ( ( coord->x + coord->w ) > out.w ) {
+               return( false );
+       }
+       if ( ( coord->y + coord->h ) > out.h ) {
+               return( false );
+       }
+
+       return( true );
+}
+// Gets the width, height, palette width and palette height of each BMP file
+
+int     GetFileDimensions(){
+       int i;
+       int width, height;
+       char name[128];
+
+       for ( i = 0; i < filenum; i++ )
+       {
+               in[i].index = i;
+
+               strcpy( name, sourcedir );
+               strcat( name, in[i].name );
+               printf( "Getting file dimensions, file : %s        \r", in[i].name );
+               if ( FileExists( name ) ) {
+                       LoadAnyImage( name, NULL, NULL, &width, &height );
+                       in[i].depth = 32;
+                       in[i].rw = width;
+                       in[i].w = width;                        // makes it width in
+                       in[i].h = height;
+                       in[i].cw = ( in[i].w + ( xcharsize - 1 ) ) / xcharsize;
+                       in[i].ch = ( in[i].h + ( ycharsize - 1 ) ) / ycharsize;
+
+                       if ( !CheckCoords( &in[i] ) && ( in[i].x >= 0 ) ) {
+                               printf( "Error : texture %s out of bounds.\n", in[i].name );
+                               return( false );
+                       }
+                       valid++;
+               }
+               else
+               {
+                       in[i].depth = 0;
+                       in[i].x = -1;
+                       in[i].y = -1;
+                       in[i].w = 0;
+                       in[i].h = 0;
+               }
+       }
+       printf( "\n\n" );
+       return( true );
+}
+
+// Sorts files into order for optimal space finding
+// Fixed position ones first, followed by the others in descending size
+// The theory being that it is easier to find space for smaller textures.
+// size = (width + height)
+// For space finding it is easier to place a 32x32 than a 128x2
+
+#define WEIGHT  0x8000
+
+void    Swap( Coords *a, Coords *b ){
+       Coords c;
+
+       c = *a;
+       *a = *b;
+       *b = c;
+}
+
+void    SortInNames(){
+       int i, j;
+       int largest, largcount;
+       int size;
+
+       printf( "Sorting filenames by size.\n\n" );
+
+       for ( j = 0; j < filenum; j++ )
+       {
+               largest = -1;
+               largcount = -1;
+
+               for ( i = j; i < filenum; i++ )
+               {
+                       if ( in[i].depth ) {
+                               size = in[i].w + in[i].h;
+
+                               if ( ( in[i].x < 0 ) && ( size > largest ) ) {
+                                       largcount = i;
+                                       largest = size;
+                               }
+                       }
+               }
+               if ( ( largcount >= 0 ) && ( largcount != j ) ) {
+                       Swap( &in[j], &in[largcount] );
+               }
+       }
+}
+
+int SetVars( char *name ){
+       if ( !GetScriptInfo( name ) ) {
+               return( false );
+       }
+
+       if ( !CheckVars() ) {
+               return( false );
+       }
+
+       destsize = out.w * out.h;
+
+       out.cw = out.w / xcharsize;
+       out.ch = out.h / ycharsize;
+
+       if ( ( usagemap = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) {
+               return( false );
+       }
+       if ( ( outpixels = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) {
+               return( false );
+       }
+       if ( ( bmptemp = (void *)SafeMalloc( destsize * 4, "" ) ) == NULL ) {
+               return( false );
+       }
+       if ( ( map = (byte *)SafeMalloc( destsize / ( xcharsize * ycharsize ), "" ) ) == NULL ) {
+               return( false );
+       }
+
+       if ( GetFileDimensions() == false ) {
+               return( false );
+       }
+
+       if ( dosort ) {
+               SortInNames();
+       }
+
+       return( true );
+}
+/****************************************************/
+/* Actual copying routines                                                     */
+/****************************************************/
+
+int FindCoords( Coords *coord ){
+       int tx, ty;
+
+       if ( coord->x >= 0 ) {
+               SetMap( coord );
+               return( true );
+       }
+       else
+       {
+               for ( ty = 0; ty < out.ch; ty++ )
+               {
+                       for ( tx = 0; tx < out.cw; tx++ )
+                       {
+                               coord->x = ( tx * xcharsize );
+                               coord->y = ( ty * ycharsize );
+
+                               if ( CheckCoords( coord ) && !TryPlace( coord ) ) {
+                                       SetMap( coord );
+                                       return( true );
+                               }
+                       }
+               }
+       }
+       coord->x = -1;
+       coord->y = -1;
+
+       return( false );
+}
+
+void CheckBaseline( int i ){
+       int y;
+       long    *pix;
+
+       in[i].baseline = -1;
+       pix = (long *)pixels;
+
+       for ( y = 0; y < in[i].h; y++, pix += in[i].w )
+       {
+               if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) {
+                       in[i].baseline = y;
+                       break;
+               }
+       }
+       pix = (long *)pixels;
+       for ( y = 0; y < in[i].w * in[i].h; y++, pix++ )
+       {
+               if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) {
+                       *pix = 0;
+               }
+       }
+
+       if ( in[i].baseline == -1 ) {
+               printf( "\nERROR : %s has no baseline\n", in[i].name );
+               nobaseline++;
+       }
+}
+
+void    CopyToMain32( Coords *coord ){
+       int x;
+       int y;
+       long        *source;
+       long        *dest;
+
+       x = coord->x;
+       y = coord->y;
+
+       source = (long *)pixels;
+       dest = (long *)( outpixels + x + ( y * out.w ) );
+
+       for ( y = 0; y < coord->h; y++, dest += out.w - coord->w )
+       {
+               for ( x = 0; x < coord->w; x++ )
+               {
+                       *dest++ = *source++;
+               }
+       }
+}
+
+void CreateMain(){
+       int i, count;
+       int width, height;
+       char name[128];
+
+       for ( i = 0, count = 0; i < filenum; i++ )
+       {
+               if ( in[i].depth ) {
+                       printf( "\rProcessing %d of %d (%d missed, %d overlapping, %d nobase)\r", count + 1, valid, missed, overlap, nobaseline );
+                       count++;
+                       if ( !FindCoords( &in[i] ) ) {
+                               missed++;
+                       }
+                       else
+                       {
+                               strcpy( name, sourcedir );
+                               strcat( name, in[i].name );
+                               LoadAnyImage( name, &pixels, NULL, &width, &height );
+                               CheckBaseline( i );
+                               CheckOverlap( &in[i] );
+                               CopyToMain32( &in[i] );
+                               SetUsageMap( &in[i] );
+                       }
+               }
+       }
+}
+
+void Cmd_TextureMix(){
+       miptex32_t      *qtex32;
+       char filename[1024];
+       int size;
+
+       InitVars();
+
+       GetScriptToken( false );
+
+       strcpy( root, token );
+       RemoveExt( root );
+       RemoveLeading( root );
+
+       strcpy( filename, ExpandPathAndArchive( token ) );
+       if ( SetVars( filename ) ) {
+               // Create combined texture
+               percent = ( ( TotalArea() * 100 ) / ( out.w * out.h ) );
+               printf( "Total area consumed : %d%%\n", percent );
+               printf( "Texture resolution  : %dx%d pixels.\n", xcharsize, ycharsize );
+               CreateMain();
+
+               // Save image as m32
+               sprintf( filename, "%spics/misc/%s.m32", gamedir, out.name );
+               qtex32 = CreateMip32( (unsigned *)outpixels, out.w, out.h, &size, false );
+
+               qtex32->contents = 0;
+               qtex32->value = 0;
+               qtex32->scale_x = 1.0;
+               qtex32->scale_y = 1.0;
+               sprintf( qtex32->name, "misc/%s", out.name );
+
+               printf( "\n\nwriting %s\n", filename );
+               SaveFile( filename, (byte *)qtex32, size );
+               free( qtex32 );
+
+               // Save out script file
+               sprintf( filename, "%spics/misc/%s.fnt", gamedir, outscript );
+               printf( "Writing %s as script file\n", filename );
+               if ( !SaveScript( filename ) ) {
+                       printf( "Unable to save output script.\n" );
+               }
+       }
+       printf( "Everythings groovy.\n" );
+       Cleanup();
+}
+
+// end