-/*\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
-\r
-void TK_Init();\r
-\r
-qboolean g_compress_pak;\r
-qboolean g_release; // don't grab, copy output data to new tree\r
-qboolean g_pak; // if true, copy to pak instead of release\r
-char g_releasedir[1024]; // c:\quake2\baseq2, etc\r
-qboolean g_archive; // don't grab, copy source data to new tree\r
-qboolean do3ds;\r
-char g_only[256]; // if set, only grab this cd\r
-qboolean g_skipmodel; // set true when a cd is not g_only\r
-int g_forcemodel = MODEL_AUTO;\r
-qboolean g_verbose = false;\r
-qboolean g_allow_newskin = true;\r
-qboolean g_ignoreTriUV = false;\r
-qboolean g_publishOutput = false;\r
-\r
-char *ext_3ds = "3ds";\r
-char *ext_tri= "tri";\r
-char *trifileext;\r
-\r
-char g_materialFile[256] = "none"; // default for Heretic2\r
-char *g_outputDir;\r
-extern char *g_publishDir;\r
-\r
-extern qboolean g_nomkdir;\r
-\r
-/*\r
-=======================================================\r
-\r
- PAK FILES\r
-\r
-=======================================================\r
-*/\r
-\r
-typedef struct\r
-{\r
- char name[56];\r
- int filepos, filelen;\r
-} packfile_t;\r
-\r
-typedef struct\r
-{\r
- char id[4];\r
- int dirofs;\r
- int dirlen;\r
-} packheader_t;\r
-\r
-packfile_t pfiles[16384];\r
-FILE *pakfile;\r
-packfile_t *pf;\r
-packheader_t pakheader;\r
-\r
-\r
-\r
-/*\r
-==============\r
-BeginPak\r
-==============\r
-*/\r
-void BeginPak (char *outname)\r
-{\r
- if (!g_pak)\r
- return;\r
-\r
- pakfile = SafeOpenWrite (outname);\r
-\r
- // leave space for header\r
- SafeWrite (pakfile, &pakheader, sizeof(pakheader));\r
- \r
- pf = pfiles;\r
-}\r
-\r
-\r
-/*\r
-==============\r
-ReleaseFile\r
-\r
-Filename should be gamedir reletive.\r
-Either copies the file to the release dir, or adds it to\r
-the pak file.\r
-==============\r
-*/\r
-void ReleaseFile (char *filename)\r
-{\r
- int len;\r
- byte *buf;\r
- char source[1024];\r
- char dest[1024];\r
-\r
- if (!g_release)\r
- return;\r
-\r
- sprintf (source, "%s%s", gamedir, filename);\r
-\r
- if (!g_pak)\r
- { // copy it\r
- sprintf (dest, "%s/%s", g_releasedir, filename);\r
- printf ("copying to %s\n", dest);\r
- QCopyFile (source, dest);\r
- return;\r
- }\r
-\r
- // pak it\r
- printf ("paking %s\n", filename);\r
- if (strlen(filename) >= sizeof(pf->name))\r
- Error ("Filename too long for pak: %s", filename);\r
-\r
- len = LoadFile (source, (void **)&buf);\r
-\r
- // segment moved to old.c\r
-\r
- strcpy (pf->name, filename);\r
- pf->filepos = LittleLong(ftell(pakfile));\r
- pf->filelen = LittleLong(len);\r
- pf++;\r
-\r
- SafeWrite (pakfile, buf, len);\r
-\r
- free (buf);\r
-}\r
-\r
-\r
-/*\r
-==============\r
-FinishPak\r
-==============\r
-*/\r
-void FinishPak (void)\r
-{\r
- int dirlen;\r
- int d;\r
- int i;\r
-\r
- if (!g_pak)\r
- return;\r
-\r
- pakheader.id[0] = 'P';\r
- pakheader.id[1] = 'A';\r
- pakheader.id[2] = 'C';\r
- pakheader.id[3] = 'K';\r
- dirlen = (byte *)pf - (byte *)pfiles;\r
- pakheader.dirofs = LittleLong(ftell(pakfile));\r
- pakheader.dirlen = LittleLong(dirlen);\r
- \r
- SafeWrite (pakfile, pfiles, dirlen);\r
-\r
- i = ftell (pakfile);\r
- \r
- fseek (pakfile, 0, SEEK_SET);\r
- SafeWrite (pakfile, &pakheader, sizeof(pakheader));\r
- fclose (pakfile); \r
- \r
- d = pf - pfiles;\r
- printf ("%i files packed in %i bytes\n",d, i);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-Cmd_File\r
-\r
-This is only used to cause a file to be copied during a release\r
-build (default.cfg, maps, etc)\r
-===============\r
-*/\r
-void Cmd_File (void)\r
-{\r
- GetScriptToken (false);\r
- ReleaseFile (token);\r
-}\r
-\r
-/*\r
-===============\r
-PackDirectory_r\r
-\r
-===============\r
-*/\r
-#ifdef _WIN32\r
-#include "io.h"\r
-void PackDirectory_r (char *dir)\r
-{\r
- struct _finddata_t fileinfo;\r
- int handle;\r
- char dirstring[1024];\r
- char filename[1024];\r
-\r
- sprintf (dirstring, "%s%s/*.*", gamedir, dir);\r
-\r
- handle = _findfirst (dirstring, &fileinfo);\r
- if (handle == -1)\r
- return;\r
-\r
- do\r
- {\r
- sprintf (filename, "%s/%s", dir, fileinfo.name);\r
- if (fileinfo.attrib & _A_SUBDIR)\r
- { // directory\r
- if (fileinfo.name[0] != '.') // don't pak . and ..\r
- PackDirectory_r (filename);\r
- continue;\r
- }\r
- // copy or pack the file\r
- ReleaseFile (filename); \r
- } while (_findnext( handle, &fileinfo ) != -1);\r
-\r
- _findclose (handle);\r
-}\r
-#else\r
-\r
-#include <sys/types.h>\r
-#ifdef NeXT\r
-#include <sys/dir.h>\r
-#else\r
-#include <dirent.h>\r
-#endif\r
-\r
-void PackDirectory_r (char *dir)\r
-{\r
-#ifdef NeXT\r
- struct direct **namelist, *ent;\r
-#else\r
- struct dirent **namelist, *ent;\r
-#endif\r
- int count;\r
- struct stat st;\r
- int i;\r
- int len;\r
- char fullname[1024];\r
- char dirstring[1024];\r
- char *name;\r
- \r
- sprintf (dirstring, "%s%s", gamedir, dir);\r
- count = scandir(dirstring, &namelist, NULL, NULL);\r
- \r
- for (i=0 ; i<count ; i++)\r
- {\r
- ent = namelist[i]; \r
- name = ent->d_name;\r
-\r
- if (name[0] == '.')\r
- continue;\r
- \r
- sprintf (fullname, "%s/%s", dir, name);\r
- sprintf (dirstring, "%s%s/%s", gamedir, dir, name);\r
- \r
- if (stat (dirstring, &st) == -1)\r
- Error ("fstating %s", pf->name);\r
- if (st.st_mode & S_IFDIR)\r
- { // directory\r
- PackDirectory_r (fullname);\r
- continue;\r
- }\r
-\r
- // copy or pack the file\r
- ReleaseFile (fullname); \r
- }\r
-}\r
-#endif\r
-\r
-\r
-/*\r
-===============\r
-Cmd_Dir\r
-\r
-This is only used to cause a directory to be copied during a\r
-release build (sounds, etc)\r
-===============\r
-*/\r
-void Cmd_Dir (void)\r
-{\r
- GetScriptToken (false);\r
- PackDirectory_r (token); \r
-}\r
-\r
-//========================================================================\r
-\r
-#define MAX_RTEX 16384\r
-int numrtex;\r
-char rtex[MAX_RTEX][64];\r
-\r
-void ReleaseTexture (char *name)\r
-{\r
- int i;\r
- char path[1024];\r
-\r
- for (i=0 ; i<numrtex ; i++)\r
- if (!Q_strcasecmp(name, rtex[i]))\r
- return;\r
-\r
- if (numrtex == MAX_RTEX)\r
- Error ("numrtex == MAX_RTEX");\r
-\r
- strcpy (rtex[i], name);\r
- numrtex++;\r
-\r
- sprintf (path, "textures/%s.wal", name);\r
- ReleaseFile (path);\r
-}\r
-\r
-/*\r
-===============\r
-Cmd_Maps\r
-\r
-Only relevent for release and pak files.\r
-Releases the .bsp files for the maps, and scans all of the files to\r
-build a list of all textures used, which are then released.\r
-===============\r
-*/\r
-void Cmd_Maps (void)\r
-{\r
- char map[1024];\r
- int i;\r
-\r
- while (ScriptTokenAvailable ())\r
- {\r
- GetScriptToken (false);\r
- sprintf (map, "maps/%s.bsp", token);\r
- ReleaseFile (map);\r
-\r
- if (!g_release)\r
- continue;\r
-\r
- // get all the texture references\r
- sprintf (map, "%smaps/%s.bsp", gamedir, token);\r
- LoadBSPFileTexinfo (map);\r
- for (i=0 ; i<numtexinfo ; i++)\r
- ReleaseTexture (texinfo[i].texture);\r
- }\r
-}\r
-\r
-\r
-//==============================================================\r
-\r
-/*\r
-===============\r
-ParseScript\r
-===============\r
-*/\r
-void ParseScript (void)\r
-{\r
- while (1)\r
- {\r
- do\r
- { // look for a line starting with a $ command\r
- GetScriptToken (true);\r
- if (endofscript)\r
- return;\r
- if (token[0] == '$')\r
- break; \r
- while (ScriptTokenAvailable())\r
- GetScriptToken (false);\r
- } while (1);\r
- \r
- //\r
- // model commands\r
- //\r
- if (!strcmp (token, "$modelname"))\r
- MODELCMD_Modelname (MODEL_MD2);\r
- else if (!strcmp (token, "$cd"))\r
- MODELCMD_Cd (MODEL_MD2);\r
- else if (!strcmp (token, "$origin"))\r
- MODELCMD_Origin (MODEL_MD2);\r
- else if (!strcmp (token, "$cluster"))\r
- MODELCMD_Cluster (MODEL_MD2);\r
- else if (!strcmp (token, "$base"))\r
- MODELCMD_Base (MODEL_MD2);\r
- else if (!strcmp (token, "$scale"))\r
- MODELCMD_ScaleUp (MODEL_MD2);\r
- else if (!strcmp (token, "$frame"))\r
- MODELCMD_Frame (MODEL_MD2);\r
- else if (!strcmp (token, "$skin"))\r
- MODELCMD_Skin (MODEL_MD2);\r
- else if (!strcmp (token, "$skinsize"))\r
- MODELCMD_Skinsize (MODEL_MD2);\r
- //\r
- // flexible model commands\r
- //\r
- else if (!strcmp (token, "$fm_modelname"))\r
- MODELCMD_Modelname (MODEL_FM);\r
- else if (!strcmp (token, "$fm_base"))\r
- MODELCMD_Base (MODEL_FM);\r
- else if (!strcmp (token, "$fm_basest"))\r
- MODELCMD_BaseST (MODEL_FM);\r
- else if (!strcmp (token, "$fm_cd"))\r
- MODELCMD_Cd (MODEL_FM);\r
- else if (!strcmp (token, "$fm_origin"))\r
- MODELCMD_Origin (MODEL_FM);\r
- else if (!strcmp (token, "$fm_cluster"))\r
- MODELCMD_Cluster (MODEL_FM);\r
- else if (!strcmp (token, "$fm_skeleton"))\r
- MODELCMD_Skeleton (MODEL_FM);\r
- else if (!strcmp (token, "$fm_scale"))\r
- MODELCMD_ScaleUp (MODEL_FM);\r
- else if (!strcmp (token, "$fm_frame"))\r
- MODELCMD_Frame (MODEL_FM);\r
- else if (!strcmp (token, "$fm_skeletal_frame")) // left in for compadibility with qdt already using fm_skeletal_frame\r
- MODELCMD_Frame (MODEL_FM);\r
- else if (!strcmp (token, "$fm_skin"))\r
- MODELCMD_Skin (MODEL_FM);\r
- else if (!strcmp (token, "$fm_skinsize"))\r
- MODELCMD_Skinsize (MODEL_FM);\r
- else if (!strcmp (token, "$fm_begin_group"))\r
- MODELCMD_BeginGroup(MODEL_FM);\r
- else if (!strcmp (token, "$fm_end_group"))\r
- MODELCMD_EndGroup(MODEL_FM);\r
- else if (!strcmp (token, "$fm_referenced"))\r
- MODELCMD_Referenced(MODEL_FM);\r
- else if (!strcmp (token, "$fm_node_order"))\r
- MODELCMD_NodeOrder(MODEL_FM);\r
- \r
- //\r
- // sprite commands\r
- //\r
- else if (!strcmp (token, "$spritename"))\r
- Cmd_SpriteName ();\r
- else if (!strcmp (token, "$sprdir"))\r
- Cmd_Sprdir ();\r
- else if (!strcmp (token, "$load"))\r
- Cmd_Load ();\r
- else if (!strcmp (token, "$spriteframe"))\r
- Cmd_SpriteFrame ();\r
- //\r
- // image commands\r
- //\r
- else if (!strcmpi (token, "$grab"))\r
- Cmd_Grab ();\r
- else if (!strcmpi (token, "$raw"))\r
- Cmd_Raw ();\r
- else if (!strcmpi (token, "$colormap"))\r
- Cmd_Colormap ();\r
- else if (!strcmpi (token, "$mippal"))\r
- Cmd_Mippal ();\r
- else if (!strcmpi (token, "$mipdir"))\r
- Cmd_Mipdir ();\r
- else if (!strcmpi (token, "$mip"))\r
- Cmd_Mip ();\r
- else if (!strcmp (token, "$environment"))\r
- Cmd_Environment ();\r
- //\r
- // pics\r
- //\r
- else if (!strcmp (token, "$picdir"))\r
- Cmd_Picdir ();\r
- else if (!strcmp (token, "$pic"))\r
- Cmd_Pic ();\r
- //\r
- // book\r
- //\r
- else if (!strcmp (token, "$bookdir"))\r
- Cmd_Bookdir ();\r
- else if (!strcmp (token, "$book"))\r
- Cmd_Book ();\r
- //\r
- // tmix\r
- //\r
- else if (!strcmp (token, "$texturemix"))\r
- Cmd_TextureMix ();\r
- //\r
- // video\r
- //\r
- else if (!strcmp (token, "$video"))\r
- Cmd_Video ();\r
- //\r
- // misc\r
- //\r
- else if (!strcmp (token, "$file"))\r
- Cmd_File ();\r
- else if (!strcmp (token, "$dir"))\r
- Cmd_Dir ();\r
- else if (!strcmp (token, "$maps"))\r
- Cmd_Maps ();\r
- else if (!strcmp (token, "$alphalight"))\r
- Cmd_Alphalight ();\r
- else if (!strcmp (token, "$inverse16table" ))\r
- Cmd_Inverse16Table();\r
- else\r
- Error ("bad command %s\n", token);\r
- }\r
-}\r
-\r
-//=======================================================\r
-\r
-/*\r
-==============\r
-main\r
-==============\r
-*/\r
-int main (int argc, char **argv)\r
-{\r
- int i;\r
- char path[1024];\r
- char *basedir;\r
- double starttime, endtime;\r
-\r
- printf ("Qdata Plus : "__TIME__" "__DATE__"\n");\r
-\r
- starttime = I_FloatTime();\r
- basedir = NULL;\r
-\r
- TK_Init();\r
- ExpandWildcards (&argc, &argv);\r
-\r
- for (i=1 ; i<argc ; i++)\r
- {\r
- if (!strcmp(argv[i], "-archive"))\r
- {\r
- // -archive f:/quake2/release/dump_11_30\r
- archive = true;\r
- strcpy (archivedir, argv[i+1]);\r
- printf ("Archiving source to: %s\n", archivedir);\r
- i++;\r
- }\r
- else if (!strcmp(argv[i], "-release"))\r
- {\r
- g_release = true;\r
- strcpy (g_releasedir, argv[i+1]);\r
- printf ("Copy output to: %s\n", g_releasedir);\r
- i++;\r
- }\r
- else if (!strcmp(argv[i], "-base"))\r
- {\r
- i++;\r
- basedir = argv[i];\r
- }\r
- else if (!strcmp(argv[i], "-compress"))\r
- {\r
- g_compress_pak = true;\r
- printf ("Compressing pakfile\n");\r
- }\r
- else if (!strcmp(argv[i], "-pak"))\r
- {\r
- g_release = true;\r
- g_pak = true;\r
- printf ("Building pakfile: %s\n", argv[i+1]);\r
- BeginPak (argv[i+1]);\r
- i++;\r
- }\r
- else if (!strcmp(argv[i], "-only"))\r
- {\r
- strcpy (g_only, argv[i+1]);\r
- printf ("Only grabbing %s\n", g_only);\r
- i++;\r
- }\r
- else if (!strcmpi(argv[i], "-keypress"))\r
- {\r
- g_dokeypress = true;\r
- }\r
- else if (!strcmp(argv[i], "-3ds"))\r
- {\r
- do3ds = true;\r
- printf ("loading .3ds files\n");\r
- }\r
- else if (!strcmp(argv[i], "-materialfile"))\r
- {\r
- strcpy(g_materialFile, argv[i+1]);\r
- printf("Setting material file to %s\n", g_materialFile);\r
- i++;\r
- }\r
-/* else if (!strcmpi(argv[i], "-newgen"))\r
- {\r
- if (i < argc-4)\r
- {\r
- printf("run new triangle grouping routine here\n");\r
- NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4]));\r
- }\r
- else\r
- {\r
- printf("qdata -newskin <base.hrc> <skin.pcx> width height\n");\r
- }\r
- return 0;\r
- }\r
-*/ else if (!strcmpi(argv[i], "-genskin"))\r
- {\r
- i++;\r
- if (i < argc-3)\r
- {\r
- GenSkin(argv[i],argv[i+1],atol(argv[i+2]),atol(argv[i+3]));\r
- }\r
- else\r
- {\r
- printf("qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>\n");\r
- }\r
- return 0;\r
- \r
- }\r
- else if (!strcmpi(argv[i], "-noopts"))\r
- {\r
- g_no_opimizations = true;\r
- printf("not performing optimizations\n");\r
- }\r
- else if (!strcmpi(argv[i], "-md2"))\r
- {\r
- g_forcemodel = MODEL_MD2;\r
- }\r
- else if (!strcmpi(argv[i], "-fm"))\r
- {\r
- g_forcemodel = MODEL_FM;\r
- }\r
- else if (!strcmpi(argv[i], "-verbose"))\r
- {\r
- g_verbose = true;\r
- }\r
- else if (!strcmpi(argv[i], "-oldskin"))\r
- {\r
- g_allow_newskin = false;\r
- }\r
- else if (!strcmpi(argv[i], "-ignoreUV"))\r
- {\r
- g_ignoreTriUV = true;\r
- }\r
- else if (!strcmpi(argv[i], "-publish"))\r
- {\r
- g_publishOutput = true;\r
- }\r
- else if (!strcmpi(argv[i], "-nomkdir"))\r
- {\r
- g_nomkdir = true;\r
- }\r
- else if (argv[i][0] == '-')\r
- Error ("Unknown option \"%s\"", argv[i]);\r
- else\r
- break;\r
- }\r
-\r
- if (i >= argc)\r
- {\r
- Error ("usage: qdata [-archive <directory>]\n"\r
- " [-release <directory>]\n"\r
- " [-base <directory>]\n"\r
- " [-compress]\n"\r
- " [-pak <file>]\n"\r
- " [-only <model>]\n"\r
- " [-keypress]\n"\r
- " [-3ds]\n"\r
- " [-materialfile <file>]\n"\r
- " [-noopts]\n"\r
- " [-md2]\n"\r
- " [-fm]\n"\r
- " [-verbose]\n"\r
- " [-ignoreUV]\n"\r
- " [-oldskin]\n"\r
- " [-publish]\n"\r
- " [-nomkdir]\n"\r
- " file.qdt\n"\r
- "or\n"\r
- " qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>");\r
- }\r
-\r
- if (do3ds)\r
- trifileext = ext_3ds;\r
- else\r
- trifileext = ext_tri;\r
-\r
- for ( ; i<argc ; i++)\r
- {\r
- printf ("--------------- %s ---------------\n", argv[i]);\r
- // load the script\r
- strcpy (path, argv[i]);\r
- DefaultExtension (path, ".qdt");\r
- DefaultExtension(g_materialFile, ".mat");\r
- SetQdirFromPath (path);\r
-\r
- printf("workingdir='%s'\n", gamedir);\r
- if (basedir)\r
- {\r
- qdir[0] = 0;\r
- g_outputDir = basedir;\r
- }\r
-\r
- printf("outputdir='%s'\n", g_outputDir);\r
-\r
- QFile_ReadMaterialTypes(g_materialFile);\r
- LoadScriptFile (ExpandArg(path));\r
- \r
- //\r
- // parse it\r
- //\r
- ParseScript ();\r
-\r
- // write out the last model\r
- FinishModel ();\r
- FMFinishModel ();\r
- FinishSprite ();\r
- }\r
-\r
- if (total_textures)\r
- {\r
- printf("\n");\r
- printf("Total textures processed: %d\n",total_textures);\r
- printf("Average size: %d x %d\n",total_x / total_textures, total_y / total_textures);\r
- }\r
-\r
- if (g_pak)\r
- FinishPak ();\r
-\r
- endtime = I_FloatTime();\r
- printf("Time elapsed: %f\n", endtime-starttime);\r
- \r
- if (g_dokeypress)\r
- {\r
- printf("Success! ... Hit a key: ");\r
- getchar();\r
- }\r
-\r
- return 0;\r
-}\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 "md4.h"
+
+void TK_Init();
+
+qboolean g_compress_pak;
+qboolean g_release; // don't grab, copy output data to new tree
+qboolean g_pak; // if true, copy to pak instead of release
+char g_releasedir[1024]; // c:\quake2\baseq2, etc
+qboolean g_archive; // don't grab, copy source data to new tree
+qboolean do3ds;
+char g_only[256]; // if set, only grab this cd
+qboolean g_skipmodel; // set true when a cd is not g_only
+int g_forcemodel = MODEL_AUTO;
+qboolean g_verbose = false;
+qboolean g_allow_newskin = true;
+qboolean g_ignoreTriUV = false;
+qboolean g_publishOutput = false;
+
+char *ext_3ds = "3ds";
+char *ext_tri = "tri";
+char *trifileext;
+
+char g_materialFile[256] = "none"; // default for Heretic2
+char *g_outputDir;
+extern char *g_publishDir;
+
+extern qboolean g_nomkdir;
+
+/*
+ =======================================================
+
+ PAK FILES
+
+ =======================================================
+ */
+
+typedef struct
+{
+ char name[56];
+ int filepos, filelen;
+} packfile_t;
+
+typedef struct
+{
+ char id[4];
+ int dirofs;
+ int dirlen;
+} packheader_t;
+
+packfile_t pfiles[16384];
+FILE *pakfile;
+packfile_t *pf;
+packheader_t pakheader;
+
+
+
+/*
+ ==============
+ BeginPak
+ ==============
+ */
+void BeginPak( char *outname ){
+ if ( !g_pak ) {
+ return;
+ }
+
+ pakfile = SafeOpenWrite( outname );
+
+ // leave space for header
+ SafeWrite( pakfile, &pakheader, sizeof( pakheader ) );
+
+ pf = pfiles;
+}
+
+
+/*
+ ==============
+ ReleaseFile
+
+ Filename should be gamedir reletive.
+ Either copies the file to the release dir, or adds it to
+ the pak file.
+ ==============
+ */
+void ReleaseFile( char *filename ){
+ int len;
+ byte *buf;
+ char source[1024];
+ char dest[1024];
+
+ if ( !g_release ) {
+ return;
+ }
+
+ sprintf( source, "%s%s", gamedir, filename );
+
+ if ( !g_pak ) { // copy it
+ sprintf( dest, "%s/%s", g_releasedir, filename );
+ printf( "copying to %s\n", dest );
+ QCopyFile( source, dest );
+ return;
+ }
+
+ // pak it
+ printf( "paking %s\n", filename );
+ if ( strlen( filename ) >= sizeof( pf->name ) ) {
+ Error( "Filename too long for pak: %s", filename );
+ }
+
+ len = LoadFile( source, (void **)&buf );
+
+ // segment moved to old.c
+
+ strcpy( pf->name, filename );
+ pf->filepos = LittleLong( ftell( pakfile ) );
+ pf->filelen = LittleLong( len );
+ pf++;
+
+ SafeWrite( pakfile, buf, len );
+
+ free( buf );
+}
+
+
+/*
+ ==============
+ FinishPak
+ ==============
+ */
+void FinishPak( void ){
+ int dirlen;
+ int d;
+ int i;
+ unsigned checksum;
+
+ if ( !g_pak ) {
+ return;
+ }
+
+ pakheader.id[0] = 'P';
+ pakheader.id[1] = 'A';
+ pakheader.id[2] = 'C';
+ pakheader.id[3] = 'K';
+ dirlen = (byte *)pf - (byte *)pfiles;
+ pakheader.dirofs = LittleLong( ftell( pakfile ) );
+ pakheader.dirlen = LittleLong( dirlen );
+
+ checksum = Com_BlockChecksum( (void *)pfiles, dirlen );
+
+ SafeWrite( pakfile, pfiles, dirlen );
+
+ i = ftell( pakfile );
+
+ fseek( pakfile, 0, SEEK_SET );
+ SafeWrite( pakfile, &pakheader, sizeof( pakheader ) );
+ fclose( pakfile );
+
+ d = pf - pfiles;
+ printf( "%i files packed in %i bytes\n",d, i );
+ printf( "checksum: 0x%x\n", checksum );
+}
+
+
+/*
+ ===============
+ Cmd_File
+
+ This is only used to cause a file to be copied during a release
+ build (default.cfg, maps, etc)
+ ===============
+ */
+void Cmd_File( void ){
+ GetScriptToken( false );
+ ReleaseFile( token );
+}
+
+/*
+ ===============
+ PackDirectory_r
+
+ ===============
+ */
+#ifdef _WIN32
+#include "io.h"
+void PackDirectory_r( char *dir ){
+ struct _finddata_t fileinfo;
+ int handle;
+ char dirstring[1024];
+ char filename[1024];
+
+ sprintf( dirstring, "%s%s/*.*", gamedir, dir );
+
+ handle = _findfirst( dirstring, &fileinfo );
+ if ( handle == -1 ) {
+ return;
+ }
+
+ do
+ {
+ sprintf( filename, "%s/%s", dir, fileinfo.name );
+ if ( fileinfo.attrib & _A_SUBDIR ) { // directory
+ if ( fileinfo.name[0] != '.' ) { // don't pak . and ..
+ PackDirectory_r( filename );
+ }
+ continue;
+ }
+ // copy or pack the file
+ ReleaseFile( filename );
+ } while ( _findnext( handle, &fileinfo ) != -1 );
+
+ _findclose( handle );
+}
+#else
+
+#include <sys/types.h>
+#ifdef NeXT
+#include <sys/dir.h>
+#else
+#include <dirent.h>
+#endif
+
+void PackDirectory_r( char *dir ){
+#ifdef NeXT
+ struct direct **namelist, *ent;
+#else
+ struct dirent **namelist, *ent;
+#endif
+ int count;
+ struct stat st;
+ int i;
+ int len;
+ char fullname[1024];
+ char dirstring[1024];
+ char *name;
+
+ sprintf( dirstring, "%s%s", gamedir, dir );
+ count = scandir( dirstring, &namelist, NULL, NULL );
+
+ for ( i = 0 ; i < count ; i++ )
+ {
+ ent = namelist[i];
+ name = ent->d_name;
+
+ if ( name[0] == '.' ) {
+ continue;
+ }
+
+ sprintf( fullname, "%s/%s", dir, name );
+ sprintf( dirstring, "%s%s/%s", gamedir, dir, name );
+
+ if ( stat( dirstring, &st ) == -1 ) {
+ Error( "fstating %s", pf->name );
+ }
+ if ( st.st_mode & S_IFDIR ) { // directory
+ PackDirectory_r( fullname );
+ continue;
+ }
+
+ // copy or pack the file
+ ReleaseFile( fullname );
+ }
+}
+#endif
+
+
+/*
+ ===============
+ Cmd_Dir
+
+ This is only used to cause a directory to be copied during a
+ release build (sounds, etc)
+ ===============
+ */
+void Cmd_Dir( void ){
+ GetScriptToken( false );
+ PackDirectory_r( token );
+}
+
+//========================================================================
+
+#define MAX_RTEX 16384
+int numrtex;
+char rtex[MAX_RTEX][64];
+
+void ReleaseTexture( char *name ){
+ int i;
+ char path[1024];
+
+ for ( i = 0 ; i < numrtex ; i++ )
+ if ( !Q_strcasecmp( name, rtex[i] ) ) {
+ return;
+ }
+
+ if ( numrtex == MAX_RTEX ) {
+ Error( "numrtex == MAX_RTEX" );
+ }
+
+ strcpy( rtex[i], name );
+ numrtex++;
+
+ sprintf( path, "textures/%s.wal", name );
+ ReleaseFile( path );
+}
+
+/*
+ ===============
+ Cmd_Maps
+
+ Only relevent for release and pak files.
+ Releases the .bsp files for the maps, and scans all of the files to
+ build a list of all textures used, which are then released.
+ ===============
+ */
+void Cmd_Maps( void ){
+ char map[1024];
+ int i;
+
+ while ( ScriptTokenAvailable() )
+ {
+ GetScriptToken( false );
+ sprintf( map, "maps/%s.bsp", token );
+ ReleaseFile( map );
+
+ if ( !g_release ) {
+ continue;
+ }
+
+ // get all the texture references
+ sprintf( map, "%smaps/%s.bsp", gamedir, token );
+ LoadBSPFileTexinfo( map );
+ for ( i = 0 ; i < numtexinfo ; i++ )
+ ReleaseTexture( texinfo[i].texture );
+ }
+}
+
+
+//==============================================================
+
+/*
+ ===============
+ ParseScript
+ ===============
+ */
+void ParseScript( void ){
+ while ( 1 )
+ {
+ do
+ { // look for a line starting with a $ command
+ GetScriptToken( true );
+ if ( endofscript ) {
+ return;
+ }
+ if ( token[0] == '$' ) {
+ break;
+ }
+ while ( ScriptTokenAvailable() )
+ GetScriptToken( false );
+ } while ( 1 );
+
+ //
+ // model commands
+ //
+ if ( !strcmp( token, "$modelname" ) ) {
+ MODELCMD_Modelname( MODEL_MD2 );
+ }
+ else if ( !strcmp( token, "$cd" ) ) {
+ MODELCMD_Cd( MODEL_MD2 );
+ }
+ else if ( !strcmp( token, "$origin" ) ) {
+ MODELCMD_Origin( MODEL_MD2 );
+ }
+ else if ( !strcmp( token, "$cluster" ) ) {
+ MODELCMD_Cluster( MODEL_MD2 );
+ }
+ else if ( !strcmp( token, "$base" ) ) {
+ MODELCMD_Base( MODEL_MD2 );
+ }
+ else if ( !strcmp( token, "$scale" ) ) {
+ MODELCMD_ScaleUp( MODEL_MD2 );
+ }
+ else if ( !strcmp( token, "$frame" ) ) {
+ MODELCMD_Frame( MODEL_MD2 );
+ }
+ else if ( !strcmp( token, "$skin" ) ) {
+ MODELCMD_Skin( MODEL_MD2 );
+ }
+ else if ( !strcmp( token, "$skinsize" ) ) {
+ MODELCMD_Skinsize( MODEL_MD2 );
+ }
+ //
+ // flexible model commands
+ //
+ else if ( !strcmp( token, "$fm_modelname" ) ) {
+ MODELCMD_Modelname( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_base" ) ) {
+ MODELCMD_Base( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_basest" ) ) {
+ MODELCMD_BaseST( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_cd" ) ) {
+ MODELCMD_Cd( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_origin" ) ) {
+ MODELCMD_Origin( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_cluster" ) ) {
+ MODELCMD_Cluster( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_skeleton" ) ) {
+ MODELCMD_Skeleton( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_scale" ) ) {
+ MODELCMD_ScaleUp( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_frame" ) ) {
+ MODELCMD_Frame( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_skeletal_frame" ) ) { // left in for compadibility with qdt already using fm_skeletal_frame
+ MODELCMD_Frame( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_skin" ) ) {
+ MODELCMD_Skin( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_skinsize" ) ) {
+ MODELCMD_Skinsize( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_begin_group" ) ) {
+ MODELCMD_BeginGroup( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_end_group" ) ) {
+ MODELCMD_EndGroup( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_referenced" ) ) {
+ MODELCMD_Referenced( MODEL_FM );
+ }
+ else if ( !strcmp( token, "$fm_node_order" ) ) {
+ MODELCMD_NodeOrder( MODEL_FM );
+ }
+
+ //
+ // sprite commands
+ //
+ else if ( !strcmp( token, "$spritename" ) ) {
+ Cmd_SpriteName();
+ }
+ else if ( !strcmp( token, "$sprdir" ) ) {
+ Cmd_Sprdir();
+ }
+ else if ( !strcmp( token, "$load" ) ) {
+ Cmd_Load();
+ }
+ else if ( !strcmp( token, "$spriteframe" ) ) {
+ Cmd_SpriteFrame();
+ }
+ //
+ // image commands
+ //
+ else if ( !strcmpi( token, "$grab" ) ) {
+ Cmd_Grab();
+ }
+ else if ( !strcmpi( token, "$raw" ) ) {
+ Cmd_Raw();
+ }
+ else if ( !strcmpi( token, "$colormap" ) ) {
+ Cmd_Colormap();
+ }
+ else if ( !strcmpi( token, "$mippal" ) ) {
+ Cmd_Mippal();
+ }
+ else if ( !strcmpi( token, "$mipdir" ) ) {
+ Cmd_Mipdir();
+ }
+ else if ( !strcmpi( token, "$mip" ) ) {
+ Cmd_Mip();
+ }
+ else if ( !strcmp( token, "$environment" ) ) {
+ Cmd_Environment();
+ }
+ //
+ // pics
+ //
+ else if ( !strcmp( token, "$picdir" ) ) {
+ Cmd_Picdir();
+ }
+ else if ( !strcmp( token, "$pic" ) ) {
+ Cmd_Pic();
+ }
+ //
+ // book
+ //
+ else if ( !strcmp( token, "$bookdir" ) ) {
+ Cmd_Bookdir();
+ }
+ else if ( !strcmp( token, "$book" ) ) {
+ Cmd_Book();
+ }
+ //
+ // tmix
+ //
+ else if ( !strcmp( token, "$texturemix" ) ) {
+ Cmd_TextureMix();
+ }
+ //
+ // video
+ //
+ else if ( !strcmp( token, "$video" ) ) {
+ Cmd_Video();
+ }
+ //
+ // misc
+ //
+ else if ( !strcmp( token, "$file" ) ) {
+ Cmd_File();
+ }
+ else if ( !strcmp( token, "$dir" ) ) {
+ Cmd_Dir();
+ }
+ else if ( !strcmp( token, "$maps" ) ) {
+ Cmd_Maps();
+ }
+ else if ( !strcmp( token, "$alphalight" ) ) {
+ Cmd_Alphalight();
+ }
+ else if ( !strcmp( token, "$inverse16table" ) ) {
+ Cmd_Inverse16Table();
+ }
+ else{
+ Error( "bad command %s\n", token );
+ }
+ }
+}
+
+//=======================================================
+
+/*
+ ==============
+ main
+ ==============
+ */
+int main( int argc, char **argv ){
+ int i;
+ char path[1024];
+ char *basedir;
+ double starttime, endtime;
+
+ printf( "Qdata Plus : "__TIME__ " "__DATE__ "\n" );
+
+ starttime = I_FloatTime();
+ basedir = NULL;
+
+ TK_Init();
+ ExpandWildcards( &argc, &argv );
+
+ for ( i = 1 ; i < argc ; i++ )
+ {
+ if ( !strcmp( argv[i], "-archive" ) ) {
+ // -archive f:/quake2/release/dump_11_30
+ archive = true;
+ strcpy( archivedir, argv[i + 1] );
+ printf( "Archiving source to: %s\n", archivedir );
+ i++;
+ }
+ else if ( !strcmp( argv[i], "-release" ) ) {
+ g_release = true;
+ strcpy( g_releasedir, argv[i + 1] );
+ printf( "Copy output to: %s\n", g_releasedir );
+ i++;
+ }
+ else if ( !strcmp( argv[i], "-base" ) ) {
+ i++;
+ basedir = argv[i];
+ }
+ else if ( !strcmp( argv[i], "-compress" ) ) {
+ g_compress_pak = true;
+ printf( "Compressing pakfile\n" );
+ }
+ else if ( !strcmp( argv[i], "-pak" ) ) {
+ g_release = true;
+ g_pak = true;
+ printf( "Building pakfile: %s\n", argv[i + 1] );
+ BeginPak( argv[i + 1] );
+ i++;
+ }
+ else if ( !strcmp( argv[i], "-only" ) ) {
+ strcpy( g_only, argv[i + 1] );
+ printf( "Only grabbing %s\n", g_only );
+ i++;
+ }
+ else if ( !strcmpi( argv[i], "-keypress" ) ) {
+ g_dokeypress = true;
+ }
+ else if ( !strcmp( argv[i], "-3ds" ) ) {
+ do3ds = true;
+ printf( "loading .3ds files\n" );
+ }
+ else if ( !strcmp( argv[i], "-materialfile" ) ) {
+ strcpy( g_materialFile, argv[i + 1] );
+ printf( "Setting material file to %s\n", g_materialFile );
+ i++;
+ }
+/* else if (!strcmpi(argv[i], "-newgen"))
+ {
+ if (i < argc-4)
+ {
+ printf("run new triangle grouping routine here\n");
+ NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4]));
+ }
+ else
+ {
+ printf("qdata -newskin <base.hrc> <skin.pcx> width height\n");
+ }
+ return 0;
+ }
+ */ else if ( !strcmpi( argv[i], "-genskin" ) ) {
+ i++;
+ if ( i < argc - 3 ) {
+ GenSkin( argv[i],argv[i + 1],atol( argv[i + 2] ),atol( argv[i + 3] ) );
+ }
+ else
+ {
+ printf( "qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>\n" );
+ }
+ return 0;
+
+ }
+ else if ( !strcmpi( argv[i], "-noopts" ) ) {
+ g_no_opimizations = true;
+ printf( "not performing optimizations\n" );
+ }
+ else if ( !strcmpi( argv[i], "-md2" ) ) {
+ g_forcemodel = MODEL_MD2;
+ }
+ else if ( !strcmpi( argv[i], "-fm" ) ) {
+ g_forcemodel = MODEL_FM;
+ }
+ else if ( !strcmpi( argv[i], "-verbose" ) ) {
+ g_verbose = true;
+ }
+ else if ( !strcmpi( argv[i], "-oldskin" ) ) {
+ g_allow_newskin = false;
+ }
+ else if ( !strcmpi( argv[i], "-ignoreUV" ) ) {
+ g_ignoreTriUV = true;
+ }
+ else if ( !strcmpi( argv[i], "-publish" ) ) {
+ g_publishOutput = true;
+ }
+ else if ( !strcmpi( argv[i], "-nomkdir" ) ) {
+ g_nomkdir = true;
+ }
+ else if ( argv[i][0] == '-' ) {
+ Error( "Unknown option \"%s\"", argv[i] );
+ }
+ else{
+ break;
+ }
+ }
+
+ if ( i >= argc ) {
+ Error( "usage: qdata [-archive <directory>]\n"
+ " [-release <directory>]\n"
+ " [-base <directory>]\n"
+ " [-compress]\n"
+ " [-pak <file>]\n"
+ " [-only <model>]\n"
+ " [-keypress]\n"
+ " [-3ds]\n"
+ " [-materialfile <file>]\n"
+ " [-noopts]\n"
+ " [-md2]\n"
+ " [-fm]\n"
+ " [-verbose]\n"
+ " [-ignoreUV]\n"
+ " [-oldskin]\n"
+ " [-publish]\n"
+ " [-nomkdir]\n"
+ " file.qdt\n"
+ "or\n"
+ " qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>" );
+ }
+
+ if ( do3ds ) {
+ trifileext = ext_3ds;
+ }
+ else{
+ trifileext = ext_tri;
+ }
+
+ for ( ; i < argc ; i++ )
+ {
+ printf( "--------------- %s ---------------\n", argv[i] );
+ // load the script
+ strcpy( path, argv[i] );
+ DefaultExtension( path, ".qdt" );
+ DefaultExtension( g_materialFile, ".mat" );
+ SetQdirFromPath( path );
+
+ printf( "workingdir='%s'\n", gamedir );
+ if ( basedir ) {
+ qdir[0] = 0;
+ g_outputDir = basedir;
+ }
+
+ printf( "outputdir='%s'\n", g_outputDir );
+
+ QFile_ReadMaterialTypes( g_materialFile );
+ LoadScriptFile( ExpandArg( path ) );
+
+ //
+ // parse it
+ //
+ ParseScript();
+
+ // write out the last model
+ FinishModel();
+ FMFinishModel();
+ FinishSprite();
+ }
+
+ if ( total_textures ) {
+ printf( "\n" );
+ printf( "Total textures processed: %d\n",total_textures );
+ printf( "Average size: %d x %d\n",total_x / total_textures, total_y / total_textures );
+ }
+
+ if ( g_pak ) {
+ FinishPak();
+ }
+
+ endtime = I_FloatTime();
+ printf( "Time elapsed: %f\n", endtime - starttime );
+
+ if ( g_dokeypress ) {
+ printf( "Success! ... Hit a key: " );
+ getchar();
+ }
+
+ return 0;
+}