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