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