]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/qdata/qdata.c
Centralise compile checks
[xonotic/netradiant.git] / tools / quake2 / extra / qdata / qdata.c
1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4
5 This file is part of Quake 2 Tools source code.
6
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, 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 Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22
23 #include "qdata.h"
24
25 qboolean        g_compress_pak;
26 qboolean        g_release;                      // don't grab, copy output data to new tree
27 qboolean        g_pak;                          // if true, copy to pak instead of release
28 char            g_releasedir[1024];     // c:\quake2\baseq2, etc
29 qboolean        g_archive;                      // don't grab, copy source data to new tree
30 qboolean        do3ds;
31 char            g_only[256];            // if set, only grab this cd
32 qboolean        g_skipmodel;            // set true when a cd is not g_only
33
34 char            *ext_3ds = "3ds";
35 char            *ext_tri= "tri";
36 char            *trifileext;
37
38 /*
39 =======================================================
40
41   PAK FILES
42
43 =======================================================
44 */
45
46 unsigned Com_BlockChecksum (void *buffer, int length);
47
48 typedef struct
49 {
50         char    name[56];
51         int             filepos, filelen;
52 } packfile_t;
53
54 typedef struct
55 {
56         char    id[4];
57         int             dirofs;
58         int             dirlen;
59 } packheader_t;
60
61 packfile_t              pfiles[16384];
62 FILE                    *pakfile;
63 packfile_t              *pf;
64 packheader_t    pakheader;
65
66
67
68 /*
69 ==============
70 BeginPak
71 ==============
72 */
73 void BeginPak (char *outname)
74 {
75         if (!g_pak)
76                 return;
77
78         pakfile = SafeOpenWrite (outname);
79
80         // leave space for header
81         SafeWrite (pakfile, &pakheader, sizeof(pakheader));
82
83         pf = pfiles;
84 }
85
86
87 /*
88 ==============
89 ReleaseFile
90
91 Filename should be gamedir reletive.
92 Either copies the file to the release dir, or adds it to
93 the pak file.
94 ==============
95 */
96 void ReleaseFile (char *filename)
97 {
98         int             len;
99         byte    *buf;
100         char    source[1024];
101         char    dest[1024];
102
103         if (!g_release)
104                 return;
105
106         sprintf (source, "%s%s", gamedir, filename);
107
108         if (!g_pak)
109         {       // copy it
110                 sprintf (dest, "%s/%s", g_releasedir, filename);
111                 printf ("copying to %s\n", dest);
112                 QCopyFile (source, dest);
113                 return;
114         }
115
116         // pak it
117         printf ("paking %s\n", filename);
118         if (strlen(filename) >= sizeof(pf->name))
119                 Error ("Filename too long for pak: %s", filename);
120
121         len = LoadFile (source, (void **)&buf);
122
123         if (g_compress_pak && len < 4096*1024 )
124         {
125                 cblock_t        in, out;
126                 cblock_t Huffman (cblock_t in);
127
128                 in.count = len;
129                 in.data = buf;
130
131                 out = Huffman (in);
132
133                 if (out.count < in.count)
134                 {
135                         printf ("   compressed from %i to %i\n", in.count, out.count);
136                         free (in.data);
137                         buf = out.data;
138                         len = out.count;
139                 }
140                 else
141                         free (out.data);
142         }
143
144         strcpy (pf->name, filename);
145         pf->filepos = LittleLong(ftell(pakfile));
146         pf->filelen = LittleLong(len);
147         pf++;
148
149         SafeWrite (pakfile, buf, len);
150
151         free (buf);
152 }
153
154
155 /*
156 ==============
157 FinishPak
158 ==============
159 */
160 void FinishPak (void)
161 {
162         int             dirlen;
163         int             d;
164         int             i;
165         unsigned        checksum;
166
167         if (!g_pak)
168                 return;
169
170         pakheader.id[0] = 'P';
171         pakheader.id[1] = 'A';
172         pakheader.id[2] = 'C';
173         pakheader.id[3] = 'K';
174         dirlen = (byte *)pf - (byte *)pfiles;
175         pakheader.dirofs = LittleLong(ftell(pakfile));
176         pakheader.dirlen = LittleLong(dirlen);
177
178         checksum = Com_BlockChecksum ( (void *)pfiles, dirlen );
179
180         SafeWrite (pakfile, pfiles, dirlen);
181
182         i = ftell (pakfile);
183
184         fseek (pakfile, 0, SEEK_SET);
185         SafeWrite (pakfile, &pakheader, sizeof(pakheader));
186         fclose (pakfile);
187
188         d = pf - pfiles;
189         printf ("%i files packed in %i bytes\n",d, i);
190         printf ("checksum: 0x%x\n", checksum);
191 }
192
193
194 /*
195 ===============
196 Cmd_File
197
198 This is only used to cause a file to be copied during a release
199 build (default.cfg, maps, etc)
200 ===============
201 */
202 void Cmd_File (void)
203 {
204         GetToken (false);
205         ReleaseFile (token);
206 }
207
208 /*
209 ===============
210 PackDirectory_r
211
212 ===============
213 */
214 #if GDEF_OS_WINDOWS
215 #include "io.h"
216 void PackDirectory_r (char *dir)
217 {
218         struct _finddata_t fileinfo;
219         int             handle;
220         char    dirstring[1024];
221         char    filename[1024];
222
223         sprintf (dirstring, "%s%s/*.*", gamedir, dir);
224
225         handle = _findfirst (dirstring, &fileinfo);
226         if (handle == -1)
227                 return;
228
229         do
230         {
231                 sprintf (filename, "%s/%s", dir, fileinfo.name);
232                 if (fileinfo.attrib & _A_SUBDIR)
233                 {       // directory
234                         if (fileinfo.name[0] != '.')    // don't pak . and ..
235                                 PackDirectory_r (filename);
236                         continue;
237                 }
238                 // copy or pack the file
239                 ReleaseFile (filename);
240         } while (_findnext( handle, &fileinfo ) != -1);
241
242         _findclose (handle);
243 }
244 #else
245
246 #include <sys/types.h>
247 #ifdef NeXT
248 #include <sys/dir.h>
249 #else
250 #include <sys/dirent.h>
251 #endif
252
253 void PackDirectory_r (char *dir)
254 {
255 #ifdef NeXT
256         struct direct **namelist, *ent;
257 #else
258         struct dirent **namelist, *ent;
259 #endif
260         int             count;
261         struct stat st;
262         int                     i;
263         int                     len;
264         char            fullname[1024];
265         char            dirstring[1024];
266         char            *name;
267
268         sprintf (dirstring, "%s%s", gamedir, dir);
269         count = scandir(dirstring, &namelist, NULL, NULL);
270
271         for (i=0 ; i<count ; i++)
272         {
273                 ent = namelist[i];
274                 name = ent->d_name;
275
276                 if (name[0] == '.')
277                         continue;
278
279                 sprintf (fullname, "%s/%s", dir, name);
280                 sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
281
282                 if (stat (dirstring, &st) == -1)
283                         Error ("fstating %s", pf->name);
284                 if (st.st_mode & S_IFDIR)
285                 {       // directory
286                         PackDirectory_r (fullname);
287                         continue;
288                 }
289
290                 // copy or pack the file
291                 ReleaseFile (fullname);
292         }
293 }
294 #endif
295
296
297 /*
298 ===============
299 Cmd_Dir
300
301 This is only used to cause a directory to be copied during a
302 release build (sounds, etc)
303 ===============
304 */
305 void Cmd_Dir (void)
306 {
307         GetToken (false);
308         PackDirectory_r (token);
309 }
310
311 //========================================================================
312
313 #define MAX_RTEX        16384
314 int             numrtex;
315 char    rtex[MAX_RTEX][64];
316
317 void ReleaseTexture (char *name)
318 {
319         int             i;
320         char    path[1024];
321
322         for (i=0 ; i<numrtex ; i++)
323                 if (!Q_strcasecmp(name, rtex[i]))
324                         return;
325
326         if (numrtex == MAX_RTEX)
327                 Error ("numrtex == MAX_RTEX");
328
329         strcpy (rtex[i], name);
330         numrtex++;
331
332         sprintf (path, "textures/%s.wal", name);
333         ReleaseFile (path);
334 }
335
336 /*
337 ===============
338 Cmd_Maps
339
340 Only relevent for release and pak files.
341 Releases the .bsp files for the maps, and scans all of the files to
342 build a list of all textures used, which are then released.
343 ===============
344 */
345 void Cmd_Maps (void)
346 {
347         char    map[1024];
348         int             i;
349
350         while (TokenAvailable ())
351         {
352                 GetToken (false);
353                 sprintf (map, "maps/%s.bsp", token);
354                 ReleaseFile (map);
355
356                 if (!g_release)
357                         continue;
358
359                 // get all the texture references
360                 sprintf (map, "%smaps/%s.bsp", gamedir, token);
361                 LoadBSPFileTexinfo (map);
362                 for (i=0 ; i<numtexinfo ; i++)
363                         ReleaseTexture (texinfo[i].texture);
364         }
365 }
366
367
368 //==============================================================
369
370 /*
371 ===============
372 ParseScript
373 ===============
374 */
375 void ParseScript (void)
376 {
377         while (1)
378         {
379                 do
380                 {       // look for a line starting with a $ command
381                         GetToken (true);
382                         if (endofscript)
383                                 return;
384                         if (token[0] == '$')
385                                 break;
386                         while (TokenAvailable())
387                                 GetToken (false);
388                 } while (1);
389
390                 //
391                 // model commands
392                 //
393                 if (!strcmp (token, "$modelname"))
394                         Cmd_Modelname ();
395                 else if (!strcmp (token, "$base"))
396                         Cmd_Base ();
397                 else if (!strcmp (token, "$cd"))
398                         Cmd_Cd ();
399                 else if (!strcmp (token, "$origin"))
400                         Cmd_Origin ();
401                 else if (!strcmp (token, "$scale"))
402                         Cmd_ScaleUp ();
403                 else if (!strcmp (token, "$frame"))
404                         Cmd_Frame ();
405                 else if (!strcmp (token, "$skin"))
406                         Cmd_Skin ();
407                 else if (!strcmp (token, "$skinsize"))
408                         Cmd_Skinsize ();
409                 //
410                 // sprite commands
411                 //
412                 else if (!strcmp (token, "$spritename"))
413                         Cmd_SpriteName ();
414                 else if (!strcmp (token, "$load"))
415                         Cmd_Load ();
416                 else if (!strcmp (token, "$spriteframe"))
417                         Cmd_SpriteFrame ();
418                 //
419                 // image commands
420                 //
421                 else if (!strcmp (token, "$grab"))
422                         Cmd_Grab ();
423                 else if (!strcmp (token, "$raw"))
424                         Cmd_Raw ();
425                 else if (!strcmp (token, "$colormap"))
426                         Cmd_Colormap ();
427                 else if (!strcmp (token, "$mippal"))
428                         Cmd_Mippal ();
429                 else if (!strcmp (token, "$mipdir"))
430                         Cmd_Mipdir ();
431                 else if (!strcmp (token, "$mip"))
432                         Cmd_Mip ();
433                 else if (!strcmp (token, "$environment"))
434                         Cmd_Environment ();
435                 //
436                 // video
437                 //
438                 else if (!strcmp (token, "$video"))
439                         Cmd_Video ();
440                 //
441                 // misc
442                 //
443                 else if (!strcmp (token, "$file"))
444                         Cmd_File ();
445                 else if (!strcmp (token, "$dir"))
446                         Cmd_Dir ();
447                 else if (!strcmp (token, "$maps"))
448                         Cmd_Maps ();
449                 else if (!strcmp (token, "$alphalight"))
450                         Cmd_Alphalight ();
451                 else if (!strcmp (token, "$inverse16table" ))
452                         Cmd_Inverse16Table();
453                 else
454                         Error ("bad command %s\n", token);
455         }
456 }
457
458 //=======================================================
459
460 /*
461 ==============
462 main
463 ==============
464 */
465 int main (int argc, char **argv)
466 {
467         static  int             i;              // VC4.2 compiler bug if auto...
468         char    path[1024];
469
470         ExpandWildcards (&argc, &argv);
471
472         for (i=1 ; i<argc ; i++)
473         {
474                 if (!strcmp(argv[i], "-archive"))
475                 {
476                         // -archive f:/quake2/release/dump_11_30
477                         archive = true;
478                         strcpy (archivedir, argv[i+1]);
479                         printf ("Archiving source to: %s\n", archivedir);
480                         i++;
481                 }
482                 else if (!strcmp(argv[i], "-release"))
483                 {
484                         g_release = true;
485                         strcpy (g_releasedir, argv[i+1]);
486                         printf ("Copy output to: %s\n", g_releasedir);
487                         i++;
488                 }
489                 else if (!strcmp(argv[i], "-compress"))
490                 {
491                         g_compress_pak = true;
492                         printf ("Compressing pakfile\n");
493                 }
494                 else if (!strcmp(argv[i], "-pak"))
495                 {
496                         g_release = true;
497                         g_pak = true;
498                         printf ("Building pakfile: %s\n", argv[i+1]);
499                         BeginPak (argv[i+1]);
500                         i++;
501                 }
502                 else if (!strcmp(argv[i], "-only"))
503                 {
504                         strcpy (g_only, argv[i+1]);
505                         printf ("Only grabbing %s\n", g_only);
506                         i++;
507                 }
508                 else if (!strcmp(argv[i], "-3ds"))
509                 {
510                         do3ds = true;
511                         printf ("loading .3ds files\n");
512                 }
513                 else if (argv[i][0] == '-')
514                         Error ("Unknown option \"%s\"", argv[i]);
515                 else
516                         break;
517         }
518
519         if (i >= argc)
520                 Error ("usage: qgrab [-archive <directory>] [-release <directory>] [-only <model>] [-3ds] file.qgr");
521
522         if (do3ds)
523                 trifileext = ext_3ds;
524         else
525                 trifileext = ext_tri;
526
527         for ( ; i<argc ; i++)
528         {
529                 printf ("--------------- %s ---------------\n", argv[i]);
530                 // load the script
531                 strcpy (path, argv[i]);
532                 DefaultExtension (path, ".qdt");
533                 SetQdirFromPath (path);
534                 LoadScriptFile (ExpandArg(path));
535
536                 //
537                 // parse it
538                 //
539                 ParseScript ();
540
541                 // write out the last model
542                 FinishModel ();
543                 FinishSprite ();
544         }
545
546         if (g_pak)
547                 FinishPak ();
548
549         return 0;
550 }
551