]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/main.c
Merge commit '7d7436ec3dd43cbdb04ad41f0a2c92a905f26807' into garux-merge
[xonotic/netradiant.git] / tools / quake3 / q3map2 / main.c
1 /* -------------------------------------------------------------------------------
2
3    Copyright (C) 1999-2007 id Software, Inc. and contributors.
4    For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6    This file is part of GtkRadiant.
7
8    GtkRadiant is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    GtkRadiant is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with GtkRadiant; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
22    -------------------------------------------------------------------------------
23
24    This code has been altered significantly from its original form, to support
25    several games based on the Quake III Arena engine, in the form of "Q3Map2."
26
27    ------------------------------------------------------------------------------- */
28
29
30
31 /* marker */
32 #define MAIN_C
33
34
35
36 /* dependencies */
37 #include "q3map2.h"
38 #include <glib.h>
39
40 /*
41    Random()
42    returns a pseudorandom number between 0 and 1
43  */
44
45 vec_t Random( void ){
46         return (vec_t) rand() / RAND_MAX;
47 }
48
49
50 char *Q_strncpyz( char *dst, const char *src, size_t len ) {
51         if ( len == 0 ) {
52                 abort();
53         }
54
55         strncpy( dst, src, len );
56         dst[ len - 1 ] = '\0';
57         return dst;
58 }
59
60
61 char *Q_strcat( char *dst, size_t dlen, const char *src ) {
62         size_t n = strlen( dst );
63
64         if ( n > dlen ) {
65                 abort(); /* buffer overflow */
66         }
67
68         return Q_strncpyz( dst + n, src, dlen - n );
69 }
70
71
72 char *Q_strncat( char *dst, size_t dlen, const char *src, size_t slen ) {
73         size_t n = strlen( dst );
74
75         if ( n > dlen ) {
76                 abort(); /* buffer overflow */
77         }
78
79         return Q_strncpyz( dst + n, src, MIN( slen, dlen - n ) );
80 }
81
82
83 /*
84    ExitQ3Map()
85    cleanup routine
86  */
87
88 static void ExitQ3Map( void ){
89         BSPFilesCleanup();
90         if ( mapDrawSurfs != NULL ) {
91                 free( mapDrawSurfs );
92         }
93 }
94
95
96 /*
97    ShiftBSPMain()
98    shifts a map: for testing physics with huge coordinates
99  */
100
101 int ShiftBSPMain( int argc, char **argv ){
102         int i, j;
103         vec3_t scale;
104         vec3_t vec;
105         char str[ 1024 ];
106         float spawn_ref = 0;
107
108
109         /* arg checking */
110         if ( argc < 3 ) {
111                 Sys_Printf( "Usage: q3map [-v] -shift [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
112                 return 0;
113         }
114
115         for ( i = 1; i < argc - 2; ++i )
116         {
117                 if ( !strcmp( argv[i], "-tex" ) ) {
118                 }
119                 else if ( !strcmp( argv[i], "-spawn_ref" ) ) {
120                         spawn_ref = atof( argv[i + 1] );
121                         ++i;
122                 }
123                 else{
124                         break;
125                 }
126         }
127
128         /* get shift */
129         // if(argc-2 >= i) // always true
130         scale[2] = scale[1] = scale[0] = atof( argv[ argc - 2 ] );
131         if ( argc - 3 >= i ) {
132                 scale[1] = scale[0] = atof( argv[ argc - 3 ] );
133         }
134         if ( argc - 4 >= i ) {
135                 scale[0] = atof( argv[ argc - 4 ] );
136         }
137
138
139         /* do some path mangling */
140         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
141         StripExtension( source );
142         DefaultExtension( source, ".bsp" );
143
144         /* load the bsp */
145         Sys_Printf( "Loading %s\n", source );
146         LoadBSPFile( source );
147         ParseEntities();
148
149         /* note it */
150         Sys_Printf( "--- ShiftBSP ---\n" );
151         Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
152
153         /* shift entity keys */
154         for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
155         {
156                 /* shift origin */
157                 GetVectorForKey( &entities[ i ], "origin", vec );
158                 if ( ( vec[ 0 ] || vec[ 1 ] || vec[ 2 ] ) ) {
159                         if ( !!strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
160                                 vec[2] += spawn_ref;
161                         }
162                         vec[0] += scale[0];
163                         vec[1] += scale[1];
164                         vec[2] += scale[2];
165                         if ( !!strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
166                                 vec[2] -= spawn_ref;
167                         }
168                         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
169                         SetKeyValue( &entities[ i ], "origin", str );
170                 }
171
172         }
173
174         /* shift models */
175         for ( i = 0; i < numBSPModels; i++ )
176         {
177                 bspModels[ i ].mins[0] += scale[0];
178                 bspModels[ i ].mins[1] += scale[1];
179                 bspModels[ i ].mins[2] += scale[2];
180                 bspModels[ i ].maxs[0] += scale[0];
181                 bspModels[ i ].maxs[1] += scale[1];
182                 bspModels[ i ].maxs[2] += scale[2];
183         }
184
185         /* shift nodes */
186         for ( i = 0; i < numBSPNodes; i++ )
187         {
188                 bspNodes[ i ].mins[0] += scale[0];
189                 bspNodes[ i ].mins[1] += scale[1];
190                 bspNodes[ i ].mins[2] += scale[2];
191                 bspNodes[ i ].maxs[0] += scale[0];
192                 bspNodes[ i ].maxs[1] += scale[1];
193                 bspNodes[ i ].maxs[2] += scale[2];
194         }
195
196         /* shift leafs */
197         for ( i = 0; i < numBSPLeafs; i++ )
198         {
199                 bspLeafs[ i ].mins[0] += scale[0];
200                 bspLeafs[ i ].mins[1] += scale[1];
201                 bspLeafs[ i ].mins[2] += scale[2];
202                 bspLeafs[ i ].maxs[0] += scale[0];
203                 bspLeafs[ i ].maxs[1] += scale[1];
204                 bspLeafs[ i ].maxs[2] += scale[2];
205         }
206
207         /* shift drawverts */
208         for ( i = 0; i < numBSPDrawVerts; i++ )
209         {
210                 bspDrawVerts[i].xyz[0] += scale[0];
211                 bspDrawVerts[i].xyz[1] += scale[1];
212                 bspDrawVerts[i].xyz[2] += scale[2];
213         }
214
215         /* shift planes */
216
217         vec3_t point;
218
219         for ( i = 0; i < numBSPPlanes; i++ )
220         {
221                 //find point on plane
222                 for ( j=0; j<3; j++ ){
223                         if ( fabs( bspPlanes[ i ].normal[j] ) > 0.5 ){
224                                 point[j] = bspPlanes[ i ].dist / bspPlanes[ i ].normal[j];
225                                 point[(j+1)%3] = point[(j+2)%3] = 0;
226                                 break;
227                         }
228                 }
229                 //shift point
230                 for ( j=0; j<3; j++ ){
231                         point[j] += scale[j];
232                 }
233                 //calc new plane dist
234                 bspPlanes[ i ].dist = DotProduct( point, bspPlanes[ i ].normal );
235         }
236
237         /* scale gridsize */
238         /*
239         GetVectorForKey( &entities[ 0 ], "gridsize", vec );
240         if ( ( vec[ 0 ] + vec[ 1 ] + vec[ 2 ] ) == 0.0f ) {
241                 VectorCopy( gridSize, vec );
242         }
243         vec[0] *= scale[0];
244         vec[1] *= scale[1];
245         vec[2] *= scale[2];
246         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
247         SetKeyValue( &entities[ 0 ], "gridsize", str );
248 */
249         /* inject command line parameters */
250         InjectCommandLine( argv, 0, argc - 1 );
251
252         /* write the bsp */
253         UnparseEntities();
254         StripExtension( source );
255         DefaultExtension( source, "_sh.bsp" );
256         Sys_Printf( "Writing %s\n", source );
257         WriteBSPFile( source );
258
259         /* return to sender */
260         return 0;
261 }
262
263
264 void FixDOSName( char *src ){
265         if ( src == NULL ) {
266                 return;
267         }
268
269         while ( *src )
270         {
271                 if ( *src == '\\' ) {
272                         *src = '/';
273                 }
274                 src++;
275         }
276 }
277
278 /*
279         Check if newcoming texture is unique and not excluded
280 */
281 void tex2list( char* texlist, int *texnum, char* EXtex, int *EXtexnum ){
282         int i;
283         if ( token[0] == '\0') return;
284         StripExtension( token );
285         FixDOSName( token );
286         for ( i = 0; i < *texnum; i++ ){
287                 if ( !Q_stricmp( texlist[i], token ) ) return;
288         }
289         for ( i = 0; i < *EXtexnum; i++ ){
290                 if ( !Q_stricmp( EXtex[i], token ) ) return;
291         }
292         strcpy ( texlist + (*texnum)*65, token );
293         (*texnum)++;
294         return;
295 }
296
297 /* 4 repack */
298 void tex2list2( char* texlist, int *texnum, char* EXtex, int *EXtexnum, char* rEXtex, int *rEXtexnum ){
299         int i;
300         if ( token[0] == '\0') return;
301         //StripExtension( token );
302         char* dot = strrchr( token, '.' );
303         if ( dot != NULL){
304                 if ( Q_stricmp( dot, ".tga" ) && Q_stricmp( dot, ".jpg" ) && Q_stricmp( dot, ".png" ) ){
305                         Sys_Printf( "WARNING4: %s : weird or missing extension in shader\n", token );
306                 }
307                 else{
308                         *dot = '\0';
309                 }
310         }
311         FixDOSName( token );
312         strcpy ( texlist + (*texnum)*65, token );
313         strcat( token, ".tga" );
314
315         /* exclude */
316         for ( i = 0; i < *texnum; i++ ){
317                 if ( !Q_stricmp( texlist + i*65, texlist + (*texnum)*65 ) ) return;
318         }
319         for ( i = 0; i < *EXtexnum; i++ ){
320                 if ( !Q_stricmp( EXtex + i*65, texlist + (*texnum)*65 ) ) return;
321         }
322         for ( i = 0; i < *rEXtexnum; i++ ){
323                 if ( !Q_stricmp( rEXtex + i*65, texlist + (*texnum)*65 ) ) return;
324         }
325         (*texnum)++;
326         return;
327 }
328
329
330 /*
331         Check if newcoming res is unique
332 */
333 void res2list( char* data, int *num ){
334         int i;
335         if ( strlen( data + (*num)*65 ) > 64 ){
336                 Sys_Printf( "WARNING6: %s : path too long.\n", data + (*num)*65 );
337         }
338         while ( *( data + (*num)*65 ) == '\\' || *( data + (*num)*65 ) == '/' ){
339                 char* cut = data + (*num)*65 + 1;
340                 strcpy( data + (*num)*65, cut );
341         }
342         if ( *( data + (*num)*65 ) == '\0') return;
343         for ( i = 0; i < *num; i++ ){
344                 if ( !Q_stricmp( data[i], data[*num] ) ) return;
345         }
346         (*num)++;
347         return;
348 }
349
350 void parseEXblock ( char* data, int *num, const char *exName ){
351         if ( !GetToken( qtrue ) || strcmp( token, "{" ) ) {
352                 Error( "ReadExclusionsFile: %s, line %d: { not found", exName, scriptline );
353         }
354         while ( 1 )
355         {
356                 if ( !GetToken( qtrue ) ) {
357                         break;
358                 }
359                 if ( !strcmp( token, "}" ) ) {
360                         break;
361                 }
362                 if ( token[0] == '{' ) {
363                         Error( "ReadExclusionsFile: %s, line %d: brace, opening twice in a row.", exName, scriptline );
364                 }
365
366                 /* add to list */
367                 strcpy( data + (*num)*65, token );
368                 (*num)++;
369         }
370         return;
371 }
372
373 char q3map2path[1024];
374 /*
375    pk3BSPMain()
376    map autopackager, works for Q3 type of shaders and ents
377  */
378
379 int pk3BSPMain( int argc, char **argv ){
380         int i, j, len;
381         qboolean dbg = qfalse, png = qfalse, packFAIL = qfalse;
382
383         /* process arguments */
384         for ( i = 1; i < ( argc - 1 ); i++ ){
385                 if ( !strcmp( argv[ i ],  "-dbg" ) ) {
386                         dbg = qtrue;
387                 }
388                 else if ( !strcmp( argv[ i ],  "-png" ) ) {
389                         png = qtrue;
390                 }
391         }
392
393         /* do some path mangling */
394         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
395         StripExtension( source );
396         DefaultExtension( source, ".bsp" );
397
398         /* load the bsp */
399         Sys_Printf( "Loading %s\n", source );
400         LoadBSPFile( source );
401         ParseEntities();
402
403
404         char packname[ 1024 ], packFailName[ 1024 ], base[ 1024 ], nameOFmap[ 1024 ], temp[ 1024 ];
405
406         /* copy map name */
407         strcpy( base, source );
408         StripExtension( base );
409
410         /* extract map name */
411         len = strlen( base ) - 1;
412         while ( len > 0 && base[ len ] != '/' && base[ len ] != '\\' )
413                 len--;
414         strcpy( nameOFmap, &base[ len + 1 ] );
415
416
417         qboolean drawsurfSHs[1024] = { qfalse };
418
419         for ( i = 0; i < numBSPDrawSurfaces; i++ ){
420                 /* can't exclude nodraw patches here (they want shaders :0!) */
421                 //if ( !( bspDrawSurfaces[i].surfaceType == 2 && bspDrawSurfaces[i].numIndexes == 0 ) ) drawsurfSHs[bspDrawSurfaces[i].shaderNum] = qtrue;
422                 drawsurfSHs[ bspDrawSurfaces[i].shaderNum ] = qtrue;
423                 //Sys_Printf( "%s\n", bspShaders[bspDrawSurfaces[i].shaderNum].shader );
424         }
425
426         int pk3ShadersN = 0;
427         char* pk3Shaders = (char *)calloc( 1024*65, sizeof( char ) );
428         int pk3SoundsN = 0;
429         char* pk3Sounds = (char *)calloc( 1024*65, sizeof( char ) );
430         int pk3ShaderfilesN = 0;
431         char* pk3Shaderfiles = (char *)calloc( 1024*65, sizeof( char ) );
432         int pk3TexturesN = 0;
433         char* pk3Textures = (char *)calloc( 1024*65, sizeof( char ) );
434         int pk3VideosN = 0;
435         char* pk3Videos = (char *)calloc( 1024*65, sizeof( char ) );
436
437
438
439         for ( i = 0; i < numBSPShaders; i++ ){
440                 if ( drawsurfSHs[i] ){
441                         strcpy( pk3Shaders + pk3ShadersN*65, bspShaders[i].shader );
442                         res2list( pk3Shaders, &pk3ShadersN );
443                         //pk3ShadersN++;
444                         //Sys_Printf( "%s\n", bspShaders[i].shader );
445                 }
446         }
447
448         /* Ent keys */
449         epair_t *ep;
450         for ( ep = entities[0].epairs; ep != NULL; ep = ep->next )
451         {
452                 if ( !Q_strncasecmp( ep->key, "vertexremapshader", 17 ) ) {
453                         sscanf( ep->value, "%*[^;] %*[;] %s", pk3Shaders + pk3ShadersN*65 );
454                         res2list( pk3Shaders, &pk3ShadersN );
455                 }
456         }
457         strcpy( pk3Sounds + pk3SoundsN*65, ValueForKey( &entities[0], "music" ) );
458         if ( *( pk3Sounds + pk3SoundsN*65 ) != '\0' ){
459                 FixDOSName( pk3Sounds + pk3SoundsN*65 );
460                 DefaultExtension( pk3Sounds + pk3SoundsN*65, ".wav" );
461                 res2list( pk3Sounds, &pk3SoundsN );
462         }
463
464         for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
465         {
466                 strcpy( pk3Sounds + pk3SoundsN*65, ValueForKey( &entities[i], "noise" ) );
467                 if ( *( pk3Sounds + pk3SoundsN*65 ) != '\0' && *( pk3Sounds + pk3SoundsN*65 ) != '*' ){
468                         FixDOSName( pk3Sounds + pk3SoundsN*65 );
469                         DefaultExtension( pk3Sounds + pk3SoundsN*65, ".wav" );
470                         res2list( pk3Sounds, &pk3SoundsN );
471                 }
472
473                 if ( !Q_stricmp( ValueForKey( &entities[i], "classname" ), "func_plat" ) ){
474                         strcpy( pk3Sounds + pk3SoundsN*65, "sound/movers/plats/pt1_strt.wav");
475                         res2list( pk3Sounds, &pk3SoundsN );
476                         strcpy( pk3Sounds + pk3SoundsN*65, "sound/movers/plats/pt1_end.wav");
477                         res2list( pk3Sounds, &pk3SoundsN );
478                 }
479                 if ( !Q_stricmp( ValueForKey( &entities[i], "classname" ), "target_push" ) ){
480                         if ( !(IntForKey( &entities[i], "spawnflags") & 1) ){
481                                 strcpy( pk3Sounds + pk3SoundsN*65, "sound/misc/windfly.wav");
482                                 res2list( pk3Sounds, &pk3SoundsN );
483                         }
484                 }
485                 strcpy( pk3Shaders + pk3ShadersN*65, ValueForKey( &entities[i], "targetShaderNewName" ) );
486                 res2list( pk3Shaders, &pk3ShadersN );
487         }
488
489         //levelshot
490         sprintf( pk3Shaders + pk3ShadersN*65, "levelshots/%s", nameOFmap );
491         res2list( pk3Shaders, &pk3ShadersN );
492
493
494         if( dbg ){
495                 Sys_Printf( "\n\tDrawsurface+ent calls....%i\n", pk3ShadersN );
496                 for ( i = 0; i < pk3ShadersN; i++ ){
497                         Sys_Printf( "%s\n", pk3Shaders + i*65 );
498                 }
499                 Sys_Printf( "\n\tSounds....%i\n", pk3SoundsN );
500                 for ( i = 0; i < pk3SoundsN; i++ ){
501                         Sys_Printf( "%s\n", pk3Sounds + i*65 );
502                 }
503         }
504
505         vfsListShaderFiles( pk3Shaderfiles, &pk3ShaderfilesN );
506
507         if( dbg ){
508                 Sys_Printf( "\n\tSchroider fileses.....%i\n", pk3ShaderfilesN );
509                 for ( i = 0; i < pk3ShaderfilesN; i++ ){
510                         Sys_Printf( "%s\n", pk3Shaderfiles + i*65 );
511                 }
512         }
513
514
515         /* load exclusions file */
516         int ExTexturesN = 0;
517         char* ExTextures = (char *)calloc( 4096*65, sizeof( char ) );
518         int ExShadersN = 0;
519         char* ExShaders = (char *)calloc( 4096*65, sizeof( char ) );
520         int ExSoundsN = 0;
521         char* ExSounds = (char *)calloc( 4096*65, sizeof( char ) );
522         int ExShaderfilesN = 0;
523         char* ExShaderfiles = (char *)calloc( 4096*65, sizeof( char ) );
524         int ExVideosN = 0;
525         char* ExVideos = (char *)calloc( 4096*65, sizeof( char ) );
526         int ExPureTexturesN = 0;
527         char* ExPureTextures = (char *)calloc( 4096*65, sizeof( char ) );
528
529         char* ExReasonShader[4096] = { NULL };
530         char* ExReasonShaderFile[4096] = { NULL };
531
532         char exName[ 1024 ];
533         byte *buffer;
534         int size;
535
536         strcpy( exName, q3map2path );
537         char *cut = strrchr( exName, '\\' );
538         char *cut2 = strrchr( exName, '/' );
539         if ( cut == NULL && cut2 == NULL ){
540                 Sys_Printf( "WARNING: Unable to load exclusions file.\n" );
541                 goto skipEXfile;
542         }
543         if ( cut2 > cut ) cut = cut2;
544         cut[1] = '\0';
545         strcat( exName, game->arg );
546         strcat( exName, ".exclude" );
547
548         Sys_Printf( "Loading %s\n", exName );
549         size = TryLoadFile( exName, (void**) &buffer );
550         if ( size <= 0 ) {
551                 Sys_Printf( "WARNING: Unable to find exclusions file %s.\n", exName );
552                 goto skipEXfile;
553         }
554
555         /* parse the file */
556         ParseFromMemory( (char *) buffer, size );
557
558         /* tokenize it */
559         while ( 1 )
560         {
561                 /* test for end of file */
562                 if ( !GetToken( qtrue ) ) {
563                         break;
564                 }
565
566                 /* blocks */
567                 if ( !Q_stricmp( token, "textures" ) ){
568                         parseEXblock ( ExTextures, &ExTexturesN, exName );
569                 }
570                 else if ( !Q_stricmp( token, "shaders" ) ){
571                         parseEXblock ( ExShaders, &ExShadersN, exName );
572                 }
573                 else if ( !Q_stricmp( token, "shaderfiles" ) ){
574                         parseEXblock ( ExShaderfiles, &ExShaderfilesN, exName );
575                 }
576                 else if ( !Q_stricmp( token, "sounds" ) ){
577                         parseEXblock ( ExSounds, &ExSoundsN, exName );
578                 }
579                 else if ( !Q_stricmp( token, "videos" ) ){
580                         parseEXblock ( ExVideos, &ExVideosN, exName );
581                 }
582                 else{
583                         Error( "ReadExclusionsFile: %s, line %d: unknown block name!\nValid ones are: textures, shaders, shaderfiles, sounds, videos.", exName, scriptline );
584                 }
585         }
586
587         /* free the buffer */
588         free( buffer );
589
590         for ( i = 0; i < ExTexturesN; i++ ){
591                 for ( j = 0; j < ExShadersN; j++ ){
592                         if ( !Q_stricmp( ExTextures + i*65, ExShaders + j*65 ) ){
593                                 break;
594                         }
595                 }
596                 if ( j == ExShadersN ){
597                         strcpy ( ExPureTextures + ExPureTexturesN*65, ExTextures + i*65 );
598                         ExPureTexturesN++;
599                 }
600         }
601
602 skipEXfile:
603
604         if( dbg ){
605                 Sys_Printf( "\n\tExTextures....%i\n", ExTexturesN );
606                 for ( i = 0; i < ExTexturesN; i++ ) Sys_Printf( "%s\n", ExTextures + i*65 );
607                 Sys_Printf( "\n\tExPureTextures....%i\n", ExPureTexturesN );
608                 for ( i = 0; i < ExPureTexturesN; i++ ) Sys_Printf( "%s\n", ExPureTextures + i*65 );
609                 Sys_Printf( "\n\tExShaders....%i\n", ExShadersN );
610                 for ( i = 0; i < ExShadersN; i++ ) Sys_Printf( "%s\n", ExShaders + i*65 );
611                 Sys_Printf( "\n\tExShaderfiles....%i\n", ExShaderfilesN );
612                 for ( i = 0; i < ExShaderfilesN; i++ ) Sys_Printf( "%s\n", ExShaderfiles + i*65 );
613                 Sys_Printf( "\n\tExSounds....%i\n", ExSoundsN );
614                 for ( i = 0; i < ExSoundsN; i++ ) Sys_Printf( "%s\n", ExSounds + i*65 );
615                 Sys_Printf( "\n\tExVideos....%i\n", ExVideosN );
616                 for ( i = 0; i < ExVideosN; i++ ) Sys_Printf( "%s\n", ExVideos + i*65 );
617         }
618
619         /* can exclude pure textures right now, shouldn't create shaders for them anyway */
620         for ( i = 0; i < pk3ShadersN ; i++ ){
621                 for ( j = 0; j < ExPureTexturesN ; j++ ){
622                         if ( !Q_stricmp( pk3Shaders + i*65, ExPureTextures + j*65 ) ){
623                                 *( pk3Shaders + i*65 ) = '\0';
624                                 break;
625                         }
626                 }
627         }
628
629         //Parse Shader Files
630          /* hack */
631         endofscript = qtrue;
632
633         for ( i = 0; i < pk3ShaderfilesN; i++ ){
634                 qboolean wantShader = qfalse, wantShaderFile = qfalse, ShaderFileExcluded = qfalse;
635                 int shader;
636                 char* reasonShader = NULL;
637                 char* reasonShaderFile = NULL;
638
639                 /* load the shader */
640                 sprintf( temp, "%s/%s", game->shaderPath, pk3Shaderfiles + i*65 );
641                 SilentLoadScriptFile( temp, 0 );
642                 if( dbg ) Sys_Printf( "\n\tentering %s\n", pk3Shaderfiles + i*65 );
643
644                 /* do wanna le shader file? */
645                 for ( j = 0; j < ExShaderfilesN; j++ ){
646                         if ( !Q_stricmp( ExShaderfiles + j*65, pk3Shaderfiles + i*65 ) ){
647                                 ShaderFileExcluded = qtrue;
648                                 reasonShaderFile = ExShaderfiles + j*65;
649                                 break;
650                         }
651                 }
652                 /* tokenize it */
653                 /* check if shader file has to be excluded */
654                 while ( !ShaderFileExcluded )
655                 {
656                         /* test for end of file */
657                         if ( !GetToken( qtrue ) ) {
658                                 break;
659                         }
660
661                         /* does it contain restricted shaders/textures? */
662                         for ( j = 0; j < ExShadersN; j++ ){
663                                 if ( !Q_stricmp( ExShaders + j*65, token ) ){
664                                         ShaderFileExcluded = qtrue;
665                                         reasonShader = ExShaders + j*65;
666                                         break;
667                                 }
668                         }
669                         if ( ShaderFileExcluded )
670                                 break;
671                         for ( j = 0; j < ExPureTexturesN; j++ ){
672                                 if ( !Q_stricmp( ExPureTextures + j*65, token ) ){
673                                         ShaderFileExcluded = qtrue;
674                                         reasonShader = ExPureTextures + j*65;
675                                         break;
676                                 }
677                         }
678                         if ( ShaderFileExcluded )
679                                 break;
680
681                         /* handle { } section */
682                         if ( !GetToken( qtrue ) ) {
683                                 break;
684                         }
685                         if ( strcmp( token, "{" ) ) {
686                                         Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s",
687                                                 temp, scriptline, token );
688                         }
689
690                         while ( 1 )
691                         {
692                                 /* get the next token */
693                                 if ( !GetToken( qtrue ) ) {
694                                         break;
695                                 }
696                                 if ( !strcmp( token, "}" ) ) {
697                                         break;
698                                 }
699                                 /* parse stage directives */
700                                 if ( !strcmp( token, "{" ) ) {
701                                         while ( 1 )
702                                         {
703                                                 if ( !GetToken( qtrue ) ) {
704                                                         break;
705                                                 }
706                                                 if ( !strcmp( token, "}" ) ) {
707                                                         break;
708                                                 }
709                                         }
710                                 }
711                         }
712                 }
713
714                 /* tokenize it again */
715                 SilentLoadScriptFile( temp, 0 );
716                 while ( 1 )
717                 {
718                         /* test for end of file */
719                         if ( !GetToken( qtrue ) ) {
720                                 break;
721                         }
722                         //dump shader names
723                         if( dbg ) Sys_Printf( "%s\n", token );
724
725                         /* do wanna le shader? */
726                         wantShader = qfalse;
727                         for ( j = 0; j < pk3ShadersN; j++ ){
728                                 if ( !Q_stricmp( pk3Shaders + j*65, token) ){
729                                         shader = j;
730                                         wantShader = qtrue;
731                                         break;
732                                 }
733                         }
734
735                         /* handle { } section */
736                         if ( !GetToken( qtrue ) ) {
737                                 break;
738                         }
739                         if ( strcmp( token, "{" ) ) {
740                                         Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s",
741                                                 temp, scriptline, token );
742                         }
743
744                         while ( 1 )
745                         {
746                                 /* get the next token */
747                                 if ( !GetToken( qtrue ) ) {
748                                         break;
749                                 }
750                                 if ( !strcmp( token, "}" ) ) {
751                                         break;
752                                 }
753
754
755                                 /* -----------------------------------------------------------------
756                                 shader stages (passes)
757                                 ----------------------------------------------------------------- */
758
759                                 /* parse stage directives */
760                                 if ( !strcmp( token, "{" ) ) {
761                                         while ( 1 )
762                                         {
763                                                 if ( !GetToken( qtrue ) ) {
764                                                         break;
765                                                 }
766                                                 if ( !strcmp( token, "}" ) ) {
767                                                         break;
768                                                 }
769                                                 /* skip the shader */
770                                                 if ( !wantShader ) continue;
771
772                                                 /* digest any images */
773                                                 if ( !Q_stricmp( token, "map" ) ||
774                                                         !Q_stricmp( token, "clampMap" ) ) {
775
776                                                         /* get an image */
777                                                         GetToken( qfalse );
778                                                         if ( token[ 0 ] != '*' && token[ 0 ] != '$' ) {
779                                                                 tex2list( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN );
780                                                         }
781                                                 }
782                                                 else if ( !Q_stricmp( token, "animMap" ) ||
783                                                         !Q_stricmp( token, "clampAnimMap" ) ) {
784                                                         GetToken( qfalse );// skip num
785                                                         while ( TokenAvailable() ){
786                                                                 GetToken( qfalse );
787                                                                 tex2list( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN );
788                                                         }
789                                                 }
790                                                 else if ( !Q_stricmp( token, "videoMap" ) ){
791                                                         GetToken( qfalse );
792                                                         FixDOSName( token );
793                                                         if ( strchr( token, '/' ) == NULL && strchr( token, '\\' ) == NULL ){
794                                                                 sprintf( temp, "video/%s", token );
795                                                                 strcpy( token, temp );
796                                                         }
797                                                         FixDOSName( token );
798                                                         for ( j = 0; j < pk3VideosN; j++ ){
799                                                                 if ( !Q_stricmp( pk3Videos + j*65, token ) ){
800                                                                         goto away;
801                                                                 }
802                                                         }
803                                                         for ( j = 0; j < ExVideosN; j++ ){
804                                                                 if ( !Q_stricmp( ExVideos + j*65, token ) ){
805                                                                         goto away;
806                                                                 }
807                                                         }
808                                                         strcpy ( pk3Videos + pk3VideosN*65, token );
809                                                         pk3VideosN++;
810                                                         away:
811                                                         j = 0;
812                                                 }
813                                         }
814                                 }
815                                 /* skip the shader */
816                                 else if ( !wantShader ) continue;
817
818                                 /* -----------------------------------------------------------------
819                                 surfaceparm * directives
820                                 ----------------------------------------------------------------- */
821
822                                 /* match surfaceparm */
823                                 else if ( !Q_stricmp( token, "surfaceparm" ) ) {
824                                         GetToken( qfalse );
825                                         if ( !Q_stricmp( token, "nodraw" ) ) {
826                                                 wantShader = qfalse;
827                                                 *( pk3Shaders + shader*65 ) = '\0';
828                                         }
829                                 }
830
831                                 /* skyparms <outer image> <cloud height> <inner image> */
832                                 else if ( !Q_stricmp( token, "skyParms" ) ) {
833                                         /* get image base */
834                                         GetToken( qfalse );
835
836                                         /* ignore bogus paths */
837                                         if ( Q_stricmp( token, "-" ) && Q_stricmp( token, "full" ) ) {
838                                                 strcpy ( temp, token );
839                                                 sprintf( token, "%s_up", temp );
840                                                 tex2list( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN );
841                                                 sprintf( token, "%s_dn", temp );
842                                                 tex2list( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN );
843                                                 sprintf( token, "%s_lf", temp );
844                                                 tex2list( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN );
845                                                 sprintf( token, "%s_rt", temp );
846                                                 tex2list( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN );
847                                                 sprintf( token, "%s_bk", temp );
848                                                 tex2list( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN );
849                                                 sprintf( token, "%s_ft", temp );
850                                                 tex2list( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN );
851                                         }
852                                         /* skip rest of line */
853                                         GetToken( qfalse );
854                                         GetToken( qfalse );
855                                 }
856                         }
857
858                         //exclude shader
859                         if ( wantShader ){
860                                 for ( j = 0; j < ExShadersN; j++ ){
861                                         if ( !Q_stricmp( ExShaders + j*65, pk3Shaders + shader*65 ) ){
862                                                 wantShader = qfalse;
863                                                 *( pk3Shaders + shader*65 ) = '\0';
864                                                 break;
865                                         }
866                                 }
867                                 if ( wantShader ){
868                                         if ( ShaderFileExcluded ){
869                                                 if ( reasonShaderFile != NULL ){
870                                                         ExReasonShaderFile[ shader ] = reasonShaderFile;
871                                                 }
872                                                 else{
873                                                         ExReasonShaderFile[ shader ] = ( char* ) calloc( 65, sizeof( char ) );
874                                                         strcpy( ExReasonShaderFile[ shader ], pk3Shaderfiles + i*65 );
875                                                 }
876                                                 ExReasonShader[ shader ] = reasonShader;
877                                         }
878                                         else{
879                                                 wantShaderFile = qtrue;
880                                                 *( pk3Shaders + shader*65 ) = '\0';
881                                         }
882                                 }
883                         }
884                 }
885                 if ( !wantShaderFile ){
886                         *( pk3Shaderfiles + i*65 ) = '\0';
887                 }
888         }
889
890
891
892 /* exclude stuff */
893 //wanted shaders from excluded .shaders
894         Sys_Printf( "\n" );
895         for ( i = 0; i < pk3ShadersN; i++ ){
896                 if ( *( pk3Shaders + i*65 ) != '\0' && ( ExReasonShader[i] != NULL || ExReasonShaderFile[i] != NULL ) ){
897                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders + i*65 );
898                         packFAIL = qtrue;
899                         if ( ExReasonShader[i] != NULL ){
900                                 Sys_Printf( "     reason: is located in %s,\n     containing restricted shader %s\n", ExReasonShaderFile[i], ExReasonShader[i] );
901                         }
902                         else{
903                                 Sys_Printf( "     reason: is located in restricted %s\n", ExReasonShaderFile[i] );
904                         }
905                         *( pk3Shaders + i*65 ) = '\0';
906                 }
907         }
908 //pure textures (shader ones are done)
909         for ( i = 0; i < pk3ShadersN; i++ ){
910                 if ( *( pk3Shaders + i*65 ) != '\0' ){
911                         FixDOSName( pk3Shaders + i*65 );
912                         for ( j = 0; j < pk3TexturesN; j++ ){
913                                 if ( !Q_stricmp( pk3Shaders + i*65, pk3Textures + j*65 ) ){
914                                         *( pk3Shaders + i*65 ) = '\0';
915                                         break;
916                                 }
917                         }
918                         if ( *( pk3Shaders + i*65 ) == '\0' ) continue;
919                         for ( j = 0; j < ExTexturesN; j++ ){
920                                 if ( !Q_stricmp( pk3Shaders + i*65, ExTextures + j*65 ) ){
921                                         *( pk3Shaders + i*65 ) = '\0';
922                                         break;
923                                 }
924                         }
925                 }
926         }
927
928 //snds
929         for ( i = 0; i < pk3SoundsN; i++ ){
930                 for ( j = 0; j < ExSoundsN; j++ ){
931                         if ( !Q_stricmp( pk3Sounds + i*65, ExSounds + j*65 ) ){
932                                 *( pk3Sounds + i*65 ) = '\0';
933                                 break;
934                         }
935                 }
936         }
937
938         /* make a pack */
939         sprintf( packname, "%s/%s_autopacked.pk3", EnginePath, nameOFmap );
940         remove( packname );
941         sprintf( packFailName, "%s/%s_FAILEDpack.pk3", EnginePath, nameOFmap );
942         remove( packFailName );
943
944         Sys_Printf( "\n--- ZipZip ---\n" );
945
946         Sys_Printf( "\n\tShader referenced textures....\n" );
947
948         for ( i = 0; i < pk3TexturesN; i++ ){
949                 if ( png ){
950                         sprintf( temp, "%s.png", pk3Textures + i*65 );
951                         if ( vfsPackFile( temp, packname, 10 ) ){
952                                 Sys_Printf( "++%s\n", temp );
953                                 continue;
954                         }
955                 }
956                 sprintf( temp, "%s.tga", pk3Textures + i*65 );
957                 if ( vfsPackFile( temp, packname, 10 ) ){
958                         Sys_Printf( "++%s\n", temp );
959                         continue;
960                 }
961                 sprintf( temp, "%s.jpg", pk3Textures + i*65 );
962                 if ( vfsPackFile( temp, packname, 10 ) ){
963                         Sys_Printf( "++%s\n", temp );
964                         continue;
965                 }
966                 Sys_Printf( "  !FAIL! %s\n", pk3Textures + i*65 );
967                 packFAIL = qtrue;
968         }
969
970         Sys_Printf( "\n\tPure textures....\n" );
971
972         for ( i = 0; i < pk3ShadersN; i++ ){
973                 if ( *( pk3Shaders + i*65 ) != '\0' ){
974                         if ( png ){
975                                 sprintf( temp, "%s.png", pk3Shaders + i*65 );
976                                 if ( vfsPackFile( temp, packname, 10 ) ){
977                                         Sys_Printf( "++%s\n", temp );
978                                         continue;
979                                 }
980                         }
981                         sprintf( temp, "%s.tga", pk3Shaders + i*65 );
982                         if ( vfsPackFile( temp, packname, 10 ) ){
983                                 Sys_Printf( "++%s\n", temp );
984                                 continue;
985                         }
986                         sprintf( temp, "%s.jpg", pk3Shaders + i*65 );
987                         if ( vfsPackFile( temp, packname, 10 ) ){
988                                 Sys_Printf( "++%s\n", temp );
989                                 continue;
990                         }
991                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders + i*65 );
992                         if ( i != pk3ShadersN - 1 ) packFAIL = qtrue; //levelshot typically
993                 }
994         }
995
996         Sys_Printf( "\n\tShaizers....\n" );
997
998         for ( i = 0; i < pk3ShaderfilesN; i++ ){
999                 if ( *( pk3Shaderfiles + i*65 ) != '\0' ){
1000                         sprintf( temp, "%s/%s", game->shaderPath, pk3Shaderfiles + i*65 );
1001                         if ( vfsPackFile( temp, packname, 10 ) ){
1002                                 Sys_Printf( "++%s\n", temp );
1003                                 continue;
1004                         }
1005                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders + i*65 );
1006                         packFAIL = qtrue;
1007                 }
1008         }
1009
1010         Sys_Printf( "\n\tSounds....\n" );
1011
1012         for ( i = 0; i < pk3SoundsN; i++ ){
1013                 if ( *( pk3Sounds + i*65 ) != '\0' ){
1014                         if ( vfsPackFile( pk3Sounds + i*65, packname, 10 ) ){
1015                                 Sys_Printf( "++%s\n", pk3Sounds + i*65 );
1016                                 continue;
1017                         }
1018                         Sys_Printf( "  !FAIL! %s\n", pk3Sounds + i*65 );
1019                         packFAIL = qtrue;
1020                 }
1021         }
1022
1023         Sys_Printf( "\n\tVideos....\n" );
1024
1025         for ( i = 0; i < pk3VideosN; i++ ){
1026                 if ( vfsPackFile( pk3Videos + i*65, packname, 10 ) ){
1027                         Sys_Printf( "++%s\n", pk3Videos + i*65 );
1028                         continue;
1029                 }
1030                 Sys_Printf( "  !FAIL! %s\n", pk3Videos + i*65 );
1031                 packFAIL = qtrue;
1032         }
1033
1034         Sys_Printf( "\n\t.bsp and stuff\n" );
1035
1036         sprintf( temp, "maps/%s.bsp", nameOFmap );
1037         if ( vfsPackFile( temp, packname, 10 ) ){
1038                         Sys_Printf( "++%s\n", temp );
1039                 }
1040         else{
1041                 Sys_Printf( "  !FAIL! %s\n", temp );
1042                 packFAIL = qtrue;
1043         }
1044
1045         sprintf( temp, "maps/%s.aas", nameOFmap );
1046         if ( vfsPackFile( temp, packname, 10 ) ){
1047                         Sys_Printf( "++%s\n", temp );
1048                 }
1049         else{
1050                 Sys_Printf( "  !FAIL! %s\n", temp );
1051         }
1052
1053         sprintf( temp, "scripts/%s.arena", nameOFmap );
1054         if ( vfsPackFile( temp, packname, 10 ) ){
1055                         Sys_Printf( "++%s\n", temp );
1056                 }
1057         else{
1058                 Sys_Printf( "  !FAIL! %s\n", temp );
1059         }
1060
1061         sprintf( temp, "scripts/%s.defi", nameOFmap );
1062         if ( vfsPackFile( temp, packname, 10 ) ){
1063                         Sys_Printf( "++%s\n", temp );
1064                 }
1065         else{
1066                 Sys_Printf( "  !FAIL! %s\n", temp );
1067         }
1068
1069         if ( !packFAIL ){
1070         Sys_Printf( "\nSaved to %s\n", packname );
1071         }
1072         else{
1073                 rename( packname, packFailName );
1074                 Sys_Printf( "\nSaved to %s\n", packFailName );
1075         }
1076         /* return to sender */
1077         return 0;
1078 }
1079
1080
1081 /*
1082    repackBSPMain()
1083    repack multiple maps, strip only required shaders
1084    works for Q3 type of shaders and ents
1085  */
1086
1087 int repackBSPMain( int argc, char **argv ){
1088         int i, j, len, compLevel = 0;
1089         qboolean dbg = qfalse, png = qfalse;
1090
1091         /* process arguments */
1092         for ( i = 1; i < ( argc - 1 ); i++ ){
1093                 if ( !strcmp( argv[ i ],  "-dbg" ) ) {
1094                         dbg = qtrue;
1095                 }
1096                 else if ( !strcmp( argv[ i ],  "-png" ) ) {
1097                         png = qtrue;
1098                 }
1099                 else if ( !strcmp( argv[ i ],  "-complevel" ) ) {
1100                         compLevel = atoi( argv[ i + 1 ] );
1101                         i++;
1102                         if ( compLevel < -1 ) compLevel = -1;
1103                         if ( compLevel > 10 ) compLevel = 10;
1104                         Sys_Printf( "Compression level set to %i\n", compLevel );
1105                 }
1106         }
1107
1108 /* load exclusions file */
1109         int ExTexturesN = 0;
1110         char* ExTextures = (char *)calloc( 4096*65, sizeof( char ) );
1111         int ExShadersN = 0;
1112         char* ExShaders = (char *)calloc( 4096*65, sizeof( char ) );
1113         int ExSoundsN = 0;
1114         char* ExSounds = (char *)calloc( 4096*65, sizeof( char ) );
1115         int ExShaderfilesN = 0;
1116         char* ExShaderfiles = (char *)calloc( 4096*65, sizeof( char ) );
1117         int ExVideosN = 0;
1118         char* ExVideos = (char *)calloc( 4096*65, sizeof( char ) );
1119         int ExPureTexturesN = 0;
1120         char* ExPureTextures = (char *)calloc( 4096*65, sizeof( char ) );
1121
1122
1123         char exName[ 1024 ];
1124         byte *buffer;
1125         int size;
1126
1127         strcpy( exName, q3map2path );
1128         char *cut = strrchr( exName, '\\' );
1129         char *cut2 = strrchr( exName, '/' );
1130         if ( cut == NULL && cut2 == NULL ){
1131                 Sys_Printf( "WARNING: Unable to load exclusions file.\n" );
1132                 goto skipEXfile;
1133         }
1134         if ( cut2 > cut ) cut = cut2;
1135         cut[1] = '\0';
1136         strcat( exName, game->arg );
1137         strcat( exName, ".exclude" );
1138
1139         Sys_Printf( "Loading %s\n", exName );
1140         size = TryLoadFile( exName, (void**) &buffer );
1141         if ( size <= 0 ) {
1142                 Sys_Printf( "WARNING: Unable to find exclusions file %s.\n", exName );
1143                 goto skipEXfile;
1144         }
1145
1146         /* parse the file */
1147         ParseFromMemory( (char *) buffer, size );
1148
1149         /* tokenize it */
1150         while ( 1 )
1151         {
1152                 /* test for end of file */
1153                 if ( !GetToken( qtrue ) ) {
1154                         break;
1155                 }
1156
1157                 /* blocks */
1158                 if ( !Q_stricmp( token, "textures" ) ){
1159                         parseEXblock ( ExTextures, &ExTexturesN, exName );
1160                 }
1161                 else if ( !Q_stricmp( token, "shaders" ) ){
1162                         parseEXblock ( ExShaders, &ExShadersN, exName );
1163                 }
1164                 else if ( !Q_stricmp( token, "shaderfiles" ) ){
1165                         parseEXblock ( ExShaderfiles, &ExShaderfilesN, exName );
1166                 }
1167                 else if ( !Q_stricmp( token, "sounds" ) ){
1168                         parseEXblock ( ExSounds, &ExSoundsN, exName );
1169                 }
1170                 else if ( !Q_stricmp( token, "videos" ) ){
1171                         parseEXblock ( ExVideos, &ExVideosN, exName );
1172                 }
1173                 else{
1174                         Error( "ReadExclusionsFile: %s, line %d: unknown block name!\nValid ones are: textures, shaders, shaderfiles, sounds, videos.", exName, scriptline );
1175                 }
1176         }
1177
1178         /* free the buffer */
1179         free( buffer );
1180
1181         for ( i = 0; i < ExTexturesN; i++ ){
1182                 for ( j = 0; j < ExShadersN; j++ ){
1183                         if ( !Q_stricmp( ExTextures + i*65, ExShaders + j*65 ) ){
1184                                 break;
1185                         }
1186                 }
1187                 if ( j == ExShadersN ){
1188                         strcpy ( ExPureTextures + ExPureTexturesN*65, ExTextures + i*65 );
1189                         ExPureTexturesN++;
1190                 }
1191         }
1192
1193 skipEXfile:
1194
1195         if( dbg ){
1196                 Sys_Printf( "\n\tExTextures....%i\n", ExTexturesN );
1197                 for ( i = 0; i < ExTexturesN; i++ ) Sys_Printf( "%s\n", ExTextures + i*65 );
1198                 Sys_Printf( "\n\tExPureTextures....%i\n", ExPureTexturesN );
1199                 for ( i = 0; i < ExPureTexturesN; i++ ) Sys_Printf( "%s\n", ExPureTextures + i*65 );
1200                 Sys_Printf( "\n\tExShaders....%i\n", ExShadersN );
1201                 for ( i = 0; i < ExShadersN; i++ ) Sys_Printf( "%s\n", ExShaders + i*65 );
1202                 Sys_Printf( "\n\tExShaderfiles....%i\n", ExShaderfilesN );
1203                 for ( i = 0; i < ExShaderfilesN; i++ ) Sys_Printf( "%s\n", ExShaderfiles + i*65 );
1204                 Sys_Printf( "\n\tExSounds....%i\n", ExSoundsN );
1205                 for ( i = 0; i < ExSoundsN; i++ ) Sys_Printf( "%s\n", ExSounds + i*65 );
1206                 Sys_Printf( "\n\tExVideos....%i\n", ExVideosN );
1207                 for ( i = 0; i < ExVideosN; i++ ) Sys_Printf( "%s\n", ExVideos + i*65 );
1208         }
1209
1210
1211
1212
1213 /* load repack.exclude */
1214         int rExTexturesN = 0;
1215         char* rExTextures = (char *)calloc( 65536*65, sizeof( char ) );
1216         int rExShadersN = 0;
1217         char* rExShaders = (char *)calloc( 32768*65, sizeof( char ) );
1218         int rExSoundsN = 0;
1219         char* rExSounds = (char *)calloc( 8192*65, sizeof( char ) );
1220         int rExShaderfilesN = 0;
1221         char* rExShaderfiles = (char *)calloc( 4096*65, sizeof( char ) );
1222         int rExVideosN = 0;
1223         char* rExVideos = (char *)calloc( 4096*65, sizeof( char ) );
1224
1225         strcpy( exName, q3map2path );
1226         cut = strrchr( exName, '\\' );
1227         cut2 = strrchr( exName, '/' );
1228         if ( cut == NULL && cut2 == NULL ){
1229                 Sys_Printf( "WARNING: Unable to load repack exclusions file.\n" );
1230                 goto skipEXrefile;
1231         }
1232         if ( cut2 > cut ) cut = cut2;
1233         cut[1] = '\0';
1234         strcat( exName, "repack.exclude" );
1235
1236         Sys_Printf( "Loading %s\n", exName );
1237         size = TryLoadFile( exName, (void**) &buffer );
1238         if ( size <= 0 ) {
1239                 Sys_Printf( "WARNING: Unable to find repack exclusions file %s.\n", exName );
1240                 goto skipEXrefile;
1241         }
1242
1243         /* parse the file */
1244         ParseFromMemory( (char *) buffer, size );
1245
1246         /* tokenize it */
1247         while ( 1 )
1248         {
1249                 /* test for end of file */
1250                 if ( !GetToken( qtrue ) ) {
1251                         break;
1252                 }
1253
1254                 /* blocks */
1255                 if ( !Q_stricmp( token, "textures" ) ){
1256                         parseEXblock ( rExTextures, &rExTexturesN, exName );
1257                 }
1258                 else if ( !Q_stricmp( token, "shaders" ) ){
1259                         parseEXblock ( rExShaders, &rExShadersN, exName );
1260                 }
1261                 else if ( !Q_stricmp( token, "shaderfiles" ) ){
1262                         parseEXblock ( rExShaderfiles, &rExShaderfilesN, exName );
1263                 }
1264                 else if ( !Q_stricmp( token, "sounds" ) ){
1265                         parseEXblock ( rExSounds, &rExSoundsN, exName );
1266                 }
1267                 else if ( !Q_stricmp( token, "videos" ) ){
1268                         parseEXblock ( rExVideos, &rExVideosN, exName );
1269                 }
1270                 else{
1271                         Error( "ReadExclusionsFile: %s, line %d: unknown block name!\nValid ones are: textures, shaders, shaderfiles, sounds, videos.", exName, scriptline );
1272                 }
1273         }
1274
1275         /* free the buffer */
1276         free( buffer );
1277
1278 skipEXrefile:
1279
1280         if( dbg ){
1281                 Sys_Printf( "\n\trExTextures....%i\n", rExTexturesN );
1282                 for ( i = 0; i < rExTexturesN; i++ ) Sys_Printf( "%s\n", rExTextures + i*65 );
1283                 Sys_Printf( "\n\trExShaders....%i\n", rExShadersN );
1284                 for ( i = 0; i < rExShadersN; i++ ) Sys_Printf( "%s\n", rExShaders + i*65 );
1285                 Sys_Printf( "\n\trExShaderfiles....%i\n", rExShaderfilesN );
1286                 for ( i = 0; i < rExShaderfilesN; i++ ) Sys_Printf( "%s\n", rExShaderfiles + i*65 );
1287                 Sys_Printf( "\n\trExSounds....%i\n", rExSoundsN );
1288                 for ( i = 0; i < rExSoundsN; i++ ) Sys_Printf( "%s\n", rExSounds + i*65 );
1289                 Sys_Printf( "\n\trExVideos....%i\n", rExVideosN );
1290                 for ( i = 0; i < rExVideosN; i++ ) Sys_Printf( "%s\n", rExVideos + i*65 );
1291         }
1292
1293
1294
1295
1296         int bspListN = 0;
1297         char* bspList = (char *)calloc( 8192*1024, sizeof( char ) );
1298
1299         /* do some path mangling */
1300         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
1301         if ( !Q_stricmp( strrchr( source, '.' ), ".bsp" ) ){
1302                 strcpy( bspList, source );
1303                 bspListN++;
1304         }
1305         else{
1306                 /* load bsps paths list */
1307                 Sys_Printf( "Loading %s\n", source );
1308                 size = TryLoadFile( source, (void**) &buffer );
1309                 if ( size <= 0 ) {
1310                         Sys_Printf( "WARNING: Unable to open bsps paths list file %s.\n", source );
1311                 }
1312
1313                 /* parse the file */
1314                 ParseFromMemory( (char *) buffer, size );
1315
1316                 /* tokenize it */
1317                 while ( 1 )
1318                 {
1319                         /* test for end of file */
1320                         if ( !GetToken( qtrue ) ) {
1321                                 break;
1322                         }
1323                         strcpy( bspList + bspListN * 1024 , token );
1324                         bspListN++;
1325                 }
1326
1327                 /* free the buffer */
1328                 free( buffer );
1329         }
1330
1331         char packname[ 1024 ], nameOFrepack[ 1024 ], nameOFmap[ 1024 ], temp[ 1024 ];
1332
1333         /* copy input file name */
1334         strcpy( temp, source );
1335         StripExtension( temp );
1336
1337         /* extract input file name */
1338         len = strlen( temp ) - 1;
1339         while ( len > 0 && temp[ len ] != '/' && temp[ len ] != '\\' )
1340                 len--;
1341         strcpy( nameOFrepack, &temp[ len + 1 ] );
1342
1343
1344 /* load bsps */
1345         int pk3ShadersN = 0;
1346         char* pk3Shaders = (char *)calloc( 65536*65, sizeof( char ) );
1347         int pk3SoundsN = 0;
1348         char* pk3Sounds = (char *)calloc( 4096*65, sizeof( char ) );
1349         int pk3ShaderfilesN = 0;
1350         char* pk3Shaderfiles = (char *)calloc( 4096*65, sizeof( char ) );
1351         int pk3TexturesN = 0;
1352         char* pk3Textures = (char *)calloc( 65536*65, sizeof( char ) );
1353         int pk3VideosN = 0;
1354         char* pk3Videos = (char *)calloc( 1024*65, sizeof( char ) );
1355
1356         for( j = 0; j < bspListN; j++ ){
1357
1358                 int pk3SoundsNold = pk3SoundsN;
1359                 int pk3ShadersNold = pk3ShadersN;
1360
1361                 strcpy( source, bspList + j*1024 );
1362                 StripExtension( source );
1363                 DefaultExtension( source, ".bsp" );
1364
1365                 /* load the bsp */
1366                 Sys_Printf( "\nLoading %s\n", source );
1367                 PartialLoadBSPFile( source );
1368                 ParseEntities();
1369
1370                 /* copy map name */
1371                 strcpy( temp, source );
1372                 StripExtension( temp );
1373
1374                 /* extract map name */
1375                 len = strlen( temp ) - 1;
1376                 while ( len > 0 && temp[ len ] != '/' && temp[ len ] != '\\' )
1377                         len--;
1378                 strcpy( nameOFmap, &temp[ len + 1 ] );
1379
1380
1381                 qboolean drawsurfSHs[1024] = { qfalse };
1382
1383                 for ( i = 0; i < numBSPDrawSurfaces; i++ ){
1384                         drawsurfSHs[ bspDrawSurfaces[i].shaderNum ] = qtrue;
1385                 }
1386
1387                 for ( i = 0; i < numBSPShaders; i++ ){
1388                         if ( drawsurfSHs[i] ){
1389                                 strcpy( pk3Shaders + pk3ShadersN*65, bspShaders[i].shader );
1390                                 res2list( pk3Shaders, &pk3ShadersN );
1391                         }
1392                 }
1393
1394                 /* Ent keys */
1395                 epair_t *ep;
1396                 for ( ep = entities[0].epairs; ep != NULL; ep = ep->next )
1397                 {
1398                         if ( !!Q_strncasecmp( ep->key, "vertexremapshader", 17 ) ) {
1399                                 sscanf( ep->value, "%*[^;] %*[;] %s", pk3Shaders + pk3ShadersN*65 );
1400                                 res2list( pk3Shaders, &pk3ShadersN );
1401                         }
1402                 }
1403                 strcpy( pk3Sounds + pk3SoundsN*65, ValueForKey( &entities[0], "music" ) );
1404                 if ( *( pk3Sounds + pk3SoundsN*65 ) != '\0' ){
1405                         FixDOSName( pk3Sounds + pk3SoundsN*65 );
1406                         DefaultExtension( pk3Sounds + pk3SoundsN*65, ".wav" );
1407                         res2list( pk3Sounds, &pk3SoundsN );
1408                 }
1409
1410                 for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
1411                 {
1412                         strcpy( pk3Sounds + pk3SoundsN*65, ValueForKey( &entities[i], "noise" ) );
1413                         if ( *( pk3Sounds + pk3SoundsN*65 ) != '\0' && *( pk3Sounds + pk3SoundsN*65 ) != '*' ){
1414                                 FixDOSName( pk3Sounds + pk3SoundsN*65 );
1415                                 DefaultExtension( pk3Sounds + pk3SoundsN*65, ".wav" );
1416                                 res2list( pk3Sounds, &pk3SoundsN );
1417                         }
1418
1419                         if ( !Q_stricmp( ValueForKey( &entities[i], "classname" ), "func_plat" ) ){
1420                                 strcpy( pk3Sounds + pk3SoundsN*65, "sound/movers/plats/pt1_strt.wav");
1421                                 res2list( pk3Sounds, &pk3SoundsN );
1422                                 strcpy( pk3Sounds + pk3SoundsN*65, "sound/movers/plats/pt1_end.wav");
1423                                 res2list( pk3Sounds, &pk3SoundsN );
1424                         }
1425                         if ( !Q_stricmp( ValueForKey( &entities[i], "classname" ), "target_push" ) ){
1426                                 if ( !(IntForKey( &entities[i], "spawnflags") & 1) ){
1427                                         strcpy( pk3Sounds + pk3SoundsN*65, "sound/misc/windfly.wav");
1428                                         res2list( pk3Sounds, &pk3SoundsN );
1429                                 }
1430                         }
1431                         strcpy( pk3Shaders + pk3ShadersN*65, ValueForKey( &entities[i], "targetShaderNewName" ) );
1432                         res2list( pk3Shaders, &pk3ShadersN );
1433                 }
1434
1435                 //levelshot
1436                 sprintf( pk3Shaders + pk3ShadersN*65, "levelshots/%s", nameOFmap );
1437                 res2list( pk3Shaders, &pk3ShadersN );
1438
1439
1440
1441                 Sys_Printf( "\n\t+Drawsurface+ent calls....%i\n", pk3ShadersN - pk3ShadersNold );
1442                 for ( i = pk3ShadersNold; i < pk3ShadersN; i++ ){
1443                         Sys_Printf( "%s\n", pk3Shaders + i*65 );
1444                 }
1445                 Sys_Printf( "\n\t+Sounds....%i\n", pk3SoundsN - pk3SoundsNold );
1446                 for ( i = pk3SoundsNold; i < pk3SoundsN; i++ ){
1447                         Sys_Printf( "%s\n", pk3Sounds + i*65 );
1448                 }
1449                 /* free bsp data */
1450 /*
1451                 if ( bspDrawVerts != 0 ) {
1452                         free( bspDrawVerts );
1453                         bspDrawVerts = NULL;
1454                         //numBSPDrawVerts = 0;
1455                         Sys_Printf( "freed BSPDrawVerts\n" );
1456                 }
1457 */              if ( bspDrawSurfaces != 0 ) {
1458                         free( bspDrawSurfaces );
1459                         bspDrawSurfaces = NULL;
1460                         //numBSPDrawSurfaces = 0;
1461                         //Sys_Printf( "freed bspDrawSurfaces\n" );
1462                 }
1463 /*              if ( bspLightBytes != 0 ) {
1464                         free( bspLightBytes );
1465                         bspLightBytes = NULL;
1466                         //numBSPLightBytes = 0;
1467                         Sys_Printf( "freed BSPLightBytes\n" );
1468                 }
1469                 if ( bspGridPoints != 0 ) {
1470                         free( bspGridPoints );
1471                         bspGridPoints = NULL;
1472                         //numBSPGridPoints = 0;
1473                         Sys_Printf( "freed BSPGridPoints\n" );
1474                 }
1475                 if ( bspPlanes != 0 ) {
1476                         free( bspPlanes );
1477                         bspPlanes = NULL;
1478                         Sys_Printf( "freed bspPlanes\n" );
1479                         //numBSPPlanes = 0;
1480                         //allocatedBSPPlanes = 0;
1481                 }
1482                 if ( bspBrushes != 0 ) {
1483                         free( bspBrushes );
1484                         bspBrushes = NULL;
1485                         Sys_Printf( "freed bspBrushes\n" );
1486                         //numBSPBrushes = 0;
1487                         //allocatedBSPBrushes = 0;
1488                 }
1489 */              if ( entities != 0 ) {
1490                         epair_t *ep2free;
1491                         for ( i = 0; i < numBSPEntities && i < numEntities; i++ ){
1492                                 ep = entities[i].epairs;
1493                                 while( ep != NULL){
1494                                         ep2free = ep;
1495                                         ep = ep->next;
1496                                         free( ep2free );
1497                                 }
1498                         }
1499                         free( entities );
1500                         entities = NULL;
1501                         //Sys_Printf( "freed entities\n" );
1502                         numEntities = 0;
1503                         numBSPEntities = 0;
1504                         allocatedEntities = 0;
1505                 }
1506 /*              if ( bspModels != 0 ) {
1507                         free( bspModels );
1508                         bspModels = NULL;
1509                         Sys_Printf( "freed bspModels\n" );
1510                         //numBSPModels = 0;
1511                         //allocatedBSPModels = 0;
1512                 }
1513 */              if ( bspShaders != 0 ) {
1514                         free( bspShaders );
1515                         bspShaders = NULL;
1516                         //Sys_Printf( "freed bspShaders\n" );
1517                         //numBSPShaders = 0;
1518                         //allocatedBSPShaders = 0;
1519                 }
1520                 if ( bspEntData != 0 ) {
1521                         free( bspEntData );
1522                         bspEntData = NULL;
1523                         //Sys_Printf( "freed bspEntData\n" );
1524                         //bspEntDataSize = 0;
1525                         //allocatedBSPEntData = 0;
1526                 }
1527 /*              if ( bspNodes != 0 ) {
1528                         free( bspNodes );
1529                         bspNodes = NULL;
1530                         Sys_Printf( "freed bspNodes\n" );
1531                         //numBSPNodes = 0;
1532                         //allocatedBSPNodes = 0;
1533                 }
1534                 if ( bspDrawIndexes != 0 ) {
1535                         free( bspDrawIndexes );
1536                         bspDrawIndexes = NULL;
1537                         Sys_Printf( "freed bspDrawIndexes\n" );
1538                         //numBSPDrawIndexes = 0;
1539                         //allocatedBSPDrawIndexes = 0;
1540                 }
1541                 if ( bspLeafSurfaces != 0 ) {
1542                         free( bspLeafSurfaces );
1543                         bspLeafSurfaces = NULL;
1544                         Sys_Printf( "freed bspLeafSurfaces\n" );
1545                         //numBSPLeafSurfaces = 0;
1546                         //allocatedBSPLeafSurfaces = 0;
1547                 }
1548                 if ( bspLeafBrushes != 0 ) {
1549                         free( bspLeafBrushes );
1550                         bspLeafBrushes = NULL;
1551                         Sys_Printf( "freed bspLeafBrushes\n" );
1552                         //numBSPLeafBrushes = 0;
1553                         //allocatedBSPLeafBrushes = 0;
1554                 }
1555                 if ( bspBrushSides != 0 ) {
1556                         free( bspBrushSides );
1557                         bspBrushSides = NULL;
1558                         Sys_Printf( "freed bspBrushSides\n" );
1559                         numBSPBrushSides = 0;
1560                         allocatedBSPBrushSides = 0;
1561                 }
1562                 if ( numBSPFogs != 0 ) {
1563                         Sys_Printf( "freed numBSPFogs\n" );
1564                         numBSPFogs = 0;
1565                 }
1566                 if ( numBSPAds != 0 ) {
1567                         Sys_Printf( "freed numBSPAds\n" );
1568                         numBSPAds = 0;
1569                 }
1570                 if ( numBSPLeafs != 0 ) {
1571                         Sys_Printf( "freed numBSPLeafs\n" );
1572                         numBSPLeafs = 0;
1573                 }
1574                 if ( numBSPVisBytes != 0 ) {
1575                         Sys_Printf( "freed numBSPVisBytes\n" );
1576                         numBSPVisBytes = 0;
1577                 }
1578 */      }
1579
1580
1581
1582         vfsListShaderFiles( pk3Shaderfiles, &pk3ShaderfilesN );
1583
1584         if( dbg ){
1585                 Sys_Printf( "\n\tSchroider fileses.....%i\n", pk3ShaderfilesN );
1586                 for ( i = 0; i < pk3ShaderfilesN; i++ ){
1587                         Sys_Printf( "%s\n", pk3Shaderfiles + i*65 );
1588                 }
1589         }
1590
1591
1592
1593         /* can exclude pure *base* textures right now, shouldn't create shaders for them anyway */
1594         for ( i = 0; i < pk3ShadersN ; i++ ){
1595                 for ( j = 0; j < ExPureTexturesN ; j++ ){
1596                         if ( !Q_stricmp( pk3Shaders + i*65, ExPureTextures + j*65 ) ){
1597                                 *( pk3Shaders + i*65 ) = '\0';
1598                                 break;
1599                         }
1600                 }
1601         }
1602         /* can exclude repack.exclude shaders, assuming they got all their images */
1603         for ( i = 0; i < pk3ShadersN ; i++ ){
1604                 for ( j = 0; j < rExShadersN ; j++ ){
1605                         if ( !Q_stricmp( pk3Shaders + i*65, rExShaders + j*65 ) ){
1606                                 *( pk3Shaders + i*65 ) = '\0';
1607                                 break;
1608                         }
1609                 }
1610         }
1611
1612         //Parse Shader Files
1613         Sys_Printf( "\t\nParsing shaders....\n\n" );
1614         char shaderText[ 8192 ];
1615         char* allShaders = (char *)calloc( 16777216, sizeof( char ) );
1616          /* hack */
1617         endofscript = qtrue;
1618
1619         for ( i = 0; i < pk3ShaderfilesN; i++ ){
1620                 qboolean wantShader = qfalse;
1621                 int shader;
1622
1623                 /* load the shader */
1624                 sprintf( temp, "%s/%s", game->shaderPath, pk3Shaderfiles + i*65 );
1625                 if ( dbg ) Sys_Printf( "\n\tentering %s\n", pk3Shaderfiles + i*65 );
1626                 SilentLoadScriptFile( temp, 0 );
1627
1628                 /* tokenize it */
1629                 while ( 1 )
1630                 {
1631                         int line = scriptline;
1632                         /* test for end of file */
1633                         if ( !GetToken( qtrue ) ) {
1634                                 break;
1635                         }
1636                         //dump shader names
1637                         if( dbg ) Sys_Printf( "%s\n", token );
1638
1639                         strcpy( shaderText, token );
1640
1641                         if ( strchr( token, '\\') != NULL  ){
1642                                 Sys_Printf( "WARNING1: %s : %s : shader name with backslash\n", pk3Shaderfiles + i*65, token );
1643                         }
1644
1645                         /* do wanna le shader? */
1646                         wantShader = qfalse;
1647                         for ( j = 0; j < pk3ShadersN; j++ ){
1648                                 if ( !Q_stricmp( pk3Shaders + j*65, token) ){
1649                                         shader = j;
1650                                         wantShader = qtrue;
1651                                         break;
1652                                 }
1653                         }
1654                         if ( wantShader ){
1655                                 for ( j = 0; j < rExTexturesN ; j++ ){
1656                                         if ( !Q_stricmp( pk3Shaders + shader*65, rExTextures + j*65 ) ){
1657                                                 Sys_Printf( "WARNING3: %s : about to include shader for excluded texture\n", pk3Shaders + shader*65 );
1658                                                 break;
1659                                         }
1660                                 }
1661                         }
1662
1663                         /* handle { } section */
1664                         if ( !GetToken( qtrue ) ) {
1665                                 break;
1666                         }
1667                         if ( strcmp( token, "{" ) ) {
1668                                         Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s",
1669                                                 temp, scriptline, token );
1670                         }
1671                         strcat( shaderText, "\n{" );
1672                         qboolean hasmap = qfalse;
1673
1674                         while ( 1 )
1675                         {
1676                                 line = scriptline;
1677                                 /* get the next token */
1678                                 if ( !GetToken( qtrue ) ) {
1679                                         break;
1680                                 }
1681                                 if ( !strcmp( token, "}" ) ) {
1682                                         strcat( shaderText, "\n}\n\n" );
1683                                         break;
1684                                 }
1685                                 /* parse stage directives */
1686                                 if ( !strcmp( token, "{" ) ) {
1687                                         qboolean tokenready = qfalse;
1688                                         strcat( shaderText, "\n\t{" );
1689                                         while ( 1 )
1690                                         {
1691                                                 /* detour of TokenAvailable() '~' */
1692                                                 if ( tokenready ) tokenready = qfalse;
1693                                                 else line = scriptline;
1694                                                 if ( !GetToken( qtrue ) ) {
1695                                                         break;
1696                                                 }
1697                                                 if ( !strcmp( token, "}" ) ) {
1698                                                         strcat( shaderText, "\n\t}" );
1699                                                         break;
1700                                                 }
1701                                                 /* skip the shader */
1702                                                 if ( !wantShader ) continue;
1703
1704                                                 /* digest any images */
1705                                                 if ( !Q_stricmp( token, "map" ) ||
1706                                                         !Q_stricmp( token, "clampMap" ) ) {
1707                                                         strcat( shaderText, "\n\t\t" );
1708                                                         strcat( shaderText, token );
1709                                                         hasmap = qtrue;
1710
1711                                                         /* get an image */
1712                                                         GetToken( qfalse );
1713                                                         if ( token[ 0 ] != '*' && token[ 0 ] != '$' ) {
1714                                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1715                                                         }
1716                                                         strcat( shaderText, " " );
1717                                                         strcat( shaderText, token );
1718                                                 }
1719                                                 else if ( !Q_stricmp( token, "animMap" ) ||
1720                                                         !Q_stricmp( token, "clampAnimMap" ) ) {
1721                                                         strcat( shaderText, "\n\t\t" );
1722                                                         strcat( shaderText, token );
1723                                                         hasmap = qtrue;
1724
1725                                                         GetToken( qfalse );// skip num
1726                                                         strcat( shaderText, " " );
1727                                                         strcat( shaderText, token );
1728                                                         while ( TokenAvailable() ){
1729                                                                 GetToken( qfalse );
1730                                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1731                                                                 strcat( shaderText, " " );
1732                                                                 strcat( shaderText, token );
1733                                                         }
1734                                                         tokenready = qtrue;
1735                                                 }
1736                                                 else if ( !Q_stricmp( token, "videoMap" ) ){
1737                                                         strcat( shaderText, "\n\t\t" );
1738                                                         strcat( shaderText, token );
1739                                                         hasmap = qtrue;
1740                                                         GetToken( qfalse );
1741                                                         strcat( shaderText, " " );
1742                                                         strcat( shaderText, token );
1743                                                         FixDOSName( token );
1744                                                         if ( strchr( token, '/' ) == NULL && strchr( token, '\\' ) == NULL ){
1745                                                                 sprintf( temp, "video/%s", token );
1746                                                                 strcpy( token, temp );
1747                                                         }
1748                                                         FixDOSName( token );
1749                                                         for ( j = 0; j < pk3VideosN; j++ ){
1750                                                                 if ( !Q_stricmp( pk3Videos + j*65, token ) ){
1751                                                                         goto away;
1752                                                                 }
1753                                                         }
1754                                                         for ( j = 0; j < ExVideosN; j++ ){
1755                                                                 if ( !Q_stricmp( ExVideos + j*65, token ) ){
1756                                                                         goto away;
1757                                                                 }
1758                                                         }
1759                                                         for ( j = 0; j < rExVideosN; j++ ){
1760                                                                 if ( !Q_stricmp( rExVideos + j*65, token ) ){
1761                                                                         goto away;
1762                                                                 }
1763                                                         }
1764                                                         strcpy ( pk3Videos + pk3VideosN*65, token );
1765                                                         pk3VideosN++;
1766                                                         away:
1767                                                         j = 0;
1768                                                 }
1769                                                 else if ( !Q_stricmp( token, "mapComp" ) || !Q_stricmp( token, "mapNoComp" ) || !Q_stricmp( token, "animmapcomp" ) || !Q_stricmp( token, "animmapnocomp" ) ){
1770                                                         Sys_Printf( "WARNING7: %s : %s shader\n", pk3Shaders + shader*65, token );
1771                                                         hasmap = qtrue;
1772                                                         if ( line == scriptline ){
1773                                                                 strcat( shaderText, " " );
1774                                                                 strcat( shaderText, token );
1775                                                         }
1776                                                         else{
1777                                                                 strcat( shaderText, "\n\t\t" );
1778                                                                 strcat( shaderText, token );
1779                                                         }
1780                                                 }
1781                                                 else if ( line == scriptline ){
1782                                                         strcat( shaderText, " " );
1783                                                         strcat( shaderText, token );
1784                                                 }
1785                                                 else{
1786                                                         strcat( shaderText, "\n\t\t" );
1787                                                         strcat( shaderText, token );
1788                                                 }
1789                                         }
1790                                 }
1791                                 /* skip the shader */
1792                                 else if ( !wantShader ) continue;
1793
1794                                 /* -----------------------------------------------------------------
1795                                 surfaceparm * directives
1796                                 ----------------------------------------------------------------- */
1797
1798                                 /* match surfaceparm */
1799                                 else if ( !Q_stricmp( token, "surfaceparm" ) ) {
1800                                         strcat( shaderText, "\n\tsurfaceparm " );
1801                                         GetToken( qfalse );
1802                                         strcat( shaderText, token );
1803                                         if ( !Q_stricmp( token, "nodraw" ) ) {
1804                                                 wantShader = qfalse;
1805                                                 *( pk3Shaders + shader*65 ) = '\0';
1806                                         }
1807                                 }
1808
1809                                 /* skyparms <outer image> <cloud height> <inner image> */
1810                                 else if ( !Q_stricmp( token, "skyParms" ) ) {
1811                                         strcat( shaderText, "\n\tskyParms " );
1812                                         hasmap = qtrue;
1813                                         /* get image base */
1814                                         GetToken( qfalse );
1815                                         strcat( shaderText, token );
1816
1817                                         /* ignore bogus paths */
1818                                         if ( Q_stricmp( token, "-" ) && Q_stricmp( token, "full" ) ) {
1819                                                 strcpy ( temp, token );
1820                                                 sprintf( token, "%s_up", temp );
1821                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1822                                                 sprintf( token, "%s_dn", temp );
1823                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1824                                                 sprintf( token, "%s_lf", temp );
1825                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1826                                                 sprintf( token, "%s_rt", temp );
1827                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1828                                                 sprintf( token, "%s_bk", temp );
1829                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1830                                                 sprintf( token, "%s_ft", temp );
1831                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1832                                         }
1833                                         /* skip rest of line */
1834                                         GetToken( qfalse );
1835                                         strcat( shaderText, " " );
1836                                         strcat( shaderText, token );
1837                                         GetToken( qfalse );
1838                                         strcat( shaderText, " " );
1839                                         strcat( shaderText, token );
1840                                 }
1841                                 else if ( !!Q_strncasecmp( token, "implicit", 8 ) ){
1842                                         Sys_Printf( "WARNING5: %s : %s shader\n", pk3Shaders + shader*65, token );
1843                                         hasmap = qtrue;
1844                                         if ( line == scriptline ){
1845                                                 strcat( shaderText, " " );
1846                                                 strcat( shaderText, token );
1847                                         }
1848                                         else{
1849                                                 strcat( shaderText, "\n\t" );
1850                                                 strcat( shaderText, token );
1851                                         }
1852                                 }
1853                                 else if ( !Q_stricmp( token, "fogparms" ) ){
1854                                         hasmap = qtrue;
1855                                         if ( line == scriptline ){
1856                                                 strcat( shaderText, " " );
1857                                                 strcat( shaderText, token );
1858                                         }
1859                                         else{
1860                                                 strcat( shaderText, "\n\t" );
1861                                                 strcat( shaderText, token );
1862                                         }
1863                                 }
1864                                 else if ( line == scriptline ){
1865                                         strcat( shaderText, " " );
1866                                         strcat( shaderText, token );
1867                                 }
1868                                 else{
1869                                         strcat( shaderText, "\n\t" );
1870                                         strcat( shaderText, token );
1871                                 }
1872                         }
1873
1874                         //exclude shader
1875                         if ( wantShader && !hasmap ){
1876                                 Sys_Printf( "WARNING8: %s : shader has no known maps\n", pk3Shaders + shader*65 );
1877                                 wantShader = qfalse;
1878                                 *( pk3Shaders + shader*65 ) = '\0';
1879                         }
1880                         if ( wantShader ){
1881                                 for ( j = 0; j < ExShadersN; j++ ){
1882                                         if ( !Q_stricmp( ExShaders + j*65, pk3Shaders + shader*65 ) ){
1883                                                 wantShader = qfalse;
1884                                                 *( pk3Shaders + shader*65 ) = '\0';
1885                                                 break;
1886                                         }
1887                                 }
1888                                 if ( wantShader ){
1889                                         strcat( allShaders, shaderText );
1890                                         *( pk3Shaders + shader*65 ) = '\0';
1891                                 }
1892                         }
1893                 }
1894         }
1895 /* TODO: RTCW's mapComp, mapNoComp, animmapcomp, animmapnocomp; nocompress?; ET's implicitmap, implicitblend, implicitmask */
1896
1897
1898 /* exclude stuff */
1899
1900 //pure textures (shader ones are done)
1901         for ( i = 0; i < pk3ShadersN; i++ ){
1902                 if ( *( pk3Shaders + i*65 ) != '\0' ){
1903                         if ( strchr( pk3Shaders + i*65, '\\') != NULL  ){
1904                                 Sys_Printf( "WARNING2: %s : bsp shader path with backslash\n", pk3Shaders + i*65 );
1905                                 FixDOSName( pk3Shaders + i*65 );
1906                                 //what if theres properly slashed one in the list?
1907                                 for ( j = 0; j < pk3ShadersN; j++ ){
1908                                         if ( !Q_stricmp( pk3Shaders + i*65, pk3Shaders + j*65 ) && (i != j) ){
1909                                                 *( pk3Shaders + i*65 ) = '\0';
1910                                                 break;
1911                                         }
1912                                 }
1913                         }
1914                         if ( *( pk3Shaders + i*65 ) == '\0' ) continue;
1915                         for ( j = 0; j < pk3TexturesN; j++ ){
1916                                 if ( !Q_stricmp( pk3Shaders + i*65, pk3Textures + j*65 ) ){
1917                                         *( pk3Shaders + i*65 ) = '\0';
1918                                         break;
1919                                 }
1920                         }
1921                         if ( *( pk3Shaders + i*65 ) == '\0' ) continue;
1922                         for ( j = 0; j < ExTexturesN; j++ ){
1923                                 if ( !Q_stricmp( pk3Shaders + i*65, ExTextures + j*65 ) ){
1924                                         *( pk3Shaders + i*65 ) = '\0';
1925                                         break;
1926                                 }
1927                         }
1928                         if ( *( pk3Shaders + i*65 ) == '\0' ) continue;
1929                         for ( j = 0; j < rExTexturesN; j++ ){
1930                                 if ( !Q_stricmp( pk3Shaders + i*65, rExTextures + j*65 ) ){
1931                                         *( pk3Shaders + i*65 ) = '\0';
1932                                         break;
1933                                 }
1934                         }
1935                 }
1936         }
1937
1938 //snds
1939         for ( i = 0; i < pk3SoundsN; i++ ){
1940                 for ( j = 0; j < ExSoundsN; j++ ){
1941                         if ( !Q_stricmp( pk3Sounds + i*65, ExSounds + j*65 ) ){
1942                                 *( pk3Sounds + i*65 ) = '\0';
1943                                 break;
1944                         }
1945                 }
1946                 if ( *( pk3Sounds + i*65 ) == '\0' ) continue;
1947                 for ( j = 0; j < rExSoundsN; j++ ){
1948                         if ( !Q_stricmp( pk3Sounds + i*65, rExSounds + j*65 ) ){
1949                                 *( pk3Sounds + i*65 ) = '\0';
1950                                 break;
1951                         }
1952                 }
1953         }
1954
1955         /* write shader */
1956         sprintf( temp, "%s/%s_strippedBYrepacker.shader", EnginePath, nameOFrepack );
1957         FILE *f;
1958         f = fopen( temp, "wb" );
1959         fwrite( allShaders, sizeof( char ), strlen( allShaders ), f );
1960         fclose( f );
1961         Sys_Printf( "Shaders saved to %s\n", temp );
1962
1963         /* make a pack */
1964         sprintf( packname, "%s/%s_repacked.pk3", EnginePath, nameOFrepack );
1965         remove( packname );
1966
1967         Sys_Printf( "\n--- ZipZip ---\n" );
1968
1969         Sys_Printf( "\n\tShader referenced textures....\n" );
1970
1971         for ( i = 0; i < pk3TexturesN; i++ ){
1972                 if ( png ){
1973                         sprintf( temp, "%s.png", pk3Textures + i*65 );
1974                         if ( vfsPackFile( temp, packname, compLevel ) ){
1975                                 Sys_Printf( "++%s\n", temp );
1976                                 continue;
1977                         }
1978                 }
1979                 sprintf( temp, "%s.tga", pk3Textures + i*65 );
1980                 if ( vfsPackFile( temp, packname, compLevel ) ){
1981                         Sys_Printf( "++%s\n", temp );
1982                         continue;
1983                 }
1984                 sprintf( temp, "%s.jpg", pk3Textures + i*65 );
1985                 if ( vfsPackFile( temp, packname, compLevel ) ){
1986                         Sys_Printf( "++%s\n", temp );
1987                         continue;
1988                 }
1989                 Sys_Printf( "  !FAIL! %s\n", pk3Textures + i*65 );
1990         }
1991
1992         Sys_Printf( "\n\tPure textures....\n" );
1993
1994         for ( i = 0; i < pk3ShadersN; i++ ){
1995                 if ( *( pk3Shaders + i*65 ) != '\0' ){
1996                         if ( png ){
1997                                 sprintf( temp, "%s.png", pk3Shaders + i*65 );
1998                                 if ( vfsPackFile( temp, packname, compLevel ) ){
1999                                         Sys_Printf( "++%s\n", temp );
2000                                         continue;
2001                                 }
2002                         }
2003                         sprintf( temp, "%s.tga", pk3Shaders + i*65 );
2004                         if ( vfsPackFile( temp, packname, compLevel ) ){
2005                                 Sys_Printf( "++%s\n", temp );
2006                                 continue;
2007                         }
2008                         sprintf( temp, "%s.jpg", pk3Shaders + i*65 );
2009                         if ( vfsPackFile( temp, packname, compLevel ) ){
2010                                 Sys_Printf( "++%s\n", temp );
2011                                 continue;
2012                         }
2013                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders + i*65 );
2014                 }
2015         }
2016
2017         Sys_Printf( "\n\tSounds....\n" );
2018
2019         for ( i = 0; i < pk3SoundsN; i++ ){
2020                 if ( *( pk3Sounds + i*65 ) != '\0' ){
2021                         if ( vfsPackFile( pk3Sounds + i*65, packname, compLevel ) ){
2022                                 Sys_Printf( "++%s\n", pk3Sounds + i*65 );
2023                                 continue;
2024                         }
2025                         Sys_Printf( "  !FAIL! %s\n", pk3Sounds + i*65 );
2026                 }
2027         }
2028
2029         Sys_Printf( "\n\tVideos....\n" );
2030
2031         for ( i = 0; i < pk3VideosN; i++ ){
2032                 if ( vfsPackFile( pk3Videos + i*65, packname, compLevel ) ){
2033                         Sys_Printf( "++%s\n", pk3Videos + i*65 );
2034                         continue;
2035                 }
2036                 Sys_Printf( "  !FAIL! %s\n", pk3Videos + i*65 );
2037         }
2038
2039         Sys_Printf( "\nSaved to %s\n", packname );
2040
2041         /* return to sender */
2042         return 0;
2043 }
2044
2045
2046
2047 /*
2048    main()
2049    q3map mojo...
2050  */
2051
2052 int main( int argc, char **argv ){
2053         int i, r;
2054         double start, end;
2055         extern qboolean werror;
2056
2057
2058         /* we want consistent 'randomness' */
2059         srand( 0 );
2060
2061         /* start timer */
2062         start = I_FloatTime();
2063
2064         /* this was changed to emit version number over the network */
2065         printf( Q3MAP_VERSION "\n" );
2066
2067         /* set exit call */
2068         atexit( ExitQ3Map );
2069
2070         /* read general options first */
2071         for ( i = 1; i < argc; i++ )
2072         {
2073                 /* -help */
2074                 if ( !strcmp( argv[ i ], "-h" ) || !strcmp( argv[ i ], "--help" )
2075                         || !strcmp( argv[ i ], "-help" ) ) {
2076                         HelpMain(argv[i+1]);
2077                         return 0;
2078                 }
2079
2080                 /* -connect */
2081                 if ( !strcmp( argv[ i ], "-connect" ) ) {
2082                         argv[ i ] = NULL;
2083                         i++;
2084                         Broadcast_Setup( argv[ i ] );
2085                         argv[ i ] = NULL;
2086                 }
2087
2088                 /* verbose */
2089                 else if ( !strcmp( argv[ i ], "-v" ) ) {
2090                         if ( !verbose ) {
2091                                 verbose = qtrue;
2092                                 argv[ i ] = NULL;
2093                         }
2094                 }
2095
2096                 /* force */
2097                 else if ( !strcmp( argv[ i ], "-force" ) ) {
2098                         force = qtrue;
2099                         argv[ i ] = NULL;
2100                 }
2101
2102                 /* make all warnings into errors */
2103                 else if ( !strcmp( argv[ i ], "-werror" ) ) {
2104                         werror = qtrue;
2105                         argv[ i ] = NULL;
2106                 }
2107
2108                 /* patch subdivisions */
2109                 else if ( !strcmp( argv[ i ], "-subdivisions" ) ) {
2110                         argv[ i ] = NULL;
2111                         i++;
2112                         patchSubdivisions = atoi( argv[ i ] );
2113                         argv[ i ] = NULL;
2114                         if ( patchSubdivisions <= 0 ) {
2115                                 patchSubdivisions = 1;
2116                         }
2117                 }
2118
2119                 /* threads */
2120                 else if ( !strcmp( argv[ i ], "-threads" ) ) {
2121                         argv[ i ] = NULL;
2122                         i++;
2123                         numthreads = atoi( argv[ i ] );
2124                         argv[ i ] = NULL;
2125                 }
2126
2127                 else if( !strcmp( argv[ i ], "-nocmdline" ) )
2128                 {
2129                         Sys_Printf( "noCmdLine\n" );
2130                         nocmdline = qtrue;
2131                         argv[ i ] = NULL;
2132                 }
2133
2134         }
2135
2136         /* init model library */
2137         PicoInit();
2138         PicoSetMallocFunc( safe_malloc );
2139         PicoSetFreeFunc( free );
2140         PicoSetPrintFunc( PicoPrintFunc );
2141         PicoSetLoadFileFunc( PicoLoadFileFunc );
2142         PicoSetFreeFileFunc( free );
2143
2144         /* set number of threads */
2145         ThreadSetDefault();
2146
2147         /* generate sinusoid jitter table */
2148         for ( i = 0; i < MAX_JITTERS; i++ )
2149         {
2150                 jitters[ i ] = sin( i * 139.54152147 );
2151                 //%     Sys_Printf( "Jitter %4d: %f\n", i, jitters[ i ] );
2152         }
2153
2154         /* we print out two versions, q3map's main version (since it evolves a bit out of GtkRadiant)
2155            and we put the GtkRadiant version to make it easy to track with what version of Radiant it was built with */
2156
2157         Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
2158         Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
2159         Sys_Printf( "NetRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
2160         Sys_Printf( "%s\n", Q3MAP_MOTD );
2161         Sys_Printf( "%s\n", argv[0] );
2162
2163         strcpy( q3map2path, argv[0] );//fuer autoPack func
2164
2165         /* ydnar: new path initialization */
2166         InitPaths( &argc, argv );
2167
2168         /* set game options */
2169         if ( !patchSubdivisions ) {
2170                 patchSubdivisions = game->patchSubdivisions;
2171         }
2172
2173         /* check if we have enough options left to attempt something */
2174         if ( argc < 2 ) {
2175                 Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );
2176         }
2177
2178         /* fixaas */
2179         if ( !strcmp( argv[ 1 ], "-fixaas" ) ) {
2180                 r = FixAASMain( argc - 1, argv + 1 );
2181         }
2182
2183         /* analyze */
2184         else if ( !strcmp( argv[ 1 ], "-analyze" ) ) {
2185                 r = AnalyzeBSPMain( argc - 1, argv + 1 );
2186         }
2187
2188         /* info */
2189         else if ( !strcmp( argv[ 1 ], "-info" ) ) {
2190                 r = BSPInfoMain( argc - 2, argv + 2 );
2191         }
2192
2193         /* vis */
2194         else if ( !strcmp( argv[ 1 ], "-vis" ) ) {
2195                 r = VisMain( argc - 1, argv + 1 );
2196         }
2197
2198         /* light */
2199         else if ( !strcmp( argv[ 1 ], "-light" ) ) {
2200                 r = LightMain( argc - 1, argv + 1 );
2201         }
2202
2203         /* vlight */
2204         else if ( !strcmp( argv[ 1 ], "-vlight" ) ) {
2205                 Sys_FPrintf( SYS_WRN, "WARNING: VLight is no longer supported, defaulting to -light -fast instead\n\n" );
2206                 argv[ 1 ] = "-fast";    /* eek a hack */
2207                 r = LightMain( argc, argv );
2208         }
2209
2210         /* QBall: export entities */
2211         else if ( !strcmp( argv[ 1 ], "-exportents" ) ) {
2212                 r = ExportEntitiesMain( argc - 1, argv + 1 );
2213         }
2214
2215         /* ydnar: lightmap export */
2216         else if ( !strcmp( argv[ 1 ], "-export" ) ) {
2217                 r = ExportLightmapsMain( argc - 1, argv + 1 );
2218         }
2219
2220         /* ydnar: lightmap import */
2221         else if ( !strcmp( argv[ 1 ], "-import" ) ) {
2222                 r = ImportLightmapsMain( argc - 1, argv + 1 );
2223         }
2224
2225         /* ydnar: bsp scaling */
2226         else if ( !strcmp( argv[ 1 ], "-scale" ) ) {
2227                 r = ScaleBSPMain( argc - 1, argv + 1 );
2228         }
2229
2230         /* bsp shifting */
2231         else if ( !strcmp( argv[ 1 ], "-shift" ) ) {
2232                 r = ShiftBSPMain( argc - 1, argv + 1 );
2233         }
2234
2235         /* autopacking */
2236         else if ( !strcmp( argv[ 1 ], "-pk3" ) ) {
2237                 r = pk3BSPMain( argc - 1, argv + 1 );
2238         }
2239
2240         /* repacker */
2241         else if ( !strcmp( argv[ 1 ], "-repack" ) ) {
2242                 r = repackBSPMain( argc - 1, argv + 1 );
2243         }
2244
2245         /* ydnar: bsp conversion */
2246         else if ( !strcmp( argv[ 1 ], "-convert" ) ) {
2247                 r = ConvertBSPMain( argc - 1, argv + 1 );
2248         }
2249
2250         /* div0: minimap */
2251         else if ( !strcmp( argv[ 1 ], "-minimap" ) ) {
2252                 r = MiniMapBSPMain( argc - 1, argv + 1 );
2253         }
2254
2255         /* ydnar: otherwise create a bsp */
2256         else{
2257                 r = BSPMain( argc, argv );
2258         }
2259
2260         /* emit time */
2261         end = I_FloatTime();
2262         Sys_Printf( "%9.0f seconds elapsed\n", end - start );
2263
2264         /* shut down connection */
2265         Broadcast_Shutdown();
2266
2267         /* return any error code */
2268         return r;
2269 }