2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 qboolean g_compress_pak;
27 qboolean g_release; // don't grab, copy output data to new tree
28 qboolean g_pak; // if true, copy to pak instead of release
29 char g_releasedir[1024]; // c:\quake2\baseq2, etc
30 qboolean g_archive; // don't grab, copy source data to new tree
32 char g_only[256]; // if set, only grab this cd
33 qboolean g_skipmodel; // set true when a cd is not g_only
34 int g_forcemodel = MODEL_AUTO;
35 qboolean g_verbose = false;
36 qboolean g_allow_newskin = true;
37 qboolean g_ignoreTriUV = false;
38 qboolean g_publishOutput = false;
40 char *ext_3ds = "3ds";
44 char g_materialFile[256] = "none"; // default for Heretic2
46 extern char *g_publishDir;
48 extern qboolean g_nomkdir;
51 =======================================================
55 =======================================================
58 unsigned Com_BlockChecksum (void *buffer, int length);
73 packfile_t pfiles[16384];
76 packheader_t pakheader;
85 void BeginPak (char *outname)
90 pakfile = SafeOpenWrite (outname);
92 // leave space for header
93 SafeWrite (pakfile, &pakheader, sizeof(pakheader));
103 Filename should be gamedir reletive.
104 Either copies the file to the release dir, or adds it to
108 void ReleaseFile (char *filename)
118 sprintf (source, "%s%s", gamedir, filename);
122 sprintf (dest, "%s/%s", g_releasedir, filename);
123 printf ("copying to %s\n", dest);
124 QCopyFile (source, dest);
129 printf ("paking %s\n", filename);
130 if (strlen(filename) >= sizeof(pf->name))
131 Error ("Filename too long for pak: %s", filename);
133 len = LoadFile (source, (void **)&buf);
135 // segment moved to old.c
137 strcpy (pf->name, filename);
138 pf->filepos = LittleLong(ftell(pakfile));
139 pf->filelen = LittleLong(len);
142 SafeWrite (pakfile, buf, len);
153 void FinishPak (void)
163 pakheader.id[0] = 'P';
164 pakheader.id[1] = 'A';
165 pakheader.id[2] = 'C';
166 pakheader.id[3] = 'K';
167 dirlen = (byte *)pf - (byte *)pfiles;
168 pakheader.dirofs = LittleLong(ftell(pakfile));
169 pakheader.dirlen = LittleLong(dirlen);
171 checksum = Com_BlockChecksum ( (void *)pfiles, dirlen );
173 SafeWrite (pakfile, pfiles, dirlen);
177 fseek (pakfile, 0, SEEK_SET);
178 SafeWrite (pakfile, &pakheader, sizeof(pakheader));
182 printf ("%i files packed in %i bytes\n",d, i);
183 printf ("checksum: 0x%x\n", checksum);
191 This is only used to cause a file to be copied during a release
192 build (default.cfg, maps, etc)
197 GetScriptToken (false);
209 void PackDirectory_r (char *dir)
211 struct _finddata_t fileinfo;
213 char dirstring[1024];
216 sprintf (dirstring, "%s%s/*.*", gamedir, dir);
218 handle = _findfirst (dirstring, &fileinfo);
224 sprintf (filename, "%s/%s", dir, fileinfo.name);
225 if (fileinfo.attrib & _A_SUBDIR)
227 if (fileinfo.name[0] != '.') // don't pak . and ..
228 PackDirectory_r (filename);
231 // copy or pack the file
232 ReleaseFile (filename);
233 } while (_findnext( handle, &fileinfo ) != -1);
239 #include <sys/types.h>
246 void PackDirectory_r (char *dir)
249 struct direct **namelist, *ent;
251 struct dirent **namelist, *ent;
258 char dirstring[1024];
261 sprintf (dirstring, "%s%s", gamedir, dir);
262 count = scandir(dirstring, &namelist, NULL, NULL);
264 for (i=0 ; i<count ; i++)
272 sprintf (fullname, "%s/%s", dir, name);
273 sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
275 if (stat (dirstring, &st) == -1)
276 Error ("fstating %s", pf->name);
277 if (st.st_mode & S_IFDIR)
279 PackDirectory_r (fullname);
283 // copy or pack the file
284 ReleaseFile (fullname);
294 This is only used to cause a directory to be copied during a
295 release build (sounds, etc)
300 GetScriptToken (false);
301 PackDirectory_r (token);
304 //========================================================================
306 #define MAX_RTEX 16384
308 char rtex[MAX_RTEX][64];
310 void ReleaseTexture (char *name)
315 for (i=0 ; i<numrtex ; i++)
316 if (!Q_strcasecmp(name, rtex[i]))
319 if (numrtex == MAX_RTEX)
320 Error ("numrtex == MAX_RTEX");
322 strcpy (rtex[i], name);
325 sprintf (path, "textures/%s.wal", name);
333 Only relevent for release and pak files.
334 Releases the .bsp files for the maps, and scans all of the files to
335 build a list of all textures used, which are then released.
343 while (ScriptTokenAvailable ())
345 GetScriptToken (false);
346 sprintf (map, "maps/%s.bsp", token);
352 // get all the texture references
353 sprintf (map, "%smaps/%s.bsp", gamedir, token);
354 LoadBSPFileTexinfo (map);
355 for (i=0 ; i<numtexinfo ; i++)
356 ReleaseTexture (texinfo[i].texture);
361 //==============================================================
368 void ParseScript (void)
373 { // look for a line starting with a $ command
374 GetScriptToken (true);
379 while (ScriptTokenAvailable())
380 GetScriptToken (false);
386 if (!strcmp (token, "$modelname"))
387 MODELCMD_Modelname (MODEL_MD2);
388 else if (!strcmp (token, "$cd"))
389 MODELCMD_Cd (MODEL_MD2);
390 else if (!strcmp (token, "$origin"))
391 MODELCMD_Origin (MODEL_MD2);
392 else if (!strcmp (token, "$cluster"))
393 MODELCMD_Cluster (MODEL_MD2);
394 else if (!strcmp (token, "$base"))
395 MODELCMD_Base (MODEL_MD2);
396 else if (!strcmp (token, "$scale"))
397 MODELCMD_ScaleUp (MODEL_MD2);
398 else if (!strcmp (token, "$frame"))
399 MODELCMD_Frame (MODEL_MD2);
400 else if (!strcmp (token, "$skin"))
401 MODELCMD_Skin (MODEL_MD2);
402 else if (!strcmp (token, "$skinsize"))
403 MODELCMD_Skinsize (MODEL_MD2);
405 // flexible model commands
407 else if (!strcmp (token, "$fm_modelname"))
408 MODELCMD_Modelname (MODEL_FM);
409 else if (!strcmp (token, "$fm_base"))
410 MODELCMD_Base (MODEL_FM);
411 else if (!strcmp (token, "$fm_basest"))
412 MODELCMD_BaseST (MODEL_FM);
413 else if (!strcmp (token, "$fm_cd"))
414 MODELCMD_Cd (MODEL_FM);
415 else if (!strcmp (token, "$fm_origin"))
416 MODELCMD_Origin (MODEL_FM);
417 else if (!strcmp (token, "$fm_cluster"))
418 MODELCMD_Cluster (MODEL_FM);
419 else if (!strcmp (token, "$fm_skeleton"))
420 MODELCMD_Skeleton (MODEL_FM);
421 else if (!strcmp (token, "$fm_scale"))
422 MODELCMD_ScaleUp (MODEL_FM);
423 else if (!strcmp (token, "$fm_frame"))
424 MODELCMD_Frame (MODEL_FM);
425 else if (!strcmp (token, "$fm_skeletal_frame")) // left in for compadibility with qdt already using fm_skeletal_frame
426 MODELCMD_Frame (MODEL_FM);
427 else if (!strcmp (token, "$fm_skin"))
428 MODELCMD_Skin (MODEL_FM);
429 else if (!strcmp (token, "$fm_skinsize"))
430 MODELCMD_Skinsize (MODEL_FM);
431 else if (!strcmp (token, "$fm_begin_group"))
432 MODELCMD_BeginGroup(MODEL_FM);
433 else if (!strcmp (token, "$fm_end_group"))
434 MODELCMD_EndGroup(MODEL_FM);
435 else if (!strcmp (token, "$fm_referenced"))
436 MODELCMD_Referenced(MODEL_FM);
437 else if (!strcmp (token, "$fm_node_order"))
438 MODELCMD_NodeOrder(MODEL_FM);
443 else if (!strcmp (token, "$spritename"))
445 else if (!strcmp (token, "$sprdir"))
447 else if (!strcmp (token, "$load"))
449 else if (!strcmp (token, "$spriteframe"))
454 else if (!strcmpi (token, "$grab"))
456 else if (!strcmpi (token, "$raw"))
458 else if (!strcmpi (token, "$colormap"))
460 else if (!strcmpi (token, "$mippal"))
462 else if (!strcmpi (token, "$mipdir"))
464 else if (!strcmpi (token, "$mip"))
466 else if (!strcmp (token, "$environment"))
471 else if (!strcmp (token, "$picdir"))
473 else if (!strcmp (token, "$pic"))
478 else if (!strcmp (token, "$bookdir"))
480 else if (!strcmp (token, "$book"))
485 else if (!strcmp (token, "$texturemix"))
490 else if (!strcmp (token, "$video"))
495 else if (!strcmp (token, "$file"))
497 else if (!strcmp (token, "$dir"))
499 else if (!strcmp (token, "$maps"))
501 else if (!strcmp (token, "$alphalight"))
503 else if (!strcmp (token, "$inverse16table" ))
504 Cmd_Inverse16Table();
506 Error ("bad command %s\n", token);
510 //=======================================================
517 int main (int argc, char **argv)
522 double starttime, endtime;
524 printf ("Qdata Plus : "__TIME__" "__DATE__"\n");
526 starttime = I_FloatTime();
530 ExpandWildcards (&argc, &argv);
532 for (i=1 ; i<argc ; i++)
534 if (!strcmp(argv[i], "-archive"))
536 // -archive f:/quake2/release/dump_11_30
538 strcpy (archivedir, argv[i+1]);
539 printf ("Archiving source to: %s\n", archivedir);
542 else if (!strcmp(argv[i], "-release"))
545 strcpy (g_releasedir, argv[i+1]);
546 printf ("Copy output to: %s\n", g_releasedir);
549 else if (!strcmp(argv[i], "-base"))
554 else if (!strcmp(argv[i], "-compress"))
556 g_compress_pak = true;
557 printf ("Compressing pakfile\n");
559 else if (!strcmp(argv[i], "-pak"))
563 printf ("Building pakfile: %s\n", argv[i+1]);
564 BeginPak (argv[i+1]);
567 else if (!strcmp(argv[i], "-only"))
569 strcpy (g_only, argv[i+1]);
570 printf ("Only grabbing %s\n", g_only);
573 else if (!strcmpi(argv[i], "-keypress"))
577 else if (!strcmp(argv[i], "-3ds"))
580 printf ("loading .3ds files\n");
582 else if (!strcmp(argv[i], "-materialfile"))
584 strcpy(g_materialFile, argv[i+1]);
585 printf("Setting material file to %s\n", g_materialFile);
588 /* else if (!strcmpi(argv[i], "-newgen"))
592 printf("run new triangle grouping routine here\n");
593 NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4]));
597 printf("qdata -newskin <base.hrc> <skin.pcx> width height\n");
601 */ else if (!strcmpi(argv[i], "-genskin"))
606 GenSkin(argv[i],argv[i+1],atol(argv[i+2]),atol(argv[i+3]));
610 printf("qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>\n");
615 else if (!strcmpi(argv[i], "-noopts"))
617 g_no_opimizations = true;
618 printf("not performing optimizations\n");
620 else if (!strcmpi(argv[i], "-md2"))
622 g_forcemodel = MODEL_MD2;
624 else if (!strcmpi(argv[i], "-fm"))
626 g_forcemodel = MODEL_FM;
628 else if (!strcmpi(argv[i], "-verbose"))
632 else if (!strcmpi(argv[i], "-oldskin"))
634 g_allow_newskin = false;
636 else if (!strcmpi(argv[i], "-ignoreUV"))
638 g_ignoreTriUV = true;
640 else if (!strcmpi(argv[i], "-publish"))
642 g_publishOutput = true;
644 else if (!strcmpi(argv[i], "-nomkdir"))
648 else if (argv[i][0] == '-')
649 Error ("Unknown option \"%s\"", argv[i]);
656 Error ("usage: qdata [-archive <directory>]\n"
657 " [-release <directory>]\n"
658 " [-base <directory>]\n"
664 " [-materialfile <file>]\n"
675 " qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>");
679 trifileext = ext_3ds;
681 trifileext = ext_tri;
683 for ( ; i<argc ; i++)
685 printf ("--------------- %s ---------------\n", argv[i]);
687 strcpy (path, argv[i]);
688 DefaultExtension (path, ".qdt");
689 DefaultExtension(g_materialFile, ".mat");
690 SetQdirFromPath (path);
692 printf("workingdir='%s'\n", gamedir);
696 g_outputDir = basedir;
699 printf("outputdir='%s'\n", g_outputDir);
701 QFile_ReadMaterialTypes(g_materialFile);
702 LoadScriptFile (ExpandArg(path));
709 // write out the last model
718 printf("Total textures processed: %d\n",total_textures);
719 printf("Average size: %d x %d\n",total_x / total_textures, total_y / total_textures);
725 endtime = I_FloatTime();
726 printf("Time elapsed: %f\n", endtime-starttime);
730 printf("Success! ... Hit a key: ");