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