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