]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/main.c
Merge commit '804c20949d43175179489ecbb1305752cfa17217' into garux-merge
[xonotic/netradiant.git] / tools / quake3 / q3map2 / main.c
1 /* -------------------------------------------------------------------------------
2
3    Copyright (C) 1999-2007 id Software, Inc. and contributors.
4    For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6    This file is part of GtkRadiant.
7
8    GtkRadiant is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    GtkRadiant is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with GtkRadiant; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
22    -------------------------------------------------------------------------------
23
24    This code has been altered significantly from its original form, to support
25    several games based on the Quake III Arena engine, in the form of "Q3Map2."
26
27    ------------------------------------------------------------------------------- */
28
29
30
31 /* marker */
32 #define MAIN_C
33
34
35
36 /* dependencies */
37 #include "q3map2.h"
38 #include <glib.h>
39
40 /*
41    Random()
42    returns a pseudorandom number between 0 and 1
43  */
44
45 vec_t Random( void ){
46         return (vec_t) rand() / RAND_MAX;
47 }
48
49
50 char *Q_strncpyz( char *dst, const char *src, size_t len ) {
51         if ( len == 0 ) {
52                 abort();
53         }
54
55         strncpy( dst, src, len );
56         dst[ len - 1 ] = '\0';
57         return dst;
58 }
59
60
61 char *Q_strcat( char *dst, size_t dlen, const char *src ) {
62         size_t n = strlen( dst );
63
64         if ( n > dlen ) {
65                 abort(); /* buffer overflow */
66         }
67
68         return Q_strncpyz( dst + n, src, dlen - n );
69 }
70
71
72 char *Q_strncat( char *dst, size_t dlen, const char *src, size_t slen ) {
73         size_t n = strlen( dst );
74
75         if ( n > dlen ) {
76                 abort(); /* buffer overflow */
77         }
78
79         return Q_strncpyz( dst + n, src, MIN( slen, dlen - n ) );
80 }
81
82
83 /*
84    ExitQ3Map()
85    cleanup routine
86  */
87
88 static void ExitQ3Map( void ){
89         BSPFilesCleanup();
90         if ( mapDrawSurfs != NULL ) {
91                 free( mapDrawSurfs );
92         }
93 }
94
95
96 /*
97    ShiftBSPMain()
98    shifts a map: for testing physics with huge coordinates
99  */
100
101 int ShiftBSPMain( int argc, char **argv ){
102         int i, j;
103         vec3_t scale;
104         vec3_t vec;
105         char str[ 1024 ];
106         float spawn_ref = 0;
107
108
109         /* arg checking */
110         if ( argc < 3 ) {
111                 Sys_Printf( "Usage: q3map [-v] -shift [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
112                 return 0;
113         }
114
115         for ( i = 1; i < argc - 2; ++i )
116         {
117                 if ( !strcmp( argv[i], "-tex" ) ) {
118                 }
119                 else if ( !strcmp( argv[i], "-spawn_ref" ) ) {
120                         spawn_ref = atof( argv[i + 1] );
121                         ++i;
122                 }
123                 else{
124                         break;
125                 }
126         }
127
128         /* get shift */
129         // if(argc-2 >= i) // always true
130         scale[2] = scale[1] = scale[0] = atof( argv[ argc - 2 ] );
131         if ( argc - 3 >= i ) {
132                 scale[1] = scale[0] = atof( argv[ argc - 3 ] );
133         }
134         if ( argc - 4 >= i ) {
135                 scale[0] = atof( argv[ argc - 4 ] );
136         }
137
138
139         /* do some path mangling */
140         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
141         StripExtension( source );
142         DefaultExtension( source, ".bsp" );
143
144         /* load the bsp */
145         Sys_Printf( "Loading %s\n", source );
146         LoadBSPFile( source );
147         ParseEntities();
148
149         /* note it */
150         Sys_Printf( "--- ShiftBSP ---\n" );
151         Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
152
153         /* shift entity keys */
154         for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
155         {
156                 /* shift origin */
157                 GetVectorForKey( &entities[ i ], "origin", vec );
158                 if ( ( vec[ 0 ] || vec[ 1 ] || vec[ 2 ] ) ) {
159                         if ( !!strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
160                                 vec[2] += spawn_ref;
161                         }
162                         vec[0] += scale[0];
163                         vec[1] += scale[1];
164                         vec[2] += scale[2];
165                         if ( !!strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
166                                 vec[2] -= spawn_ref;
167                         }
168                         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
169                         SetKeyValue( &entities[ i ], "origin", str );
170                 }
171
172         }
173
174         /* shift models */
175         for ( i = 0; i < numBSPModels; i++ )
176         {
177                 bspModels[ i ].mins[0] += scale[0];
178                 bspModels[ i ].mins[1] += scale[1];
179                 bspModels[ i ].mins[2] += scale[2];
180                 bspModels[ i ].maxs[0] += scale[0];
181                 bspModels[ i ].maxs[1] += scale[1];
182                 bspModels[ i ].maxs[2] += scale[2];
183         }
184
185         /* shift nodes */
186         for ( i = 0; i < numBSPNodes; i++ )
187         {
188                 bspNodes[ i ].mins[0] += scale[0];
189                 bspNodes[ i ].mins[1] += scale[1];
190                 bspNodes[ i ].mins[2] += scale[2];
191                 bspNodes[ i ].maxs[0] += scale[0];
192                 bspNodes[ i ].maxs[1] += scale[1];
193                 bspNodes[ i ].maxs[2] += scale[2];
194         }
195
196         /* shift leafs */
197         for ( i = 0; i < numBSPLeafs; i++ )
198         {
199                 bspLeafs[ i ].mins[0] += scale[0];
200                 bspLeafs[ i ].mins[1] += scale[1];
201                 bspLeafs[ i ].mins[2] += scale[2];
202                 bspLeafs[ i ].maxs[0] += scale[0];
203                 bspLeafs[ i ].maxs[1] += scale[1];
204                 bspLeafs[ i ].maxs[2] += scale[2];
205         }
206
207         /* shift drawverts */
208         for ( i = 0; i < numBSPDrawVerts; i++ )
209         {
210                 bspDrawVerts[i].xyz[0] += scale[0];
211                 bspDrawVerts[i].xyz[1] += scale[1];
212                 bspDrawVerts[i].xyz[2] += scale[2];
213         }
214
215         /* shift planes */
216
217         vec3_t point;
218
219         for ( i = 0; i < numBSPPlanes; i++ )
220         {
221                 //find point on plane
222                 for ( j=0; j<3; j++ ){
223                         if ( fabs( bspPlanes[ i ].normal[j] ) > 0.5 ){
224                                 point[j] = bspPlanes[ i ].dist / bspPlanes[ i ].normal[j];
225                                 point[(j+1)%3] = point[(j+2)%3] = 0;
226                                 break;
227                         }
228                 }
229                 //shift point
230                 for ( j=0; j<3; j++ ){
231                         point[j] += scale[j];
232                 }
233                 //calc new plane dist
234                 bspPlanes[ i ].dist = DotProduct( point, bspPlanes[ i ].normal );
235         }
236
237         /* scale gridsize */
238         /*
239         GetVectorForKey( &entities[ 0 ], "gridsize", vec );
240         if ( ( vec[ 0 ] + vec[ 1 ] + vec[ 2 ] ) == 0.0f ) {
241                 VectorCopy( gridSize, vec );
242         }
243         vec[0] *= scale[0];
244         vec[1] *= scale[1];
245         vec[2] *= scale[2];
246         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
247         SetKeyValue( &entities[ 0 ], "gridsize", str );
248 */
249         /* inject command line parameters */
250         InjectCommandLine( argv, 0, argc - 1 );
251
252         /* write the bsp */
253         UnparseEntities();
254         StripExtension( source );
255         DefaultExtension( source, "_sh.bsp" );
256         Sys_Printf( "Writing %s\n", source );
257         WriteBSPFile( source );
258
259         /* return to sender */
260         return 0;
261 }
262
263
264 void FixDOSName( char *src ){
265         if ( src == NULL ) {
266                 return;
267         }
268
269         while ( *src )
270         {
271                 if ( *src == '\\' ) {
272                         *src = '/';
273                 }
274                 src++;
275         }
276 }
277
278 /*
279         Check if newcoming texture is unique and not excluded
280 */
281 void tex2list( char* texlist, int *texnum, char* EXtex, int *EXtexnum ){
282         int i;
283         if ( token[0] == '\0') return;
284         StripExtension( token );
285         FixDOSName( token );
286         for ( i = 0; i < *texnum; i++ ){
287                 if ( !Q_stricmp( texlist + i*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
1011                         if ( i == pk3ShadersN - 1 ){ //levelshot typically
1012                                 Sys_Printf( "  ~fail  %s\n", pk3Shaders + i*65 );
1013                         }
1014                         else{
1015                                 Sys_Printf( "  !FAIL! %s\n", pk3Shaders + i*65 );
1016                                 packFAIL = qtrue;
1017                         }
1018                 }
1019         }
1020
1021         Sys_Printf( "\n\tShaizers....\n" );
1022
1023         for ( i = 0; i < pk3ShaderfilesN; i++ ){
1024                 if ( *( pk3Shaderfiles + i*65 ) != '\0' ){
1025                         sprintf( temp, "%s/%s", game->shaderPath, pk3Shaderfiles + i*65 );
1026                         if ( vfsPackFile( temp, packname, 10 ) ){
1027                                 Sys_Printf( "++%s\n", temp );
1028                                 continue;
1029                         }
1030                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders + i*65 );
1031                         packFAIL = qtrue;
1032                 }
1033         }
1034
1035         Sys_Printf( "\n\tSounds....\n" );
1036
1037         for ( i = 0; i < pk3SoundsN; i++ ){
1038                 if ( *( pk3Sounds + i*65 ) != '\0' ){
1039                         if ( vfsPackFile( pk3Sounds + i*65, packname, 10 ) ){
1040                                 Sys_Printf( "++%s\n", pk3Sounds + i*65 );
1041                                 continue;
1042                         }
1043                         Sys_Printf( "  !FAIL! %s\n", pk3Sounds + i*65 );
1044                         packFAIL = qtrue;
1045                 }
1046         }
1047
1048         Sys_Printf( "\n\tVideos....\n" );
1049
1050         for ( i = 0; i < pk3VideosN; i++ ){
1051                 if ( vfsPackFile( pk3Videos + i*65, packname, 10 ) ){
1052                         Sys_Printf( "++%s\n", pk3Videos + i*65 );
1053                         continue;
1054                 }
1055                 Sys_Printf( "  !FAIL! %s\n", pk3Videos + i*65 );
1056                 packFAIL = qtrue;
1057         }
1058
1059         Sys_Printf( "\n\t.bsp and stuff\n" );
1060
1061         sprintf( temp, "maps/%s.bsp", nameOFmap );
1062         //if ( vfsPackFile( temp, packname, 10 ) ){
1063         if ( vfsPackFile_Absolute_Path( source, temp, packname, 10 ) ){
1064                         Sys_Printf( "++%s\n", temp );
1065                 }
1066         else{
1067                 Sys_Printf( "  !FAIL! %s\n", temp );
1068                 packFAIL = qtrue;
1069         }
1070
1071         sprintf( temp, "maps/%s.aas", nameOFmap );
1072         if ( vfsPackFile( temp, packname, 10 ) ){
1073                         Sys_Printf( "++%s\n", temp );
1074                 }
1075         else{
1076                 Sys_Printf( "  ~fail  %s\n", temp );
1077         }
1078
1079         sprintf( temp, "scripts/%s.arena", nameOFmap );
1080         if ( vfsPackFile( temp, packname, 10 ) ){
1081                         Sys_Printf( "++%s\n", temp );
1082                 }
1083         else{
1084                 Sys_Printf( "  ~fail  %s\n", temp );
1085         }
1086
1087         sprintf( temp, "scripts/%s.defi", nameOFmap );
1088         if ( vfsPackFile( temp, packname, 10 ) ){
1089                         Sys_Printf( "++%s\n", temp );
1090                 }
1091         else{
1092                 Sys_Printf( "  ~fail  %s\n", temp );
1093         }
1094
1095         if ( !packFAIL ){
1096         Sys_Printf( "\nSaved to %s\n", packname );
1097         }
1098         else{
1099                 rename( packname, packFailName );
1100                 Sys_Printf( "\nSaved to %s\n", packFailName );
1101         }
1102         /* return to sender */
1103         return 0;
1104 }
1105
1106
1107 /*
1108    repackBSPMain()
1109    repack multiple maps, strip out only required shaders
1110    works for Q3 type of shaders and ents
1111  */
1112
1113 int repackBSPMain( int argc, char **argv ){
1114         int i, j, len, compLevel = 0;
1115         qboolean dbg = qfalse, png = qfalse;
1116
1117         /* process arguments */
1118         for ( i = 1; i < ( argc - 1 ); i++ ){
1119                 if ( !strcmp( argv[ i ],  "-dbg" ) ) {
1120                         dbg = qtrue;
1121                 }
1122                 else if ( !strcmp( argv[ i ],  "-png" ) ) {
1123                         png = qtrue;
1124                 }
1125                 else if ( !strcmp( argv[ i ],  "-complevel" ) ) {
1126                         compLevel = atoi( argv[ i + 1 ] );
1127                         i++;
1128                         if ( compLevel < -1 ) compLevel = -1;
1129                         if ( compLevel > 10 ) compLevel = 10;
1130                         Sys_Printf( "Compression level set to %i\n", compLevel );
1131                 }
1132         }
1133
1134 /* load exclusions file */
1135         int ExTexturesN = 0;
1136         char* ExTextures = (char *)calloc( 4096*65, sizeof( char ) );
1137         int ExShadersN = 0;
1138         char* ExShaders = (char *)calloc( 4096*65, sizeof( char ) );
1139         int ExSoundsN = 0;
1140         char* ExSounds = (char *)calloc( 4096*65, sizeof( char ) );
1141         int ExShaderfilesN = 0;
1142         char* ExShaderfiles = (char *)calloc( 4096*65, sizeof( char ) );
1143         int ExVideosN = 0;
1144         char* ExVideos = (char *)calloc( 4096*65, sizeof( char ) );
1145         int ExPureTexturesN = 0;
1146         char* ExPureTextures = (char *)calloc( 4096*65, sizeof( char ) );
1147
1148
1149         char exName[ 1024 ];
1150         byte *buffer;
1151         int size;
1152
1153         strcpy( exName, q3map2path );
1154         char *cut = strrchr( exName, '\\' );
1155         char *cut2 = strrchr( exName, '/' );
1156         if ( cut == NULL && cut2 == NULL ){
1157                 Sys_Printf( "WARNING: Unable to load exclusions file.\n" );
1158                 goto skipEXfile;
1159         }
1160         if ( cut2 > cut ) cut = cut2;
1161         cut[1] = '\0';
1162         strcat( exName, game->arg );
1163         strcat( exName, ".exclude" );
1164
1165         Sys_Printf( "Loading %s\n", exName );
1166         size = TryLoadFile( exName, (void**) &buffer );
1167         if ( size <= 0 ) {
1168                 Sys_Printf( "WARNING: Unable to find exclusions file %s.\n", exName );
1169                 goto skipEXfile;
1170         }
1171
1172         /* parse the file */
1173         ParseFromMemory( (char *) buffer, size );
1174
1175         /* tokenize it */
1176         while ( 1 )
1177         {
1178                 /* test for end of file */
1179                 if ( !GetToken( qtrue ) ) {
1180                         break;
1181                 }
1182
1183                 /* blocks */
1184                 if ( !Q_stricmp( token, "textures" ) ){
1185                         parseEXblock ( ExTextures, &ExTexturesN, exName );
1186                 }
1187                 else if ( !Q_stricmp( token, "shaders" ) ){
1188                         parseEXblock ( ExShaders, &ExShadersN, exName );
1189                 }
1190                 else if ( !Q_stricmp( token, "shaderfiles" ) ){
1191                         parseEXblock ( ExShaderfiles, &ExShaderfilesN, exName );
1192                 }
1193                 else if ( !Q_stricmp( token, "sounds" ) ){
1194                         parseEXblock ( ExSounds, &ExSoundsN, exName );
1195                 }
1196                 else if ( !Q_stricmp( token, "videos" ) ){
1197                         parseEXblock ( ExVideos, &ExVideosN, exName );
1198                 }
1199                 else{
1200                         Error( "ReadExclusionsFile: %s, line %d: unknown block name!\nValid ones are: textures, shaders, shaderfiles, sounds, videos.", exName, scriptline );
1201                 }
1202         }
1203
1204         /* free the buffer */
1205         free( buffer );
1206
1207         for ( i = 0; i < ExTexturesN; i++ ){
1208                 for ( j = 0; j < ExShadersN; j++ ){
1209                         if ( !Q_stricmp( ExTextures + i*65, ExShaders + j*65 ) ){
1210                                 break;
1211                         }
1212                 }
1213                 if ( j == ExShadersN ){
1214                         strcpy ( ExPureTextures + ExPureTexturesN*65, ExTextures + i*65 );
1215                         ExPureTexturesN++;
1216                 }
1217         }
1218
1219 skipEXfile:
1220
1221         if( dbg ){
1222                 Sys_Printf( "\n\tExTextures....%i\n", ExTexturesN );
1223                 for ( i = 0; i < ExTexturesN; i++ ) Sys_Printf( "%s\n", ExTextures + i*65 );
1224                 Sys_Printf( "\n\tExPureTextures....%i\n", ExPureTexturesN );
1225                 for ( i = 0; i < ExPureTexturesN; i++ ) Sys_Printf( "%s\n", ExPureTextures + i*65 );
1226                 Sys_Printf( "\n\tExShaders....%i\n", ExShadersN );
1227                 for ( i = 0; i < ExShadersN; i++ ) Sys_Printf( "%s\n", ExShaders + i*65 );
1228                 Sys_Printf( "\n\tExShaderfiles....%i\n", ExShaderfilesN );
1229                 for ( i = 0; i < ExShaderfilesN; i++ ) Sys_Printf( "%s\n", ExShaderfiles + i*65 );
1230                 Sys_Printf( "\n\tExSounds....%i\n", ExSoundsN );
1231                 for ( i = 0; i < ExSoundsN; i++ ) Sys_Printf( "%s\n", ExSounds + i*65 );
1232                 Sys_Printf( "\n\tExVideos....%i\n", ExVideosN );
1233                 for ( i = 0; i < ExVideosN; i++ ) Sys_Printf( "%s\n", ExVideos + i*65 );
1234         }
1235
1236
1237
1238
1239 /* load repack.exclude */
1240         int rExTexturesN = 0;
1241         char* rExTextures = (char *)calloc( 65536*65, sizeof( char ) );
1242         int rExShadersN = 0;
1243         char* rExShaders = (char *)calloc( 32768*65, sizeof( char ) );
1244         int rExSoundsN = 0;
1245         char* rExSounds = (char *)calloc( 8192*65, sizeof( char ) );
1246         int rExShaderfilesN = 0;
1247         char* rExShaderfiles = (char *)calloc( 4096*65, sizeof( char ) );
1248         int rExVideosN = 0;
1249         char* rExVideos = (char *)calloc( 4096*65, sizeof( char ) );
1250
1251         strcpy( exName, q3map2path );
1252         cut = strrchr( exName, '\\' );
1253         cut2 = strrchr( exName, '/' );
1254         if ( cut == NULL && cut2 == NULL ){
1255                 Sys_Printf( "WARNING: Unable to load repack exclusions file.\n" );
1256                 goto skipEXrefile;
1257         }
1258         if ( cut2 > cut ) cut = cut2;
1259         cut[1] = '\0';
1260         strcat( exName, "repack.exclude" );
1261
1262         Sys_Printf( "Loading %s\n", exName );
1263         size = TryLoadFile( exName, (void**) &buffer );
1264         if ( size <= 0 ) {
1265                 Sys_Printf( "WARNING: Unable to find repack exclusions file %s.\n", exName );
1266                 goto skipEXrefile;
1267         }
1268
1269         /* parse the file */
1270         ParseFromMemory( (char *) buffer, size );
1271
1272         /* tokenize it */
1273         while ( 1 )
1274         {
1275                 /* test for end of file */
1276                 if ( !GetToken( qtrue ) ) {
1277                         break;
1278                 }
1279
1280                 /* blocks */
1281                 if ( !Q_stricmp( token, "textures" ) ){
1282                         parseEXblock ( rExTextures, &rExTexturesN, exName );
1283                 }
1284                 else if ( !Q_stricmp( token, "shaders" ) ){
1285                         parseEXblock ( rExShaders, &rExShadersN, exName );
1286                 }
1287                 else if ( !Q_stricmp( token, "shaderfiles" ) ){
1288                         parseEXblock ( rExShaderfiles, &rExShaderfilesN, exName );
1289                 }
1290                 else if ( !Q_stricmp( token, "sounds" ) ){
1291                         parseEXblock ( rExSounds, &rExSoundsN, exName );
1292                 }
1293                 else if ( !Q_stricmp( token, "videos" ) ){
1294                         parseEXblock ( rExVideos, &rExVideosN, exName );
1295                 }
1296                 else{
1297                         Error( "ReadExclusionsFile: %s, line %d: unknown block name!\nValid ones are: textures, shaders, shaderfiles, sounds, videos.", exName, scriptline );
1298                 }
1299         }
1300
1301         /* free the buffer */
1302         free( buffer );
1303
1304 skipEXrefile:
1305
1306         if( dbg ){
1307                 Sys_Printf( "\n\trExTextures....%i\n", rExTexturesN );
1308                 for ( i = 0; i < rExTexturesN; i++ ) Sys_Printf( "%s\n", rExTextures + i*65 );
1309                 Sys_Printf( "\n\trExShaders....%i\n", rExShadersN );
1310                 for ( i = 0; i < rExShadersN; i++ ) Sys_Printf( "%s\n", rExShaders + i*65 );
1311                 Sys_Printf( "\n\trExShaderfiles....%i\n", rExShaderfilesN );
1312                 for ( i = 0; i < rExShaderfilesN; i++ ) Sys_Printf( "%s\n", rExShaderfiles + i*65 );
1313                 Sys_Printf( "\n\trExSounds....%i\n", rExSoundsN );
1314                 for ( i = 0; i < rExSoundsN; i++ ) Sys_Printf( "%s\n", rExSounds + i*65 );
1315                 Sys_Printf( "\n\trExVideos....%i\n", rExVideosN );
1316                 for ( i = 0; i < rExVideosN; i++ ) Sys_Printf( "%s\n", rExVideos + i*65 );
1317         }
1318
1319
1320
1321
1322         int bspListN = 0;
1323         char* bspList = (char *)calloc( 8192*1024, sizeof( char ) );
1324
1325         /* do some path mangling */
1326         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
1327         if ( !Q_stricmp( strrchr( source, '.' ), ".bsp" ) ){
1328                 strcpy( bspList, source );
1329                 bspListN++;
1330         }
1331         else{
1332                 /* load bsps paths list */
1333                 Sys_Printf( "Loading %s\n", source );
1334                 size = TryLoadFile( source, (void**) &buffer );
1335                 if ( size <= 0 ) {
1336                         Sys_Printf( "WARNING: Unable to open bsps paths list file %s.\n", source );
1337                 }
1338
1339                 /* parse the file */
1340                 ParseFromMemory( (char *) buffer, size );
1341
1342                 /* tokenize it */
1343                 while ( 1 )
1344                 {
1345                         /* test for end of file */
1346                         if ( !GetToken( qtrue ) ) {
1347                                 break;
1348                         }
1349                         strcpy( bspList + bspListN * 1024 , token );
1350                         bspListN++;
1351                 }
1352
1353                 /* free the buffer */
1354                 free( buffer );
1355         }
1356
1357         char packname[ 1024 ], nameOFrepack[ 1024 ], nameOFmap[ 1024 ], temp[ 1024 ];
1358
1359         /* copy input file name */
1360         strcpy( temp, source );
1361         StripExtension( temp );
1362
1363         /* extract input file name */
1364         len = strlen( temp ) - 1;
1365         while ( len > 0 && temp[ len ] != '/' && temp[ len ] != '\\' )
1366                 len--;
1367         strcpy( nameOFrepack, &temp[ len + 1 ] );
1368
1369
1370 /* load bsps */
1371         int pk3ShadersN = 0;
1372         char* pk3Shaders = (char *)calloc( 65536*65, sizeof( char ) );
1373         int pk3SoundsN = 0;
1374         char* pk3Sounds = (char *)calloc( 4096*65, sizeof( char ) );
1375         int pk3ShaderfilesN = 0;
1376         char* pk3Shaderfiles = (char *)calloc( 4096*65, sizeof( char ) );
1377         int pk3TexturesN = 0;
1378         char* pk3Textures = (char *)calloc( 65536*65, sizeof( char ) );
1379         int pk3VideosN = 0;
1380         char* pk3Videos = (char *)calloc( 1024*65, sizeof( char ) );
1381
1382         for( j = 0; j < bspListN; j++ ){
1383
1384                 int pk3SoundsNold = pk3SoundsN;
1385                 int pk3ShadersNold = pk3ShadersN;
1386
1387                 strcpy( source, bspList + j*1024 );
1388                 StripExtension( source );
1389                 DefaultExtension( source, ".bsp" );
1390
1391                 /* load the bsp */
1392                 Sys_Printf( "\nLoading %s\n", source );
1393                 PartialLoadBSPFile( source );
1394                 ParseEntities();
1395
1396                 /* copy map name */
1397                 strcpy( temp, source );
1398                 StripExtension( temp );
1399
1400                 /* extract map name */
1401                 len = strlen( temp ) - 1;
1402                 while ( len > 0 && temp[ len ] != '/' && temp[ len ] != '\\' )
1403                         len--;
1404                 strcpy( nameOFmap, &temp[ len + 1 ] );
1405
1406
1407                 qboolean drawsurfSHs[1024] = { qfalse };
1408
1409                 for ( i = 0; i < numBSPDrawSurfaces; i++ ){
1410                         drawsurfSHs[ bspDrawSurfaces[i].shaderNum ] = qtrue;
1411                 }
1412
1413                 for ( i = 0; i < numBSPShaders; i++ ){
1414                         if ( drawsurfSHs[i] ){
1415                                 strcpy( pk3Shaders + pk3ShadersN*65, bspShaders[i].shader );
1416                                 res2list( pk3Shaders, &pk3ShadersN );
1417                         }
1418                 }
1419
1420                 /* Ent keys */
1421                 epair_t *ep;
1422                 for ( ep = entities[0].epairs; ep != NULL; ep = ep->next )
1423                 {
1424                         if ( !Q_strncasecmp( ep->key, "vertexremapshader", 17 ) ) {
1425                                 sscanf( ep->value, "%*[^;] %*[;] %s", pk3Shaders + pk3ShadersN*65 );
1426                                 res2list( pk3Shaders, &pk3ShadersN );
1427                         }
1428                 }
1429                 strcpy( pk3Sounds + pk3SoundsN*65, ValueForKey( &entities[0], "music" ) );
1430                 if ( *( pk3Sounds + pk3SoundsN*65 ) != '\0' ){
1431                         FixDOSName( pk3Sounds + pk3SoundsN*65 );
1432                         DefaultExtension( pk3Sounds + pk3SoundsN*65, ".wav" );
1433                         res2list( pk3Sounds, &pk3SoundsN );
1434                 }
1435
1436                 for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
1437                 {
1438                         strcpy( pk3Sounds + pk3SoundsN*65, ValueForKey( &entities[i], "noise" ) );
1439                         if ( *( pk3Sounds + pk3SoundsN*65 ) != '\0' && *( pk3Sounds + pk3SoundsN*65 ) != '*' ){
1440                                 FixDOSName( pk3Sounds + pk3SoundsN*65 );
1441                                 DefaultExtension( pk3Sounds + pk3SoundsN*65, ".wav" );
1442                                 res2list( pk3Sounds, &pk3SoundsN );
1443                         }
1444
1445                         if ( !Q_stricmp( ValueForKey( &entities[i], "classname" ), "func_plat" ) ){
1446                                 strcpy( pk3Sounds + pk3SoundsN*65, "sound/movers/plats/pt1_strt.wav");
1447                                 res2list( pk3Sounds, &pk3SoundsN );
1448                                 strcpy( pk3Sounds + pk3SoundsN*65, "sound/movers/plats/pt1_end.wav");
1449                                 res2list( pk3Sounds, &pk3SoundsN );
1450                         }
1451                         if ( !Q_stricmp( ValueForKey( &entities[i], "classname" ), "target_push" ) ){
1452                                 if ( !(IntForKey( &entities[i], "spawnflags") & 1) ){
1453                                         strcpy( pk3Sounds + pk3SoundsN*65, "sound/misc/windfly.wav");
1454                                         res2list( pk3Sounds, &pk3SoundsN );
1455                                 }
1456                         }
1457                         strcpy( pk3Shaders + pk3ShadersN*65, ValueForKey( &entities[i], "targetShaderNewName" ) );
1458                         res2list( pk3Shaders, &pk3ShadersN );
1459                 }
1460
1461                 //levelshot
1462                 sprintf( pk3Shaders + pk3ShadersN*65, "levelshots/%s", nameOFmap );
1463                 res2list( pk3Shaders, &pk3ShadersN );
1464
1465
1466
1467                 Sys_Printf( "\n\t+Drawsurface+ent calls....%i\n", pk3ShadersN - pk3ShadersNold );
1468                 for ( i = pk3ShadersNold; i < pk3ShadersN; i++ ){
1469                         Sys_Printf( "%s\n", pk3Shaders + i*65 );
1470                 }
1471                 Sys_Printf( "\n\t+Sounds....%i\n", pk3SoundsN - pk3SoundsNold );
1472                 for ( i = pk3SoundsNold; i < pk3SoundsN; i++ ){
1473                         Sys_Printf( "%s\n", pk3Sounds + i*65 );
1474                 }
1475                 /* free bsp data */
1476 /*
1477                 if ( bspDrawVerts != 0 ) {
1478                         free( bspDrawVerts );
1479                         bspDrawVerts = NULL;
1480                         //numBSPDrawVerts = 0;
1481                         Sys_Printf( "freed BSPDrawVerts\n" );
1482                 }
1483 */              if ( bspDrawSurfaces != 0 ) {
1484                         free( bspDrawSurfaces );
1485                         bspDrawSurfaces = NULL;
1486                         //numBSPDrawSurfaces = 0;
1487                         //Sys_Printf( "freed bspDrawSurfaces\n" );
1488                 }
1489 /*              if ( bspLightBytes != 0 ) {
1490                         free( bspLightBytes );
1491                         bspLightBytes = NULL;
1492                         //numBSPLightBytes = 0;
1493                         Sys_Printf( "freed BSPLightBytes\n" );
1494                 }
1495                 if ( bspGridPoints != 0 ) {
1496                         free( bspGridPoints );
1497                         bspGridPoints = NULL;
1498                         //numBSPGridPoints = 0;
1499                         Sys_Printf( "freed BSPGridPoints\n" );
1500                 }
1501                 if ( bspPlanes != 0 ) {
1502                         free( bspPlanes );
1503                         bspPlanes = NULL;
1504                         Sys_Printf( "freed bspPlanes\n" );
1505                         //numBSPPlanes = 0;
1506                         //allocatedBSPPlanes = 0;
1507                 }
1508                 if ( bspBrushes != 0 ) {
1509                         free( bspBrushes );
1510                         bspBrushes = NULL;
1511                         Sys_Printf( "freed bspBrushes\n" );
1512                         //numBSPBrushes = 0;
1513                         //allocatedBSPBrushes = 0;
1514                 }
1515 */              if ( entities != 0 ) {
1516                         epair_t *ep2free;
1517                         for ( i = 0; i < numBSPEntities && i < numEntities; i++ ){
1518                                 ep = entities[i].epairs;
1519                                 while( ep != NULL){
1520                                         ep2free = ep;
1521                                         ep = ep->next;
1522                                         free( ep2free );
1523                                 }
1524                         }
1525                         free( entities );
1526                         entities = NULL;
1527                         //Sys_Printf( "freed entities\n" );
1528                         numEntities = 0;
1529                         numBSPEntities = 0;
1530                         allocatedEntities = 0;
1531                 }
1532 /*              if ( bspModels != 0 ) {
1533                         free( bspModels );
1534                         bspModels = NULL;
1535                         Sys_Printf( "freed bspModels\n" );
1536                         //numBSPModels = 0;
1537                         //allocatedBSPModels = 0;
1538                 }
1539 */              if ( bspShaders != 0 ) {
1540                         free( bspShaders );
1541                         bspShaders = NULL;
1542                         //Sys_Printf( "freed bspShaders\n" );
1543                         //numBSPShaders = 0;
1544                         //allocatedBSPShaders = 0;
1545                 }
1546                 if ( bspEntData != 0 ) {
1547                         free( bspEntData );
1548                         bspEntData = NULL;
1549                         //Sys_Printf( "freed bspEntData\n" );
1550                         //bspEntDataSize = 0;
1551                         //allocatedBSPEntData = 0;
1552                 }
1553 /*              if ( bspNodes != 0 ) {
1554                         free( bspNodes );
1555                         bspNodes = NULL;
1556                         Sys_Printf( "freed bspNodes\n" );
1557                         //numBSPNodes = 0;
1558                         //allocatedBSPNodes = 0;
1559                 }
1560                 if ( bspDrawIndexes != 0 ) {
1561                         free( bspDrawIndexes );
1562                         bspDrawIndexes = NULL;
1563                         Sys_Printf( "freed bspDrawIndexes\n" );
1564                         //numBSPDrawIndexes = 0;
1565                         //allocatedBSPDrawIndexes = 0;
1566                 }
1567                 if ( bspLeafSurfaces != 0 ) {
1568                         free( bspLeafSurfaces );
1569                         bspLeafSurfaces = NULL;
1570                         Sys_Printf( "freed bspLeafSurfaces\n" );
1571                         //numBSPLeafSurfaces = 0;
1572                         //allocatedBSPLeafSurfaces = 0;
1573                 }
1574                 if ( bspLeafBrushes != 0 ) {
1575                         free( bspLeafBrushes );
1576                         bspLeafBrushes = NULL;
1577                         Sys_Printf( "freed bspLeafBrushes\n" );
1578                         //numBSPLeafBrushes = 0;
1579                         //allocatedBSPLeafBrushes = 0;
1580                 }
1581                 if ( bspBrushSides != 0 ) {
1582                         free( bspBrushSides );
1583                         bspBrushSides = NULL;
1584                         Sys_Printf( "freed bspBrushSides\n" );
1585                         numBSPBrushSides = 0;
1586                         allocatedBSPBrushSides = 0;
1587                 }
1588                 if ( numBSPFogs != 0 ) {
1589                         Sys_Printf( "freed numBSPFogs\n" );
1590                         numBSPFogs = 0;
1591                 }
1592                 if ( numBSPAds != 0 ) {
1593                         Sys_Printf( "freed numBSPAds\n" );
1594                         numBSPAds = 0;
1595                 }
1596                 if ( numBSPLeafs != 0 ) {
1597                         Sys_Printf( "freed numBSPLeafs\n" );
1598                         numBSPLeafs = 0;
1599                 }
1600                 if ( numBSPVisBytes != 0 ) {
1601                         Sys_Printf( "freed numBSPVisBytes\n" );
1602                         numBSPVisBytes = 0;
1603                 }
1604 */      }
1605
1606
1607
1608         vfsListShaderFiles( pk3Shaderfiles, &pk3ShaderfilesN );
1609
1610         if( dbg ){
1611                 Sys_Printf( "\n\tSchroider fileses.....%i\n", pk3ShaderfilesN );
1612                 for ( i = 0; i < pk3ShaderfilesN; i++ ){
1613                         Sys_Printf( "%s\n", pk3Shaderfiles + i*65 );
1614                 }
1615         }
1616
1617
1618
1619         /* can exclude pure *base* textures right now, shouldn't create shaders for them anyway */
1620         for ( i = 0; i < pk3ShadersN ; i++ ){
1621                 for ( j = 0; j < ExPureTexturesN ; j++ ){
1622                         if ( !Q_stricmp( pk3Shaders + i*65, ExPureTextures + j*65 ) ){
1623                                 *( pk3Shaders + i*65 ) = '\0';
1624                                 break;
1625                         }
1626                 }
1627         }
1628         /* can exclude repack.exclude shaders, assuming they got all their images */
1629         for ( i = 0; i < pk3ShadersN ; i++ ){
1630                 for ( j = 0; j < rExShadersN ; j++ ){
1631                         if ( !Q_stricmp( pk3Shaders + i*65, rExShaders + j*65 ) ){
1632                                 *( pk3Shaders + i*65 ) = '\0';
1633                                 break;
1634                         }
1635                 }
1636         }
1637
1638         //Parse Shader Files
1639         Sys_Printf( "\t\nParsing shaders....\n\n" );
1640         char shaderText[ 8192 ];
1641         char* allShaders = (char *)calloc( 16777216, sizeof( char ) );
1642          /* hack */
1643         endofscript = qtrue;
1644
1645         for ( i = 0; i < pk3ShaderfilesN; i++ ){
1646                 qboolean wantShader = qfalse;
1647                 int shader;
1648
1649                 /* load the shader */
1650                 sprintf( temp, "%s/%s", game->shaderPath, pk3Shaderfiles + i*65 );
1651                 if ( dbg ) Sys_Printf( "\n\tentering %s\n", pk3Shaderfiles + i*65 );
1652                 SilentLoadScriptFile( temp, 0 );
1653
1654                 /* tokenize it */
1655                 while ( 1 )
1656                 {
1657                         int line = scriptline;
1658                         /* test for end of file */
1659                         if ( !GetToken( qtrue ) ) {
1660                                 break;
1661                         }
1662                         //dump shader names
1663                         if( dbg ) Sys_Printf( "%s\n", token );
1664
1665                         strcpy( shaderText, token );
1666
1667                         if ( strchr( token, '\\') != NULL  ){
1668                                 Sys_Printf( "WARNING1: %s : %s : shader name with backslash\n", pk3Shaderfiles + i*65, token );
1669                         }
1670
1671                         /* do wanna le shader? */
1672                         wantShader = qfalse;
1673                         for ( j = 0; j < pk3ShadersN; j++ ){
1674                                 if ( !Q_stricmp( pk3Shaders + j*65, token) ){
1675                                         shader = j;
1676                                         wantShader = qtrue;
1677                                         break;
1678                                 }
1679                         }
1680                         if ( wantShader ){
1681                                 for ( j = 0; j < rExTexturesN ; j++ ){
1682                                         if ( !Q_stricmp( pk3Shaders + shader*65, rExTextures + j*65 ) ){
1683                                                 Sys_Printf( "WARNING3: %s : about to include shader for excluded texture\n", pk3Shaders + shader*65 );
1684                                                 break;
1685                                         }
1686                                 }
1687                         }
1688
1689                         /* handle { } section */
1690                         if ( !GetToken( qtrue ) ) {
1691                                 break;
1692                         }
1693                         if ( strcmp( token, "{" ) ) {
1694                                         Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s\nFile location be: %s",
1695                                                 temp, scriptline, token, g_strLoadedFileLocation );
1696                         }
1697                         strcat( shaderText, "\n{" );
1698                         qboolean hasmap = qfalse;
1699
1700                         while ( 1 )
1701                         {
1702                                 line = scriptline;
1703                                 /* get the next token */
1704                                 if ( !GetToken( qtrue ) ) {
1705                                         break;
1706                                 }
1707                                 if ( !strcmp( token, "}" ) ) {
1708                                         strcat( shaderText, "\n}\n\n" );
1709                                         break;
1710                                 }
1711                                 /* parse stage directives */
1712                                 if ( !strcmp( token, "{" ) ) {
1713                                         qboolean tokenready = qfalse;
1714                                         strcat( shaderText, "\n\t{" );
1715                                         while ( 1 )
1716                                         {
1717                                                 /* detour of TokenAvailable() '~' */
1718                                                 if ( tokenready ) tokenready = qfalse;
1719                                                 else line = scriptline;
1720                                                 if ( !GetToken( qtrue ) ) {
1721                                                         break;
1722                                                 }
1723                                                 if ( !strcmp( token, "}" ) ) {
1724                                                         strcat( shaderText, "\n\t}" );
1725                                                         break;
1726                                                 }
1727                                                 if ( !strcmp( token, "{" ) ) {
1728                                                         strcat( shaderText, "\n\t{" );
1729                                                         Sys_Printf( "WARNING9: %s : line %d : opening brace inside shader stage\n", temp, scriptline );
1730                                                 }
1731                                                 /* skip the shader */
1732                                                 if ( !wantShader ) continue;
1733
1734                                                 /* digest any images */
1735                                                 if ( !Q_stricmp( token, "map" ) ||
1736                                                         !Q_stricmp( token, "clampMap" ) ) {
1737                                                         strcat( shaderText, "\n\t\t" );
1738                                                         strcat( shaderText, token );
1739                                                         hasmap = qtrue;
1740
1741                                                         /* get an image */
1742                                                         GetToken( qfalse );
1743                                                         if ( token[ 0 ] != '*' && token[ 0 ] != '$' ) {
1744                                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1745                                                         }
1746                                                         strcat( shaderText, " " );
1747                                                         strcat( shaderText, token );
1748                                                 }
1749                                                 else if ( !Q_stricmp( token, "animMap" ) ||
1750                                                         !Q_stricmp( token, "clampAnimMap" ) ) {
1751                                                         strcat( shaderText, "\n\t\t" );
1752                                                         strcat( shaderText, token );
1753                                                         hasmap = qtrue;
1754
1755                                                         GetToken( qfalse );// skip num
1756                                                         strcat( shaderText, " " );
1757                                                         strcat( shaderText, token );
1758                                                         while ( TokenAvailable() ){
1759                                                                 GetToken( qfalse );
1760                                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1761                                                                 strcat( shaderText, " " );
1762                                                                 strcat( shaderText, token );
1763                                                         }
1764                                                         tokenready = qtrue;
1765                                                 }
1766                                                 else if ( !Q_stricmp( token, "videoMap" ) ){
1767                                                         strcat( shaderText, "\n\t\t" );
1768                                                         strcat( shaderText, token );
1769                                                         hasmap = qtrue;
1770                                                         GetToken( qfalse );
1771                                                         strcat( shaderText, " " );
1772                                                         strcat( shaderText, token );
1773                                                         FixDOSName( token );
1774                                                         if ( strchr( token, '/' ) == NULL && strchr( token, '\\' ) == NULL ){
1775                                                                 sprintf( temp, "video/%s", token );
1776                                                                 strcpy( token, temp );
1777                                                         }
1778                                                         FixDOSName( token );
1779                                                         for ( j = 0; j < pk3VideosN; j++ ){
1780                                                                 if ( !Q_stricmp( pk3Videos + j*65, token ) ){
1781                                                                         goto away;
1782                                                                 }
1783                                                         }
1784                                                         for ( j = 0; j < ExVideosN; j++ ){
1785                                                                 if ( !Q_stricmp( ExVideos + j*65, token ) ){
1786                                                                         goto away;
1787                                                                 }
1788                                                         }
1789                                                         for ( j = 0; j < rExVideosN; j++ ){
1790                                                                 if ( !Q_stricmp( rExVideos + j*65, token ) ){
1791                                                                         goto away;
1792                                                                 }
1793                                                         }
1794                                                         strcpy ( pk3Videos + pk3VideosN*65, token );
1795                                                         pk3VideosN++;
1796                                                         away:
1797                                                         j = 0;
1798                                                 }
1799                                                 else if ( !Q_stricmp( token, "mapComp" ) || !Q_stricmp( token, "mapNoComp" ) || !Q_stricmp( token, "animmapcomp" ) || !Q_stricmp( token, "animmapnocomp" ) ){
1800                                                         Sys_Printf( "WARNING7: %s : %s shader\n", pk3Shaders + shader*65, token );
1801                                                         hasmap = qtrue;
1802                                                         if ( line == scriptline ){
1803                                                                 strcat( shaderText, " " );
1804                                                                 strcat( shaderText, token );
1805                                                         }
1806                                                         else{
1807                                                                 strcat( shaderText, "\n\t\t" );
1808                                                                 strcat( shaderText, token );
1809                                                         }
1810                                                 }
1811                                                 else if ( line == scriptline ){
1812                                                         strcat( shaderText, " " );
1813                                                         strcat( shaderText, token );
1814                                                 }
1815                                                 else{
1816                                                         strcat( shaderText, "\n\t\t" );
1817                                                         strcat( shaderText, token );
1818                                                 }
1819                                         }
1820                                 }
1821                                 /* skip the shader */
1822                                 else if ( !wantShader ) continue;
1823
1824                                 /* -----------------------------------------------------------------
1825                                 surfaceparm * directives
1826                                 ----------------------------------------------------------------- */
1827
1828                                 /* match surfaceparm */
1829                                 else if ( !Q_stricmp( token, "surfaceparm" ) ) {
1830                                         strcat( shaderText, "\n\tsurfaceparm " );
1831                                         GetToken( qfalse );
1832                                         strcat( shaderText, token );
1833                                         if ( !Q_stricmp( token, "nodraw" ) ) {
1834                                                 wantShader = qfalse;
1835                                                 *( pk3Shaders + shader*65 ) = '\0';
1836                                         }
1837                                 }
1838
1839                                 /* skyparms <outer image> <cloud height> <inner image> */
1840                                 else if ( !Q_stricmp( token, "skyParms" ) ) {
1841                                         strcat( shaderText, "\n\tskyParms " );
1842                                         hasmap = qtrue;
1843                                         /* get image base */
1844                                         GetToken( qfalse );
1845                                         strcat( shaderText, token );
1846
1847                                         /* ignore bogus paths */
1848                                         if ( Q_stricmp( token, "-" ) && Q_stricmp( token, "full" ) ) {
1849                                                 strcpy ( temp, token );
1850                                                 sprintf( token, "%s_up", temp );
1851                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1852                                                 sprintf( token, "%s_dn", temp );
1853                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1854                                                 sprintf( token, "%s_lf", temp );
1855                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1856                                                 sprintf( token, "%s_rt", temp );
1857                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1858                                                 sprintf( token, "%s_bk", temp );
1859                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1860                                                 sprintf( token, "%s_ft", temp );
1861                                                 tex2list2( pk3Textures, &pk3TexturesN, ExTextures, &ExTexturesN, rExTextures, &rExTexturesN );
1862                                         }
1863                                         /* skip rest of line */
1864                                         GetToken( qfalse );
1865                                         strcat( shaderText, " " );
1866                                         strcat( shaderText, token );
1867                                         GetToken( qfalse );
1868                                         strcat( shaderText, " " );
1869                                         strcat( shaderText, token );
1870                                 }
1871                                 else if ( !Q_strncasecmp( token, "implicit", 8 ) ){
1872                                         Sys_Printf( "WARNING5: %s : %s shader\n", pk3Shaders + shader*65, token );
1873                                         hasmap = qtrue;
1874                                         if ( line == scriptline ){
1875                                                 strcat( shaderText, " " );
1876                                                 strcat( shaderText, token );
1877                                         }
1878                                         else{
1879                                                 strcat( shaderText, "\n\t" );
1880                                                 strcat( shaderText, token );
1881                                         }
1882                                 }
1883                                 else if ( !Q_stricmp( token, "fogparms" ) ){
1884                                         hasmap = qtrue;
1885                                         if ( line == scriptline ){
1886                                                 strcat( shaderText, " " );
1887                                                 strcat( shaderText, token );
1888                                         }
1889                                         else{
1890                                                 strcat( shaderText, "\n\t" );
1891                                                 strcat( shaderText, token );
1892                                         }
1893                                 }
1894                                 else if ( line == scriptline ){
1895                                         strcat( shaderText, " " );
1896                                         strcat( shaderText, token );
1897                                 }
1898                                 else{
1899                                         strcat( shaderText, "\n\t" );
1900                                         strcat( shaderText, token );
1901                                 }
1902                         }
1903
1904                         //exclude shader
1905                         if ( wantShader ){
1906                                 for ( j = 0; j < ExShadersN; j++ ){
1907                                         if ( !Q_stricmp( ExShaders + j*65, pk3Shaders + shader*65 ) ){
1908                                                 wantShader = qfalse;
1909                                                 *( pk3Shaders + shader*65 ) = '\0';
1910                                                 break;
1911                                         }
1912                                 }
1913                                 if ( wantShader && !hasmap ){
1914                                         Sys_Printf( "WARNING8: %s : shader has no known maps\n", pk3Shaders + shader*65 );
1915                                         wantShader = qfalse;
1916                                         *( pk3Shaders + shader*65 ) = '\0';
1917                                 }
1918                                 if ( wantShader ){
1919                                         strcat( allShaders, shaderText );
1920                                         *( pk3Shaders + shader*65 ) = '\0';
1921                                 }
1922                         }
1923                 }
1924         }
1925 /* TODO: RTCW's mapComp, mapNoComp, animmapcomp, animmapnocomp; nocompress?; ET's implicitmap, implicitblend, implicitmask */
1926
1927
1928 /* exclude stuff */
1929
1930 //pure textures (shader ones are done)
1931         for ( i = 0; i < pk3ShadersN; i++ ){
1932                 if ( *( pk3Shaders + i*65 ) != '\0' ){
1933                         if ( strchr( pk3Shaders + i*65, '\\') != NULL  ){
1934                                 Sys_Printf( "WARNING2: %s : bsp shader path with backslash\n", pk3Shaders + i*65 );
1935                                 FixDOSName( pk3Shaders + i*65 );
1936                                 //what if theres properly slashed one in the list?
1937                                 for ( j = 0; j < pk3ShadersN; j++ ){
1938                                         if ( !Q_stricmp( pk3Shaders + i*65, pk3Shaders + j*65 ) && (i != j) ){
1939                                                 *( pk3Shaders + i*65 ) = '\0';
1940                                                 break;
1941                                         }
1942                                 }
1943                         }
1944                         if ( *( pk3Shaders + i*65 ) == '\0' ) continue;
1945                         for ( j = 0; j < pk3TexturesN; j++ ){
1946                                 if ( !Q_stricmp( pk3Shaders + i*65, pk3Textures + j*65 ) ){
1947                                         *( pk3Shaders + i*65 ) = '\0';
1948                                         break;
1949                                 }
1950                         }
1951                         if ( *( pk3Shaders + i*65 ) == '\0' ) continue;
1952                         for ( j = 0; j < ExTexturesN; j++ ){
1953                                 if ( !Q_stricmp( pk3Shaders + i*65, ExTextures + j*65 ) ){
1954                                         *( pk3Shaders + i*65 ) = '\0';
1955                                         break;
1956                                 }
1957                         }
1958                         if ( *( pk3Shaders + i*65 ) == '\0' ) continue;
1959                         for ( j = 0; j < rExTexturesN; j++ ){
1960                                 if ( !Q_stricmp( pk3Shaders + i*65, rExTextures + j*65 ) ){
1961                                         *( pk3Shaders + i*65 ) = '\0';
1962                                         break;
1963                                 }
1964                         }
1965                 }
1966         }
1967
1968 //snds
1969         for ( i = 0; i < pk3SoundsN; i++ ){
1970                 for ( j = 0; j < ExSoundsN; j++ ){
1971                         if ( !Q_stricmp( pk3Sounds + i*65, ExSounds + j*65 ) ){
1972                                 *( pk3Sounds + i*65 ) = '\0';
1973                                 break;
1974                         }
1975                 }
1976                 if ( *( pk3Sounds + i*65 ) == '\0' ) continue;
1977                 for ( j = 0; j < rExSoundsN; j++ ){
1978                         if ( !Q_stricmp( pk3Sounds + i*65, rExSounds + j*65 ) ){
1979                                 *( pk3Sounds + i*65 ) = '\0';
1980                                 break;
1981                         }
1982                 }
1983         }
1984
1985         /* write shader */
1986         sprintf( temp, "%s/%s_strippedBYrepacker.shader", EnginePath, nameOFrepack );
1987         FILE *f;
1988         f = fopen( temp, "wb" );
1989         fwrite( allShaders, sizeof( char ), strlen( allShaders ), f );
1990         fclose( f );
1991         Sys_Printf( "Shaders saved to %s\n", temp );
1992
1993         /* make a pack */
1994         sprintf( packname, "%s/%s_repacked.pk3", EnginePath, nameOFrepack );
1995         remove( packname );
1996
1997         Sys_Printf( "\n--- ZipZip ---\n" );
1998
1999         Sys_Printf( "\n\tShader referenced textures....\n" );
2000
2001         for ( i = 0; i < pk3TexturesN; i++ ){
2002                 if ( png ){
2003                         sprintf( temp, "%s.png", pk3Textures + i*65 );
2004                         if ( vfsPackFile( temp, packname, compLevel ) ){
2005                                 Sys_Printf( "++%s\n", temp );
2006                                 continue;
2007                         }
2008                 }
2009                 sprintf( temp, "%s.tga", pk3Textures + i*65 );
2010                 if ( vfsPackFile( temp, packname, compLevel ) ){
2011                         Sys_Printf( "++%s\n", temp );
2012                         continue;
2013                 }
2014                 sprintf( temp, "%s.jpg", pk3Textures + i*65 );
2015                 if ( vfsPackFile( temp, packname, compLevel ) ){
2016                         Sys_Printf( "++%s\n", temp );
2017                         continue;
2018                 }
2019                 Sys_Printf( "  !FAIL! %s\n", pk3Textures + i*65 );
2020         }
2021
2022         Sys_Printf( "\n\tPure textures....\n" );
2023
2024         for ( i = 0; i < pk3ShadersN; i++ ){
2025                 if ( *( pk3Shaders + i*65 ) != '\0' ){
2026                         if ( png ){
2027                                 sprintf( temp, "%s.png", pk3Shaders + i*65 );
2028                                 if ( vfsPackFile( temp, packname, compLevel ) ){
2029                                         Sys_Printf( "++%s\n", temp );
2030                                         continue;
2031                                 }
2032                         }
2033                         sprintf( temp, "%s.tga", pk3Shaders + i*65 );
2034                         if ( vfsPackFile( temp, packname, compLevel ) ){
2035                                 Sys_Printf( "++%s\n", temp );
2036                                 continue;
2037                         }
2038                         sprintf( temp, "%s.jpg", pk3Shaders + i*65 );
2039                         if ( vfsPackFile( temp, packname, compLevel ) ){
2040                                 Sys_Printf( "++%s\n", temp );
2041                                 continue;
2042                         }
2043                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders + i*65 );
2044                 }
2045         }
2046
2047         Sys_Printf( "\n\tSounds....\n" );
2048
2049         for ( i = 0; i < pk3SoundsN; i++ ){
2050                 if ( *( pk3Sounds + i*65 ) != '\0' ){
2051                         if ( vfsPackFile( pk3Sounds + i*65, packname, compLevel ) ){
2052                                 Sys_Printf( "++%s\n", pk3Sounds + i*65 );
2053                                 continue;
2054                         }
2055                         Sys_Printf( "  !FAIL! %s\n", pk3Sounds + i*65 );
2056                 }
2057         }
2058
2059         Sys_Printf( "\n\tVideos....\n" );
2060
2061         for ( i = 0; i < pk3VideosN; i++ ){
2062                 if ( vfsPackFile( pk3Videos + i*65, packname, compLevel ) ){
2063                         Sys_Printf( "++%s\n", pk3Videos + i*65 );
2064                         continue;
2065                 }
2066                 Sys_Printf( "  !FAIL! %s\n", pk3Videos + i*65 );
2067         }
2068
2069         Sys_Printf( "\nSaved to %s\n", packname );
2070
2071         /* return to sender */
2072         return 0;
2073 }
2074
2075
2076
2077 /*
2078    main()
2079    q3map mojo...
2080  */
2081
2082 int main( int argc, char **argv ){
2083         int i, r;
2084         double start, end;
2085         extern qboolean werror;
2086
2087 #ifdef WIN32
2088         _setmaxstdio(2048);
2089 #endif
2090
2091         /* we want consistent 'randomness' */
2092         srand( 0 );
2093
2094         /* start timer */
2095         start = I_FloatTime();
2096
2097         /* this was changed to emit version number over the network */
2098         printf( Q3MAP_VERSION "\n" );
2099
2100         /* set exit call */
2101         atexit( ExitQ3Map );
2102
2103         /* read general options first */
2104         for ( i = 1; i < argc; i++ )
2105         {
2106                 /* -help */
2107                 if ( !strcmp( argv[ i ], "-h" ) || !strcmp( argv[ i ], "--help" )
2108                         || !strcmp( argv[ i ], "-help" ) ) {
2109                         HelpMain(argv[i+1]);
2110                         return 0;
2111                 }
2112
2113                 /* -connect */
2114                 if ( !strcmp( argv[ i ], "-connect" ) ) {
2115                         argv[ i ] = NULL;
2116                         i++;
2117                         Broadcast_Setup( argv[ i ] );
2118                         argv[ i ] = NULL;
2119                 }
2120
2121                 /* verbose */
2122                 else if ( !strcmp( argv[ i ], "-v" ) ) {
2123                         if ( !verbose ) {
2124                                 verbose = qtrue;
2125                                 argv[ i ] = NULL;
2126                         }
2127                 }
2128
2129                 /* force */
2130                 else if ( !strcmp( argv[ i ], "-force" ) ) {
2131                         force = qtrue;
2132                         argv[ i ] = NULL;
2133                 }
2134
2135                 /* make all warnings into errors */
2136                 else if ( !strcmp( argv[ i ], "-werror" ) ) {
2137                         werror = qtrue;
2138                         argv[ i ] = NULL;
2139                 }
2140
2141                 /* patch subdivisions */
2142                 else if ( !strcmp( argv[ i ], "-subdivisions" ) ) {
2143                         argv[ i ] = NULL;
2144                         i++;
2145                         patchSubdivisions = atoi( argv[ i ] );
2146                         argv[ i ] = NULL;
2147                         if ( patchSubdivisions <= 0 ) {
2148                                 patchSubdivisions = 1;
2149                         }
2150                 }
2151
2152                 /* threads */
2153                 else if ( !strcmp( argv[ i ], "-threads" ) ) {
2154                         argv[ i ] = NULL;
2155                         i++;
2156                         numthreads = atoi( argv[ i ] );
2157                         argv[ i ] = NULL;
2158                 }
2159
2160                 else if( !strcmp( argv[ i ], "-nocmdline" ) )
2161                 {
2162                         Sys_Printf( "noCmdLine\n" );
2163                         nocmdline = qtrue;
2164                         argv[ i ] = NULL;
2165                 }
2166
2167         }
2168
2169         /* init model library */
2170         PicoInit();
2171         PicoSetMallocFunc( safe_malloc );
2172         PicoSetFreeFunc( free );
2173         PicoSetPrintFunc( PicoPrintFunc );
2174         PicoSetLoadFileFunc( PicoLoadFileFunc );
2175         PicoSetFreeFileFunc( free );
2176
2177         /* set number of threads */
2178         ThreadSetDefault();
2179
2180         /* generate sinusoid jitter table */
2181         for ( i = 0; i < MAX_JITTERS; i++ )
2182         {
2183                 jitters[ i ] = sin( i * 139.54152147 );
2184                 //%     Sys_Printf( "Jitter %4d: %f\n", i, jitters[ i ] );
2185         }
2186
2187         /* we print out two versions, q3map's main version (since it evolves a bit out of GtkRadiant)
2188            and we put the GtkRadiant version to make it easy to track with what version of Radiant it was built with */
2189
2190         Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
2191         Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
2192         Sys_Printf( "NetRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
2193         Sys_Printf( "%s\n", Q3MAP_MOTD );
2194         Sys_Printf( "%s\n", argv[0] );
2195
2196         strcpy( q3map2path, argv[0] );//fuer autoPack func
2197
2198         /* ydnar: new path initialization */
2199         InitPaths( &argc, argv );
2200
2201         /* set game options */
2202         if ( !patchSubdivisions ) {
2203                 patchSubdivisions = game->patchSubdivisions;
2204         }
2205
2206         /* check if we have enough options left to attempt something */
2207         if ( argc < 2 ) {
2208                 Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );
2209         }
2210
2211         /* fixaas */
2212         if ( !strcmp( argv[ 1 ], "-fixaas" ) ) {
2213                 r = FixAASMain( argc - 1, argv + 1 );
2214         }
2215
2216         /* analyze */
2217         else if ( !strcmp( argv[ 1 ], "-analyze" ) ) {
2218                 r = AnalyzeBSPMain( argc - 1, argv + 1 );
2219         }
2220
2221         /* info */
2222         else if ( !strcmp( argv[ 1 ], "-info" ) ) {
2223                 r = BSPInfoMain( argc - 2, argv + 2 );
2224         }
2225
2226         /* vis */
2227         else if ( !strcmp( argv[ 1 ], "-vis" ) ) {
2228                 r = VisMain( argc - 1, argv + 1 );
2229         }
2230
2231         /* light */
2232         else if ( !strcmp( argv[ 1 ], "-light" ) ) {
2233                 r = LightMain( argc - 1, argv + 1 );
2234         }
2235
2236         /* vlight */
2237         else if ( !strcmp( argv[ 1 ], "-vlight" ) ) {
2238                 Sys_FPrintf( SYS_WRN, "WARNING: VLight is no longer supported, defaulting to -light -fast instead\n\n" );
2239                 argv[ 1 ] = "-fast";    /* eek a hack */
2240                 r = LightMain( argc, argv );
2241         }
2242
2243         /* QBall: export entities */
2244         else if ( !strcmp( argv[ 1 ], "-exportents" ) ) {
2245                 r = ExportEntitiesMain( argc - 1, argv + 1 );
2246         }
2247
2248         /* ydnar: lightmap export */
2249         else if ( !strcmp( argv[ 1 ], "-export" ) ) {
2250                 r = ExportLightmapsMain( argc - 1, argv + 1 );
2251         }
2252
2253         /* ydnar: lightmap import */
2254         else if ( !strcmp( argv[ 1 ], "-import" ) ) {
2255                 r = ImportLightmapsMain( argc - 1, argv + 1 );
2256         }
2257
2258         /* ydnar: bsp scaling */
2259         else if ( !strcmp( argv[ 1 ], "-scale" ) ) {
2260                 r = ScaleBSPMain( argc - 1, argv + 1 );
2261         }
2262
2263         /* bsp shifting */
2264         else if ( !strcmp( argv[ 1 ], "-shift" ) ) {
2265                 r = ShiftBSPMain( argc - 1, argv + 1 );
2266         }
2267
2268         /* autopacking */
2269         else if ( !strcmp( argv[ 1 ], "-pk3" ) ) {
2270                 r = pk3BSPMain( argc - 1, argv + 1 );
2271         }
2272
2273         /* repacker */
2274         else if ( !strcmp( argv[ 1 ], "-repack" ) ) {
2275                 r = repackBSPMain( argc - 1, argv + 1 );
2276         }
2277
2278         /* ydnar: bsp conversion */
2279         else if ( !strcmp( argv[ 1 ], "-convert" ) ) {
2280                 r = ConvertBSPMain( argc - 1, argv + 1 );
2281         }
2282
2283         /* div0: minimap */
2284         else if ( !strcmp( argv[ 1 ], "-minimap" ) ) {
2285                 r = MiniMapBSPMain( argc - 1, argv + 1 );
2286         }
2287
2288         /* ydnar: otherwise create a bsp */
2289         else{
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 }