2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
26 qboolean g_compress_pak;
\r
27 qboolean g_release; // don't grab, copy output data to new tree
\r
28 qboolean g_pak; // if true, copy to pak instead of release
\r
29 char g_releasedir[1024]; // c:\quake2\baseq2, etc
\r
30 qboolean g_archive; // don't grab, copy source data to new tree
\r
32 char g_only[256]; // if set, only grab this cd
\r
33 qboolean g_skipmodel; // set true when a cd is not g_only
\r
34 int g_forcemodel = MODEL_AUTO;
\r
35 qboolean g_verbose = false;
\r
36 qboolean g_allow_newskin = true;
\r
37 qboolean g_ignoreTriUV = false;
\r
38 qboolean g_publishOutput = false;
\r
40 char *ext_3ds = "3ds";
\r
41 char *ext_tri= "tri";
\r
44 char g_materialFile[256] = "none"; // default for Heretic2
\r
46 extern char *g_publishDir;
\r
48 extern qboolean g_nomkdir;
\r
51 =======================================================
\r
55 =======================================================
\r
61 int filepos, filelen;
\r
71 packfile_t pfiles[16384];
\r
74 packheader_t pakheader;
\r
83 void BeginPak (char *outname)
\r
88 pakfile = SafeOpenWrite (outname);
\r
90 // leave space for header
\r
91 SafeWrite (pakfile, &pakheader, sizeof(pakheader));
\r
101 Filename should be gamedir reletive.
\r
102 Either copies the file to the release dir, or adds it to
\r
106 void ReleaseFile (char *filename)
\r
116 sprintf (source, "%s%s", gamedir, filename);
\r
120 sprintf (dest, "%s/%s", g_releasedir, filename);
\r
121 printf ("copying to %s\n", dest);
\r
122 QCopyFile (source, dest);
\r
127 printf ("paking %s\n", filename);
\r
128 if (strlen(filename) >= sizeof(pf->name))
\r
129 Error ("Filename too long for pak: %s", filename);
\r
131 len = LoadFile (source, (void **)&buf);
\r
133 // segment moved to old.c
\r
135 strcpy (pf->name, filename);
\r
136 pf->filepos = LittleLong(ftell(pakfile));
\r
137 pf->filelen = LittleLong(len);
\r
140 SafeWrite (pakfile, buf, len);
\r
151 void FinishPak (void)
\r
160 pakheader.id[0] = 'P';
\r
161 pakheader.id[1] = 'A';
\r
162 pakheader.id[2] = 'C';
\r
163 pakheader.id[3] = 'K';
\r
164 dirlen = (byte *)pf - (byte *)pfiles;
\r
165 pakheader.dirofs = LittleLong(ftell(pakfile));
\r
166 pakheader.dirlen = LittleLong(dirlen);
\r
168 SafeWrite (pakfile, pfiles, dirlen);
\r
170 i = ftell (pakfile);
\r
172 fseek (pakfile, 0, SEEK_SET);
\r
173 SafeWrite (pakfile, &pakheader, sizeof(pakheader));
\r
177 printf ("%i files packed in %i bytes\n",d, i);
\r
185 This is only used to cause a file to be copied during a release
\r
186 build (default.cfg, maps, etc)
\r
189 void Cmd_File (void)
\r
191 GetScriptToken (false);
\r
192 ReleaseFile (token);
\r
203 void PackDirectory_r (char *dir)
\r
205 struct _finddata_t fileinfo;
\r
207 char dirstring[1024];
\r
208 char filename[1024];
\r
210 sprintf (dirstring, "%s%s/*.*", gamedir, dir);
\r
212 handle = _findfirst (dirstring, &fileinfo);
\r
218 sprintf (filename, "%s/%s", dir, fileinfo.name);
\r
219 if (fileinfo.attrib & _A_SUBDIR)
\r
221 if (fileinfo.name[0] != '.') // don't pak . and ..
\r
222 PackDirectory_r (filename);
\r
225 // copy or pack the file
\r
226 ReleaseFile (filename);
\r
227 } while (_findnext( handle, &fileinfo ) != -1);
\r
229 _findclose (handle);
\r
233 #include <sys/types.h>
\r
235 #include <sys/dir.h>
\r
237 #include <dirent.h>
\r
240 void PackDirectory_r (char *dir)
\r
243 struct direct **namelist, *ent;
\r
245 struct dirent **namelist, *ent;
\r
251 char fullname[1024];
\r
252 char dirstring[1024];
\r
255 sprintf (dirstring, "%s%s", gamedir, dir);
\r
256 count = scandir(dirstring, &namelist, NULL, NULL);
\r
258 for (i=0 ; i<count ; i++)
\r
260 ent = namelist[i];
\r
261 name = ent->d_name;
\r
263 if (name[0] == '.')
\r
266 sprintf (fullname, "%s/%s", dir, name);
\r
267 sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
\r
269 if (stat (dirstring, &st) == -1)
\r
270 Error ("fstating %s", pf->name);
\r
271 if (st.st_mode & S_IFDIR)
\r
273 PackDirectory_r (fullname);
\r
277 // copy or pack the file
\r
278 ReleaseFile (fullname);
\r
288 This is only used to cause a directory to be copied during a
\r
289 release build (sounds, etc)
\r
292 void Cmd_Dir (void)
\r
294 GetScriptToken (false);
\r
295 PackDirectory_r (token);
\r
298 //========================================================================
\r
300 #define MAX_RTEX 16384
\r
302 char rtex[MAX_RTEX][64];
\r
304 void ReleaseTexture (char *name)
\r
309 for (i=0 ; i<numrtex ; i++)
\r
310 if (!Q_strcasecmp(name, rtex[i]))
\r
313 if (numrtex == MAX_RTEX)
\r
314 Error ("numrtex == MAX_RTEX");
\r
316 strcpy (rtex[i], name);
\r
319 sprintf (path, "textures/%s.wal", name);
\r
320 ReleaseFile (path);
\r
327 Only relevent for release and pak files.
\r
328 Releases the .bsp files for the maps, and scans all of the files to
\r
329 build a list of all textures used, which are then released.
\r
332 void Cmd_Maps (void)
\r
337 while (ScriptTokenAvailable ())
\r
339 GetScriptToken (false);
\r
340 sprintf (map, "maps/%s.bsp", token);
\r
346 // get all the texture references
\r
347 sprintf (map, "%smaps/%s.bsp", gamedir, token);
\r
348 LoadBSPFileTexinfo (map);
\r
349 for (i=0 ; i<numtexinfo ; i++)
\r
350 ReleaseTexture (texinfo[i].texture);
\r
355 //==============================================================
\r
362 void ParseScript (void)
\r
367 { // look for a line starting with a $ command
\r
368 GetScriptToken (true);
\r
371 if (token[0] == '$')
\r
373 while (ScriptTokenAvailable())
\r
374 GetScriptToken (false);
\r
380 if (!strcmp (token, "$modelname"))
\r
381 MODELCMD_Modelname (MODEL_MD2);
\r
382 else if (!strcmp (token, "$cd"))
\r
383 MODELCMD_Cd (MODEL_MD2);
\r
384 else if (!strcmp (token, "$origin"))
\r
385 MODELCMD_Origin (MODEL_MD2);
\r
386 else if (!strcmp (token, "$cluster"))
\r
387 MODELCMD_Cluster (MODEL_MD2);
\r
388 else if (!strcmp (token, "$base"))
\r
389 MODELCMD_Base (MODEL_MD2);
\r
390 else if (!strcmp (token, "$scale"))
\r
391 MODELCMD_ScaleUp (MODEL_MD2);
\r
392 else if (!strcmp (token, "$frame"))
\r
393 MODELCMD_Frame (MODEL_MD2);
\r
394 else if (!strcmp (token, "$skin"))
\r
395 MODELCMD_Skin (MODEL_MD2);
\r
396 else if (!strcmp (token, "$skinsize"))
\r
397 MODELCMD_Skinsize (MODEL_MD2);
\r
399 // flexible model commands
\r
401 else if (!strcmp (token, "$fm_modelname"))
\r
402 MODELCMD_Modelname (MODEL_FM);
\r
403 else if (!strcmp (token, "$fm_base"))
\r
404 MODELCMD_Base (MODEL_FM);
\r
405 else if (!strcmp (token, "$fm_basest"))
\r
406 MODELCMD_BaseST (MODEL_FM);
\r
407 else if (!strcmp (token, "$fm_cd"))
\r
408 MODELCMD_Cd (MODEL_FM);
\r
409 else if (!strcmp (token, "$fm_origin"))
\r
410 MODELCMD_Origin (MODEL_FM);
\r
411 else if (!strcmp (token, "$fm_cluster"))
\r
412 MODELCMD_Cluster (MODEL_FM);
\r
413 else if (!strcmp (token, "$fm_skeleton"))
\r
414 MODELCMD_Skeleton (MODEL_FM);
\r
415 else if (!strcmp (token, "$fm_scale"))
\r
416 MODELCMD_ScaleUp (MODEL_FM);
\r
417 else if (!strcmp (token, "$fm_frame"))
\r
418 MODELCMD_Frame (MODEL_FM);
\r
419 else if (!strcmp (token, "$fm_skeletal_frame")) // left in for compadibility with qdt already using fm_skeletal_frame
\r
420 MODELCMD_Frame (MODEL_FM);
\r
421 else if (!strcmp (token, "$fm_skin"))
\r
422 MODELCMD_Skin (MODEL_FM);
\r
423 else if (!strcmp (token, "$fm_skinsize"))
\r
424 MODELCMD_Skinsize (MODEL_FM);
\r
425 else if (!strcmp (token, "$fm_begin_group"))
\r
426 MODELCMD_BeginGroup(MODEL_FM);
\r
427 else if (!strcmp (token, "$fm_end_group"))
\r
428 MODELCMD_EndGroup(MODEL_FM);
\r
429 else if (!strcmp (token, "$fm_referenced"))
\r
430 MODELCMD_Referenced(MODEL_FM);
\r
431 else if (!strcmp (token, "$fm_node_order"))
\r
432 MODELCMD_NodeOrder(MODEL_FM);
\r
437 else if (!strcmp (token, "$spritename"))
\r
439 else if (!strcmp (token, "$sprdir"))
\r
441 else if (!strcmp (token, "$load"))
\r
443 else if (!strcmp (token, "$spriteframe"))
\r
444 Cmd_SpriteFrame ();
\r
448 else if (!strcmpi (token, "$grab"))
\r
450 else if (!strcmpi (token, "$raw"))
\r
452 else if (!strcmpi (token, "$colormap"))
\r
454 else if (!strcmpi (token, "$mippal"))
\r
456 else if (!strcmpi (token, "$mipdir"))
\r
458 else if (!strcmpi (token, "$mip"))
\r
460 else if (!strcmp (token, "$environment"))
\r
461 Cmd_Environment ();
\r
465 else if (!strcmp (token, "$picdir"))
\r
467 else if (!strcmp (token, "$pic"))
\r
472 else if (!strcmp (token, "$bookdir"))
\r
474 else if (!strcmp (token, "$book"))
\r
479 else if (!strcmp (token, "$texturemix"))
\r
484 else if (!strcmp (token, "$video"))
\r
489 else if (!strcmp (token, "$file"))
\r
491 else if (!strcmp (token, "$dir"))
\r
493 else if (!strcmp (token, "$maps"))
\r
495 else if (!strcmp (token, "$alphalight"))
\r
497 else if (!strcmp (token, "$inverse16table" ))
\r
498 Cmd_Inverse16Table();
\r
500 Error ("bad command %s\n", token);
\r
504 //=======================================================
\r
511 int main (int argc, char **argv)
\r
516 double starttime, endtime;
\r
518 printf ("Qdata Plus : "__TIME__" "__DATE__"\n");
\r
520 starttime = I_FloatTime();
\r
524 ExpandWildcards (&argc, &argv);
\r
526 for (i=1 ; i<argc ; i++)
\r
528 if (!strcmp(argv[i], "-archive"))
\r
530 // -archive f:/quake2/release/dump_11_30
\r
532 strcpy (archivedir, argv[i+1]);
\r
533 printf ("Archiving source to: %s\n", archivedir);
\r
536 else if (!strcmp(argv[i], "-release"))
\r
539 strcpy (g_releasedir, argv[i+1]);
\r
540 printf ("Copy output to: %s\n", g_releasedir);
\r
543 else if (!strcmp(argv[i], "-base"))
\r
548 else if (!strcmp(argv[i], "-compress"))
\r
550 g_compress_pak = true;
\r
551 printf ("Compressing pakfile\n");
\r
553 else if (!strcmp(argv[i], "-pak"))
\r
557 printf ("Building pakfile: %s\n", argv[i+1]);
\r
558 BeginPak (argv[i+1]);
\r
561 else if (!strcmp(argv[i], "-only"))
\r
563 strcpy (g_only, argv[i+1]);
\r
564 printf ("Only grabbing %s\n", g_only);
\r
567 else if (!strcmpi(argv[i], "-keypress"))
\r
569 g_dokeypress = true;
\r
571 else if (!strcmp(argv[i], "-3ds"))
\r
574 printf ("loading .3ds files\n");
\r
576 else if (!strcmp(argv[i], "-materialfile"))
\r
578 strcpy(g_materialFile, argv[i+1]);
\r
579 printf("Setting material file to %s\n", g_materialFile);
\r
582 /* else if (!strcmpi(argv[i], "-newgen"))
\r
586 printf("run new triangle grouping routine here\n");
\r
587 NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4]));
\r
591 printf("qdata -newskin <base.hrc> <skin.pcx> width height\n");
\r
595 */ else if (!strcmpi(argv[i], "-genskin"))
\r
600 GenSkin(argv[i],argv[i+1],atol(argv[i+2]),atol(argv[i+3]));
\r
604 printf("qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>\n");
\r
609 else if (!strcmpi(argv[i], "-noopts"))
\r
611 g_no_opimizations = true;
\r
612 printf("not performing optimizations\n");
\r
614 else if (!strcmpi(argv[i], "-md2"))
\r
616 g_forcemodel = MODEL_MD2;
\r
618 else if (!strcmpi(argv[i], "-fm"))
\r
620 g_forcemodel = MODEL_FM;
\r
622 else if (!strcmpi(argv[i], "-verbose"))
\r
626 else if (!strcmpi(argv[i], "-oldskin"))
\r
628 g_allow_newskin = false;
\r
630 else if (!strcmpi(argv[i], "-ignoreUV"))
\r
632 g_ignoreTriUV = true;
\r
634 else if (!strcmpi(argv[i], "-publish"))
\r
636 g_publishOutput = true;
\r
638 else if (!strcmpi(argv[i], "-nomkdir"))
\r
642 else if (argv[i][0] == '-')
\r
643 Error ("Unknown option \"%s\"", argv[i]);
\r
650 Error ("usage: qdata [-archive <directory>]\n"
\r
651 " [-release <directory>]\n"
\r
652 " [-base <directory>]\n"
\r
655 " [-only <model>]\n"
\r
658 " [-materialfile <file>]\n"
\r
669 " qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>");
\r
673 trifileext = ext_3ds;
\r
675 trifileext = ext_tri;
\r
677 for ( ; i<argc ; i++)
\r
679 printf ("--------------- %s ---------------\n", argv[i]);
\r
681 strcpy (path, argv[i]);
\r
682 DefaultExtension (path, ".qdt");
\r
683 DefaultExtension(g_materialFile, ".mat");
\r
684 SetQdirFromPath (path);
\r
686 printf("workingdir='%s'\n", gamedir);
\r
690 g_outputDir = basedir;
\r
693 printf("outputdir='%s'\n", g_outputDir);
\r
695 QFile_ReadMaterialTypes(g_materialFile);
\r
696 LoadScriptFile (ExpandArg(path));
\r
703 // write out the last model
\r
709 if (total_textures)
\r
712 printf("Total textures processed: %d\n",total_textures);
\r
713 printf("Average size: %d x %d\n",total_x / total_textures, total_y / total_textures);
\r
719 endtime = I_FloatTime();
\r
720 printf("Time elapsed: %f\n", endtime-starttime);
\r
724 printf("Success! ... Hit a key: ");
\r