]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/qdata.c
eol style
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / qdata.c
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
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.
11
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.
16
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
20 */
21
22 #include "qdata.h"
23
24 void TK_Init();
25
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
31 qboolean        do3ds;
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;
39
40 char            *ext_3ds = "3ds";
41 char            *ext_tri= "tri";
42 char            *trifileext;
43
44 char            g_materialFile[256] = "none";   // default for Heretic2
45 char            *g_outputDir;
46 extern char *g_publishDir;
47
48 extern qboolean g_nomkdir;
49
50 /*
51 =======================================================
52
53   PAK FILES
54
55 =======================================================
56 */
57
58 typedef struct
59 {
60         char    name[56];
61         int             filepos, filelen;
62 } packfile_t;
63
64 typedef struct
65 {
66         char    id[4];
67         int             dirofs;
68         int             dirlen;
69 } packheader_t;
70
71 packfile_t              pfiles[16384];
72 FILE                    *pakfile;
73 packfile_t              *pf;
74 packheader_t    pakheader;
75
76
77
78 /*
79 ==============
80 BeginPak
81 ==============
82 */
83 void BeginPak (char *outname)
84 {
85         if (!g_pak)
86                 return;
87
88         pakfile = SafeOpenWrite (outname);
89
90         // leave space for header
91         SafeWrite (pakfile, &pakheader, sizeof(pakheader));
92         
93         pf = pfiles;
94 }
95
96
97 /*
98 ==============
99 ReleaseFile
100
101 Filename should be gamedir reletive.
102 Either copies the file to the release dir, or adds it to
103 the pak file.
104 ==============
105 */
106 void ReleaseFile (char *filename)
107 {
108         int             len;
109         byte    *buf;
110         char    source[1024];
111         char    dest[1024];
112
113         if (!g_release)
114                 return;
115
116         sprintf (source, "%s%s", gamedir, filename);
117
118         if (!g_pak)
119         {       // copy it
120                 sprintf (dest, "%s/%s", g_releasedir, filename);
121                 printf ("copying to %s\n", dest);
122                 QCopyFile (source, dest);
123                 return;
124         }
125
126         // pak it
127         printf ("paking %s\n", filename);
128         if (strlen(filename) >= sizeof(pf->name))
129                 Error ("Filename too long for pak: %s", filename);
130
131         len = LoadFile (source, (void **)&buf);
132
133         // segment moved to old.c
134
135         strcpy (pf->name, filename);
136         pf->filepos = LittleLong(ftell(pakfile));
137         pf->filelen = LittleLong(len);
138         pf++;
139
140         SafeWrite (pakfile, buf, len);
141
142         free (buf);
143 }
144
145
146 /*
147 ==============
148 FinishPak
149 ==============
150 */
151 void FinishPak (void)
152 {
153         int             dirlen;
154         int             d;
155         int             i;
156
157         if (!g_pak)
158                 return;
159
160         pakheader.id[0] = 'P';
161         pakheader.id[1] = 'A';
162         pakheader.id[2] = 'C';
163         pakheader.id[3] = 'K';
164         dirlen = (byte *)pf - (byte *)pfiles;
165         pakheader.dirofs = LittleLong(ftell(pakfile));
166         pakheader.dirlen = LittleLong(dirlen);
167         
168         SafeWrite (pakfile, pfiles, dirlen);
169
170         i = ftell (pakfile);
171          
172         fseek (pakfile, 0, SEEK_SET);
173         SafeWrite (pakfile, &pakheader, sizeof(pakheader));
174         fclose (pakfile);       
175         
176         d = pf - pfiles;
177         printf ("%i files packed in %i bytes\n",d, i);
178 }
179
180
181 /*
182 ===============
183 Cmd_File
184
185 This is only used to cause a file to be copied during a release
186 build (default.cfg, maps, etc)
187 ===============
188 */
189 void Cmd_File (void)
190 {
191         GetScriptToken (false);
192         ReleaseFile (token);
193 }
194
195 /*
196 ===============
197 PackDirectory_r
198
199 ===============
200 */
201 #ifdef _WIN32
202 #include "io.h"
203 void PackDirectory_r (char *dir)
204 {
205         struct _finddata_t fileinfo;
206         int             handle;
207         char    dirstring[1024];
208         char    filename[1024];
209
210         sprintf (dirstring, "%s%s/*.*", gamedir, dir);
211
212         handle = _findfirst (dirstring, &fileinfo);
213         if (handle == -1)
214                 return;
215
216         do
217         {
218                 sprintf (filename, "%s/%s", dir, fileinfo.name);
219                 if (fileinfo.attrib & _A_SUBDIR)
220                 {       // directory
221                         if (fileinfo.name[0] != '.')    // don't pak . and ..
222                                 PackDirectory_r (filename);
223                         continue;
224                 }
225                 // copy or pack the file
226                 ReleaseFile (filename);         
227         } while (_findnext( handle, &fileinfo ) != -1);
228
229         _findclose (handle);
230 }
231 #else
232
233 #include <sys/types.h>
234 #ifdef NeXT
235 #include <sys/dir.h>
236 #else
237 #include <dirent.h>
238 #endif
239
240 void PackDirectory_r (char *dir)
241 {
242 #ifdef NeXT
243         struct direct **namelist, *ent;
244 #else
245         struct dirent **namelist, *ent;
246 #endif
247         int             count;
248         struct stat st;
249         int                     i;
250         int                     len;
251         char            fullname[1024];
252         char            dirstring[1024];
253         char            *name;
254         
255         sprintf (dirstring, "%s%s", gamedir, dir);
256         count = scandir(dirstring, &namelist, NULL, NULL);
257         
258         for (i=0 ; i<count ; i++)
259         {
260                 ent = namelist[i];      
261                 name = ent->d_name;
262
263                 if (name[0] == '.')
264                         continue;
265         
266                 sprintf (fullname, "%s/%s", dir, name);
267                 sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
268                 
269                 if (stat (dirstring, &st) == -1)
270                         Error ("fstating %s", pf->name);
271                 if (st.st_mode & S_IFDIR)
272                 {       // directory
273                         PackDirectory_r (fullname);
274                         continue;
275                 }
276
277                 // copy or pack the file
278                 ReleaseFile (fullname);         
279         }
280 }
281 #endif
282
283
284 /*
285 ===============
286 Cmd_Dir
287
288 This is only used to cause a directory to be copied during a
289 release build (sounds, etc)
290 ===============
291 */
292 void Cmd_Dir (void)
293 {
294         GetScriptToken (false);
295         PackDirectory_r (token);        
296 }
297
298 //========================================================================
299
300 #define MAX_RTEX        16384
301 int             numrtex;
302 char    rtex[MAX_RTEX][64];
303
304 void ReleaseTexture (char *name)
305 {
306         int             i;
307         char    path[1024];
308
309         for (i=0 ; i<numrtex ; i++)
310                 if (!Q_strcasecmp(name, rtex[i]))
311                         return;
312
313         if (numrtex == MAX_RTEX)
314                 Error ("numrtex == MAX_RTEX");
315
316         strcpy (rtex[i], name);
317         numrtex++;
318
319         sprintf (path, "textures/%s.wal", name);
320         ReleaseFile (path);
321 }
322
323 /*
324 ===============
325 Cmd_Maps
326
327 Only relevent for release and pak files.
328 Releases the .bsp files for the maps, and scans all of the files to
329 build a list of all textures used, which are then released.
330 ===============
331 */
332 void Cmd_Maps (void)
333 {
334         char    map[1024];
335         int             i;
336
337         while (ScriptTokenAvailable ())
338         {
339                 GetScriptToken (false);
340                 sprintf (map, "maps/%s.bsp", token);
341                 ReleaseFile (map);
342
343                 if (!g_release)
344                         continue;
345
346                 // get all the texture references
347                 sprintf (map, "%smaps/%s.bsp", gamedir, token);
348                 LoadBSPFileTexinfo (map);
349                 for (i=0 ; i<numtexinfo ; i++)
350                         ReleaseTexture (texinfo[i].texture);
351         }
352 }
353
354
355 //==============================================================
356
357 /*
358 ===============
359 ParseScript
360 ===============
361 */
362 void ParseScript (void)
363 {
364         while (1)
365         {
366                 do
367                 {       // look for a line starting with a $ command
368                         GetScriptToken (true);
369                         if (endofscript)
370                                 return;
371                         if (token[0] == '$')
372                                 break;                          
373                         while (ScriptTokenAvailable())
374                                 GetScriptToken (false);
375                 } while (1);
376                 
377                 //
378                 // model commands
379                 //
380                 if (!strcmp (token, "$modelname"))
381                         MODELCMD_Modelname (MODEL_MD2);
382                 else if (!strcmp (token, "$cd"))
383                         MODELCMD_Cd (MODEL_MD2);
384                 else if (!strcmp (token, "$origin"))
385                         MODELCMD_Origin (MODEL_MD2);
386                 else if (!strcmp (token, "$cluster"))
387                         MODELCMD_Cluster (MODEL_MD2);
388                 else if (!strcmp (token, "$base"))
389                         MODELCMD_Base (MODEL_MD2);
390                 else if (!strcmp (token, "$scale"))
391                         MODELCMD_ScaleUp (MODEL_MD2);
392                 else if (!strcmp (token, "$frame"))
393                         MODELCMD_Frame (MODEL_MD2);
394                 else if (!strcmp (token, "$skin"))
395                         MODELCMD_Skin (MODEL_MD2);
396                 else if (!strcmp (token, "$skinsize"))
397                         MODELCMD_Skinsize (MODEL_MD2);
398                 //
399                 // flexible model commands
400                 //
401                 else if (!strcmp (token, "$fm_modelname"))
402                         MODELCMD_Modelname (MODEL_FM);
403                 else if (!strcmp (token, "$fm_base"))
404                         MODELCMD_Base (MODEL_FM);
405                 else if (!strcmp (token, "$fm_basest"))
406                         MODELCMD_BaseST (MODEL_FM);
407                 else if (!strcmp (token, "$fm_cd"))
408                         MODELCMD_Cd (MODEL_FM);
409                 else if (!strcmp (token, "$fm_origin"))
410                         MODELCMD_Origin (MODEL_FM);
411                 else if (!strcmp (token, "$fm_cluster"))
412                         MODELCMD_Cluster (MODEL_FM);
413                 else if (!strcmp (token, "$fm_skeleton"))
414                         MODELCMD_Skeleton (MODEL_FM);
415                 else if (!strcmp (token, "$fm_scale"))
416                         MODELCMD_ScaleUp (MODEL_FM);
417                 else if (!strcmp (token, "$fm_frame"))
418                         MODELCMD_Frame (MODEL_FM);
419                 else if (!strcmp (token, "$fm_skeletal_frame")) // left in for compadibility with qdt already using fm_skeletal_frame
420                         MODELCMD_Frame (MODEL_FM);
421                 else if (!strcmp (token, "$fm_skin"))
422                         MODELCMD_Skin (MODEL_FM);
423                 else if (!strcmp (token, "$fm_skinsize"))
424                         MODELCMD_Skinsize (MODEL_FM);
425                 else if (!strcmp (token, "$fm_begin_group"))
426                         MODELCMD_BeginGroup(MODEL_FM);
427                 else if (!strcmp (token, "$fm_end_group"))
428                         MODELCMD_EndGroup(MODEL_FM);
429                 else if (!strcmp (token, "$fm_referenced"))
430                         MODELCMD_Referenced(MODEL_FM);
431                 else if (!strcmp (token, "$fm_node_order"))
432                         MODELCMD_NodeOrder(MODEL_FM);
433                 
434                 //
435                 // sprite commands
436                 //
437                 else if (!strcmp (token, "$spritename"))
438                         Cmd_SpriteName ();
439                 else if (!strcmp (token, "$sprdir"))
440                         Cmd_Sprdir ();
441                 else if (!strcmp (token, "$load"))
442                         Cmd_Load ();
443                 else if (!strcmp (token, "$spriteframe"))
444                         Cmd_SpriteFrame ();
445                 //
446                 // image commands
447                 //
448                 else if (!strcmpi (token, "$grab"))
449                         Cmd_Grab ();
450                 else if (!strcmpi (token, "$raw"))
451                         Cmd_Raw ();
452                 else if (!strcmpi (token, "$colormap"))
453                         Cmd_Colormap ();
454                 else if (!strcmpi (token, "$mippal"))
455                         Cmd_Mippal ();
456                 else if (!strcmpi (token, "$mipdir"))
457                         Cmd_Mipdir ();
458                 else if (!strcmpi (token, "$mip"))
459                         Cmd_Mip ();
460                 else if (!strcmp (token, "$environment"))
461                         Cmd_Environment ();
462                 //
463                 // pics
464                 //
465                 else if (!strcmp (token, "$picdir"))
466                         Cmd_Picdir ();
467                 else if (!strcmp (token, "$pic"))
468                         Cmd_Pic ();
469                 //
470                 // book
471                 //
472                 else if (!strcmp (token, "$bookdir"))
473                         Cmd_Bookdir ();
474                 else if (!strcmp (token, "$book"))
475                         Cmd_Book ();
476                 //
477                 // tmix
478                 //
479                 else if (!strcmp (token, "$texturemix"))
480                         Cmd_TextureMix ();
481                 //
482                 // video
483                 //
484                 else if (!strcmp (token, "$video"))
485                         Cmd_Video ();
486                 //
487                 // misc
488                 //
489                 else if (!strcmp (token, "$file"))
490                         Cmd_File ();
491                 else if (!strcmp (token, "$dir"))
492                         Cmd_Dir ();
493                 else if (!strcmp (token, "$maps"))
494                         Cmd_Maps ();
495                 else if (!strcmp (token, "$alphalight"))
496                         Cmd_Alphalight ();
497                 else if (!strcmp (token, "$inverse16table" ))
498                         Cmd_Inverse16Table();
499                 else
500                         Error ("bad command %s\n", token);
501         }
502 }
503
504 //=======================================================
505
506 /*
507 ==============
508 main
509 ==============
510 */
511 int main (int argc, char **argv)
512 {
513         int                     i;
514         char            path[1024];
515         char            *basedir;
516         double          starttime, endtime;
517
518         printf ("Qdata Plus : "__TIME__" "__DATE__"\n");
519
520         starttime = I_FloatTime();
521         basedir = NULL;
522
523         TK_Init();
524         ExpandWildcards (&argc, &argv);
525
526         for (i=1 ; i<argc ; i++)
527         {
528                 if (!strcmp(argv[i], "-archive"))
529                 {
530                         // -archive f:/quake2/release/dump_11_30
531                         archive = true;
532                         strcpy (archivedir, argv[i+1]);
533                         printf ("Archiving source to: %s\n", archivedir);
534                         i++;
535                 }
536                 else if (!strcmp(argv[i], "-release"))
537                 {
538                         g_release = true;
539                         strcpy (g_releasedir, argv[i+1]);
540                         printf ("Copy output to: %s\n", g_releasedir);
541                         i++;
542                 }
543                 else if (!strcmp(argv[i], "-base"))
544                 {
545                         i++;
546                         basedir = argv[i];
547                 }
548                 else if (!strcmp(argv[i], "-compress"))
549                 {
550                         g_compress_pak = true;
551                         printf ("Compressing pakfile\n");
552                 }
553                 else if (!strcmp(argv[i], "-pak"))
554                 {
555                         g_release = true;
556                         g_pak = true;
557                         printf ("Building pakfile: %s\n", argv[i+1]);
558                         BeginPak (argv[i+1]);
559                         i++;
560                 }
561                 else if (!strcmp(argv[i], "-only"))
562                 {
563                         strcpy (g_only, argv[i+1]);
564                         printf ("Only grabbing %s\n", g_only);
565                         i++;
566                 }
567                 else if (!strcmpi(argv[i], "-keypress"))
568                 {
569                         g_dokeypress = true;
570                 }
571                 else if (!strcmp(argv[i], "-3ds"))
572                 {
573                         do3ds = true;
574                         printf ("loading .3ds files\n");
575                 }
576                 else if (!strcmp(argv[i], "-materialfile"))
577                 {
578                         strcpy(g_materialFile, argv[i+1]);
579                         printf("Setting material file to %s\n", g_materialFile);
580                         i++;
581                 }
582 /*              else if (!strcmpi(argv[i], "-newgen"))
583                 {
584                         if (i < argc-4)
585                         {
586                                 printf("run new triangle grouping routine here\n");
587                                 NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4]));
588                         }
589                         else
590                         {
591                                 printf("qdata -newskin <base.hrc> <skin.pcx> width height\n");
592                         }
593                         return 0;
594                 }
595 */              else if (!strcmpi(argv[i], "-genskin"))
596                 {
597                         i++;
598                         if (i < argc-3)
599                         {
600                                 GenSkin(argv[i],argv[i+1],atol(argv[i+2]),atol(argv[i+3]));
601                         }
602                         else
603                         {
604                                 printf("qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>\n");
605                         }
606                         return 0;
607                         
608                 }
609                 else if (!strcmpi(argv[i], "-noopts"))
610                 {
611                         g_no_opimizations = true;
612                         printf("not performing optimizations\n");
613                 }
614                 else if (!strcmpi(argv[i], "-md2"))
615                 {
616                         g_forcemodel = MODEL_MD2;
617                 }
618                 else if (!strcmpi(argv[i], "-fm"))
619                 {
620                         g_forcemodel = MODEL_FM;
621                 }
622                 else if (!strcmpi(argv[i], "-verbose"))
623                 {
624                         g_verbose = true;
625                 }
626                 else if (!strcmpi(argv[i], "-oldskin"))
627                 {
628                         g_allow_newskin = false;
629                 }
630                 else if (!strcmpi(argv[i], "-ignoreUV"))
631                 {
632                         g_ignoreTriUV = true;
633                 }
634                 else if (!strcmpi(argv[i], "-publish"))
635                 {
636                         g_publishOutput = true;
637                 }
638                 else if (!strcmpi(argv[i], "-nomkdir"))
639                 {
640                         g_nomkdir = true;
641                 }
642                 else if (argv[i][0] == '-')
643                         Error ("Unknown option \"%s\"", argv[i]);
644                 else
645                         break;
646         }
647
648         if (i >= argc)
649         {
650                 Error ("usage: qdata [-archive <directory>]\n"
651                         "             [-release <directory>]\n"
652                         "             [-base <directory>]\n"
653                         "             [-compress]\n"
654                         "             [-pak <file>]\n"
655                         "             [-only <model>]\n"
656                         "             [-keypress]\n"
657                         "             [-3ds]\n"
658                         "             [-materialfile <file>]\n"
659                         "             [-noopts]\n"
660                         "             [-md2]\n"
661                         "             [-fm]\n"
662                         "             [-verbose]\n"
663                         "             [-ignoreUV]\n"
664                         "             [-oldskin]\n"
665                         "             [-publish]\n"
666                         "             [-nomkdir]\n"
667                         "             file.qdt\n"
668                         "or\n"
669                         "       qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>");
670         }
671
672         if (do3ds)
673                 trifileext = ext_3ds;
674         else
675                 trifileext = ext_tri;
676
677         for ( ; i<argc ; i++)
678         {
679                 printf ("--------------- %s ---------------\n", argv[i]);
680                 // load the script
681                 strcpy (path, argv[i]);
682                 DefaultExtension (path, ".qdt");
683                 DefaultExtension(g_materialFile, ".mat");
684                 SetQdirFromPath (path);
685
686                 printf("workingdir='%s'\n", gamedir);
687                 if (basedir)
688                 {
689                         qdir[0] = 0;
690                         g_outputDir = basedir;
691                 }
692
693                 printf("outputdir='%s'\n", g_outputDir);
694
695                 QFile_ReadMaterialTypes(g_materialFile);
696                 LoadScriptFile (ExpandArg(path));
697                 
698                 //
699                 // parse it
700                 //
701                 ParseScript ();
702
703                 // write out the last model
704                 FinishModel ();
705                 FMFinishModel ();
706                 FinishSprite ();
707         }
708
709         if (total_textures)
710         {
711                 printf("\n");
712                 printf("Total textures processed: %d\n",total_textures);
713                 printf("Average size: %d x %d\n",total_x / total_textures, total_y / total_textures);
714         }
715
716         if (g_pak)
717                 FinishPak ();
718
719         endtime = I_FloatTime();
720         printf("Time elapsed:  %f\n", endtime-starttime);
721         
722         if (g_dokeypress)
723         {
724                 printf("Success! ... Hit a key: ");
725                 getchar();
726         }
727
728         return 0;
729 }
730