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