]> icculus.org git repositories - divverent/netradiant.git/blob - tools/quake3/q3map2/main.c
support non-uniform -scale
[divverent/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
39
40
41 /*
42 Random()
43 returns a pseudorandom number between 0 and 1
44 */
45
46 vec_t Random( void )
47 {
48         return (vec_t) rand() / RAND_MAX;
49 }
50
51
52
53 /*
54 ExitQ3Map()
55 cleanup routine
56 */
57
58 static void ExitQ3Map( void )
59 {
60         BSPFilesCleanup();
61         if( mapDrawSurfs != NULL )
62                 free( mapDrawSurfs );
63 }
64
65
66
67 /*
68 MD4BlockChecksum()
69 calculates an md4 checksum for a block of data
70 */
71
72 static int MD4BlockChecksum( void *buffer, int length )
73 {
74         return Com_BlockChecksum(buffer, length);
75 }
76
77
78
79 /*
80 FixAAS()
81 resets an aas checksum to match the given BSP
82 */
83
84 int FixAAS( int argc, char **argv )
85 {
86         int                     length, checksum;
87         void            *buffer;
88         FILE            *file;
89         char            aas[ 1024 ], **ext;
90         char            *exts[] =
91                                 {
92                                         ".aas",
93                                         "_b0.aas",
94                                         "_b1.aas",
95                                         NULL
96                                 };
97         
98         
99         /* arg checking */
100         if( argc < 2 )
101         {
102                 Sys_Printf( "Usage: q3map -fixaas [-v] <mapname>\n" );
103                 return 0;
104         }
105         
106         /* do some path mangling */
107         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
108         StripExtension( source );
109         DefaultExtension( source, ".bsp" );
110         
111         /* note it */
112         Sys_Printf( "--- FixAAS ---\n" );
113         
114         /* load the bsp */
115         Sys_Printf( "Loading %s\n", source );
116         length = LoadFile( source, &buffer );
117         
118         /* create bsp checksum */
119         Sys_Printf( "Creating checksum...\n" );
120         checksum = LittleLong( MD4BlockChecksum( buffer, length ) );
121         
122         /* write checksum to aas */
123         ext = exts;
124         while( *ext )
125         {
126                 /* mangle name */
127                 strcpy( aas, source );
128                 StripExtension( aas );
129                 strcat( aas, *ext );
130                 Sys_Printf( "Trying %s\n", aas );
131                 ext++;
132                 
133                 /* fix it */
134                 file = fopen( aas, "r+b" );
135                 if( !file )
136                         continue;
137                 if( fwrite( &checksum, 4, 1, file ) != 1 )
138                         Error( "Error writing checksum to %s", aas );
139                 fclose( file );
140         }
141         
142         /* return to sender */
143         return 0;
144 }
145
146
147
148 /*
149 AnalyzeBSP() - ydnar
150 analyzes a Quake engine BSP file
151 */
152
153 typedef struct abspHeader_s
154 {
155         char                    ident[ 4 ];
156         int                             version;
157         
158         bspLump_t               lumps[ 1 ];     /* unknown size */
159 }
160 abspHeader_t;
161
162 typedef struct abspLumpTest_s
163 {
164         int                             radix, minCount;
165         char                    *name;
166 }
167 abspLumpTest_t;
168
169 int AnalyzeBSP( int argc, char **argv )
170 {
171         abspHeader_t                    *header;
172         int                                             size, i, version, offset, length, lumpInt, count;
173         char                                    ident[ 5 ];
174         void                                    *lump;
175         float                                   lumpFloat;
176         char                                    lumpString[ 1024 ], source[ 1024 ];
177         qboolean                                lumpSwap = qfalse;
178         abspLumpTest_t                  *lumpTest;
179         static abspLumpTest_t   lumpTests[] =
180                                                         {
181                                                                 { sizeof( bspPlane_t ),                 6,              "IBSP LUMP_PLANES" },
182                                                                 { sizeof( bspBrush_t ),                 1,              "IBSP LUMP_BRUSHES" },
183                                                                 { 8,                                                    6,              "IBSP LUMP_BRUSHSIDES" },
184                                                                 { sizeof( bspBrushSide_t ),             6,              "RBSP LUMP_BRUSHSIDES" },
185                                                                 { sizeof( bspModel_t ),                 1,              "IBSP LUMP_MODELS" },
186                                                                 { sizeof( bspNode_t ),                  2,              "IBSP LUMP_NODES" },
187                                                                 { sizeof( bspLeaf_t ),                  1,              "IBSP LUMP_LEAFS" },
188                                                                 { 104,                                                  3,              "IBSP LUMP_DRAWSURFS" },
189                                                                 { 44,                                                   3,              "IBSP LUMP_DRAWVERTS" },
190                                                                 { 4,                                                    6,              "IBSP LUMP_DRAWINDEXES" },
191                                                                 { 128 * 128 * 3,                                1,              "IBSP LUMP_LIGHTMAPS" },
192                                                                 { 256 * 256 * 3,                                1,              "IBSP LUMP_LIGHTMAPS (256 x 256)" },
193                                                                 { 512 * 512 * 3,                                1,              "IBSP LUMP_LIGHTMAPS (512 x 512)" },
194                                                                 { 0, 0, NULL }
195                                                         };
196         
197         
198         /* arg checking */
199         if( argc < 1 )
200         {
201                 Sys_Printf( "Usage: q3map -analyze [-lumpswap] [-v] <mapname>\n" );
202                 return 0;
203         }
204         
205         /* process arguments */
206         for( i = 1; i < (argc - 1); i++ )
207         {
208                 /* -format map|ase|... */
209                 if( !strcmp( argv[ i ],  "-lumpswap" ) )
210                 {
211                         Sys_Printf( "Swapped lump structs enabled\n" );
212                         lumpSwap = qtrue;
213                 }
214         }
215         
216         /* clean up map name */
217         strcpy( source, ExpandArg( argv[ i ] ) );
218         Sys_Printf( "Loading %s\n", source );
219         
220         /* load the file */
221         size = LoadFile( source, (void**) &header );
222         if( size == 0 || header == NULL )
223         {
224                 Sys_Printf( "Unable to load %s.\n", source );
225                 return -1;
226         }
227         
228         /* analyze ident/version */
229         memcpy( ident, header->ident, 4 );
230         ident[ 4 ] = '\0';
231         version = LittleLong( header->version );
232         
233         Sys_Printf( "Identity:      %s\n", ident );
234         Sys_Printf( "Version:       %d\n", version );
235         Sys_Printf( "---------------------------------------\n" );
236         
237         /* analyze each lump */
238         for( i = 0; i < 100; i++ )
239         {
240                 /* call of duty swapped lump pairs */
241                 if( lumpSwap )
242                 {
243                         offset = LittleLong( header->lumps[ i ].length );
244                         length = LittleLong( header->lumps[ i ].offset );
245                 }
246                 
247                 /* standard lump pairs */
248                 else
249                 {
250                         offset = LittleLong( header->lumps[ i ].offset );
251                         length = LittleLong( header->lumps[ i ].length );
252                 }
253                 
254                 /* extract data */
255                 lump = (byte*) header + offset;
256                 lumpInt = LittleLong( (int) *((int*) lump) );
257                 lumpFloat = LittleFloat( (float) *((float*) lump) );
258                 memcpy( lumpString, (char*) lump, (length < 1024 ? length : 1024) );
259                 lumpString[ 1024 ] = '\0';
260                 
261                 /* print basic lump info */
262                 Sys_Printf( "Lump:          %d\n", i );
263                 Sys_Printf( "Offset:        %d bytes\n", offset );
264                 Sys_Printf( "Length:        %d bytes\n", length );
265                 
266                 /* only operate on valid lumps */
267                 if( length > 0 )
268                 {
269                         /* print data in 4 formats */
270                         Sys_Printf( "As hex:        %08X\n", lumpInt );
271                         Sys_Printf( "As int:        %d\n", lumpInt );
272                         Sys_Printf( "As float:      %f\n", lumpFloat );
273                         Sys_Printf( "As string:     %s\n", lumpString );
274                         
275                         /* guess lump type */
276                         if( lumpString[ 0 ] == '{' && lumpString[ 2 ] == '"' )
277                                 Sys_Printf( "Type guess:    IBSP LUMP_ENTITIES\n" );
278                         else if( strstr( lumpString, "textures/" ) )
279                                 Sys_Printf( "Type guess:    IBSP LUMP_SHADERS\n" );
280                         else
281                         {
282                                 /* guess based on size/count */
283                                 for( lumpTest = lumpTests; lumpTest->radix > 0; lumpTest++ )
284                                 {
285                                         if( (length % lumpTest->radix) != 0 )
286                                                 continue;
287                                         count = length / lumpTest->radix;
288                                         if( count < lumpTest->minCount )
289                                                 continue;
290                                         Sys_Printf( "Type guess:    %s (%d x %d)\n", lumpTest->name, count, lumpTest->radix );
291                                 }
292                         }
293                 }
294                 
295                 Sys_Printf( "---------------------------------------\n" );
296                 
297                 /* end of file */
298                 if( offset + length >= size )
299                         break;
300         }
301         
302         /* last stats */
303         Sys_Printf( "Lump count:    %d\n", i + 1 );
304         Sys_Printf( "File size:     %d bytes\n", size );
305         
306         /* return to caller */
307         return 0;
308 }
309
310
311
312 /*
313 BSPInfo()
314 emits statistics about the bsp file
315 */
316
317 int BSPInfo( int count, char **fileNames )
318 {
319         int                     i;
320         char            source[ 1024 ], ext[ 64 ];
321         int                     size;
322         FILE            *f;
323         
324         
325         /* dummy check */
326         if( count < 1 )
327         {
328                 Sys_Printf( "No files to dump info for.\n");
329                 return -1;
330         }
331         
332         /* enable info mode */
333         infoMode = qtrue;
334         
335         /* walk file list */
336         for( i = 0; i < count; i++ )
337         {
338                 Sys_Printf( "---------------------------------\n" );
339                 
340                 /* mangle filename and get size */
341                 strcpy( source, fileNames[ i ] );
342                 ExtractFileExtension( source, ext );
343                 if( !Q_stricmp( ext, "map" ) )
344                         StripExtension( source );
345                 DefaultExtension( source, ".bsp" );
346                 f = fopen( source, "rb" );
347                 if( f )
348                 {
349                         size = Q_filelength (f);
350                         fclose( f );
351                 }
352                 else
353                         size = 0;
354                 
355                 /* load the bsp file and print lump sizes */
356                 Sys_Printf( "%s\n", source );
357                 LoadBSPFile( source );          
358                 PrintBSPFileSizes();
359                 
360                 /* print sizes */
361                 Sys_Printf( "\n" );
362                 Sys_Printf( "          total         %9d\n", size );
363                 Sys_Printf( "                        %9d KB\n", size / 1024 );
364                 Sys_Printf( "                        %9d MB\n", size / (1024 * 1024) );
365                 
366                 Sys_Printf( "---------------------------------\n" );
367         }
368         
369         /* return count */
370         return i;
371 }
372
373
374
375 /*
376 ScaleBSPMain()
377 amaze and confuse your enemies with wierd scaled maps!
378 */
379
380 int ScaleBSPMain( int argc, char **argv )
381 {
382         int                     i;
383         float           f, a;
384         vec3_t scale;
385         vec3_t          vec;
386         char            str[ 1024 ];
387         int uniform, axis;
388         
389         
390         /* arg checking */
391         if( argc < 2 )
392         {
393                 Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
394                 return 0;
395         }
396         
397         /* get scale */
398         scale[2] = scale[1] = scale[0] = atof( argv[ argc - 2 ] );
399         if(argc >= 3)
400                 scale[1] = scale[0] = atof( argv[ argc - 3 ] );
401         if(argc >= 4)
402                 scale[0] = atof( argv[ argc - 4 ] );
403         
404         uniform = ((scale[0] == scale[1]) && (scale[1] == scale[2]));
405
406         if( scale[0] == 0.0f || scale[1] == 0.0f || scale[2] == 0.0f )
407         {
408                 Sys_Printf( "Usage: q3map -scale <value> <mapname>\n" );
409                 Sys_Printf( "Non-zero scale value required.\n" );
410                 return 0;
411         }
412         
413         /* do some path mangling */
414         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
415         StripExtension( source );
416         DefaultExtension( source, ".bsp" );
417         
418         /* load the bsp */
419         Sys_Printf( "Loading %s\n", source );
420         LoadBSPFile( source );
421         ParseEntities();
422         
423         /* note it */
424         Sys_Printf( "--- ScaleBSP ---\n" );
425         Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
426         
427         /* scale entity keys */
428         for( i = 0; i < numBSPEntities && i < numEntities; i++ )
429         {
430                 /* scale origin */
431                 GetVectorForKey( &entities[ i ], "origin", vec );
432                 if( (vec[ 0 ] || vec[ 1 ] || vec[ 2 ]) )
433                 {
434                         vec[0] *= scale[0];
435                         vec[1] *= scale[1];
436                         vec[2] *= scale[2];
437                         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
438                         SetKeyValue( &entities[ i ], "origin", str );
439                 }
440
441                 a = FloatForKey( &entities[ i ], "angle" );
442                 if(a == -1 || a == -2) // z scale
443                         axis = 2;
444                 else if(fabs(sin(DEG2RAD(a))) < 0.707)
445                         axis = 0;
446                 else
447                         axis = 1;
448                 
449                 /* scale door lip */
450                 f = FloatForKey( &entities[ i ], "lip" );
451                 if( f )
452                 {
453                         f *= scale[axis];
454                         sprintf( str, "%f", f );
455                         SetKeyValue( &entities[ i ], "lip", str );
456                 }
457                 
458                 /* scale plat height */
459                 f = FloatForKey( &entities[ i ], "height" );
460                 if( f )
461                 {
462                         f *= scale[2];
463                         sprintf( str, "%f", f );
464                         SetKeyValue( &entities[ i ], "height", str );
465                 }
466
467                 // TODO maybe allow a definition file for entities to specify which values are scaled how?
468         }
469         
470         /* scale models */
471         for( i = 0; i < numBSPModels; i++ )
472         {
473                 bspModels[ i ].mins[0] *= scale[0];
474                 bspModels[ i ].mins[1] *= scale[1];
475                 bspModels[ i ].mins[2] *= scale[2];
476                 bspModels[ i ].maxs[0] *= scale[0];
477                 bspModels[ i ].maxs[1] *= scale[1];
478                 bspModels[ i ].maxs[2] *= scale[2];
479         }
480         
481         /* scale nodes */
482         for( i = 0; i < numBSPNodes; i++ )
483         {
484                 bspNodes[ i ].mins[0] *= scale[0];
485                 bspNodes[ i ].mins[1] *= scale[1];
486                 bspNodes[ i ].mins[2] *= scale[2];
487                 bspNodes[ i ].maxs[0] *= scale[0];
488                 bspNodes[ i ].maxs[1] *= scale[1];
489                 bspNodes[ i ].maxs[2] *= scale[2];
490         }
491         
492         /* scale leafs */
493         for( i = 0; i < numBSPLeafs; i++ )
494         {
495                 bspLeafs[ i ].mins[0] *= scale[0];
496                 bspLeafs[ i ].mins[1] *= scale[1];
497                 bspLeafs[ i ].mins[2] *= scale[2];
498                 bspLeafs[ i ].maxs[0] *= scale[0];
499                 bspLeafs[ i ].maxs[1] *= scale[1];
500                 bspLeafs[ i ].maxs[2] *= scale[2];
501         }
502         
503         /* scale drawverts */
504         for( i = 0; i < numBSPDrawVerts; i++ )
505         {
506                 bspDrawVerts[i].xyz[0] *= scale[0];
507                 bspDrawVerts[i].xyz[1] *= scale[1];
508                 bspDrawVerts[i].xyz[2] *= scale[2];
509                 bspDrawVerts[i].normal[0] /= scale[0];
510                 bspDrawVerts[i].normal[1] /= scale[1];
511                 bspDrawVerts[i].normal[2] /= scale[2];
512                 VectorNormalize(bspDrawVerts[i].normal, bspDrawVerts[i].normal);
513         }
514         
515         /* scale planes */
516         if(uniform)
517         {
518                 for( i = 0; i < numBSPPlanes; i++ )
519                 {
520                         bspPlanes[ i ].dist *= scale[0];
521                 }
522         }
523         else
524         {
525                 for( i = 0; i < numBSPPlanes; i++ )
526                 {
527                         bspPlanes[ i ].normal[0] /= scale[0];
528                         bspPlanes[ i ].normal[1] /= scale[1];
529                         bspPlanes[ i ].normal[2] /= scale[2];
530                         f = 1/VectorLength(bspPlanes[i].normal);
531                         VectorScale(bspPlanes[i].normal, f, bspPlanes[i].normal);
532                         bspPlanes[ i ].dist *= f;
533                 }
534         }
535         
536         /* scale gridsize */
537         GetVectorForKey( &entities[ 0 ], "gridsize", vec );
538         if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) == 0.0f )
539                 VectorCopy( gridSize, vec );
540         vec[0] *= scale[0];
541         vec[1] *= scale[1];
542         vec[2] *= scale[2];
543         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
544         SetKeyValue( &entities[ 0 ], "gridsize", str );
545
546         /* inject command line parameters */
547         InjectCommandLine(argv, 0, argc - 1);
548         
549         /* write the bsp */
550         UnparseEntities();
551         StripExtension( source );
552         DefaultExtension( source, "_s.bsp" );
553         Sys_Printf( "Writing %s\n", source );
554         WriteBSPFile( source );
555         
556         /* return to sender */
557         return 0;
558 }
559
560
561
562 /*
563 ConvertBSPMain()
564 main argument processing function for bsp conversion
565 */
566
567 int ConvertBSPMain( int argc, char **argv )
568 {
569         int             i;
570         int             (*convertFunc)( char * );
571         game_t  *convertGame;
572         
573         
574         /* set default */
575         convertFunc = ConvertBSPToASE;
576         convertGame = NULL;
577         
578         /* arg checking */
579         if( argc < 1 )
580         {
581                 Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
582                 return 0;
583         }
584         
585         /* process arguments */
586         for( i = 1; i < (argc - 1); i++ )
587         {
588                 /* -format map|ase|... */
589                 if( !strcmp( argv[ i ],  "-format" ) )
590                 {
591                         i++;
592                         if( !Q_stricmp( argv[ i ], "ase" ) )
593                                 convertFunc = ConvertBSPToASE;
594                         else if( !Q_stricmp( argv[ i ], "map" ) )
595                                 convertFunc = ConvertBSPToMap;
596                         else
597                         {
598                                 convertGame = GetGame( argv[ i ] );
599                                 if( convertGame == NULL )
600                                         Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
601                         }
602                 }
603                 else if( !strcmp( argv[ i ],  "-ne" ) )
604                 {
605                         normalEpsilon = atof( argv[ i + 1 ] );
606                         i++;
607                         Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
608                 }
609                 else if( !strcmp( argv[ i ],  "-de" ) )
610                 {
611                         distanceEpsilon = atof( argv[ i + 1 ] );
612                         i++;
613                         Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
614                 }
615                 else if( !strcmp( argv[ i ],  "-shadersasbitmap" ) )
616                         shadersAsBitmap = qtrue;
617         }
618         
619         /* clean up map name */
620         strcpy( source, ExpandArg( argv[ i ] ) );
621         StripExtension( source );
622         DefaultExtension( source, ".bsp" );
623         
624         LoadShaderInfo();
625         
626         Sys_Printf( "Loading %s\n", source );
627         
628         /* ydnar: load surface file */
629         //%     LoadSurfaceExtraFile( source );
630         
631         LoadBSPFile( source );
632         
633         /* parse bsp entities */
634         ParseEntities();
635         
636         /* bsp format convert? */
637         if( convertGame != NULL )
638         {
639                 /* set global game */
640                 game = convertGame;
641                 
642                 /* write bsp */
643                 StripExtension( source );
644                 DefaultExtension( source, "_c.bsp" );
645                 Sys_Printf( "Writing %s\n", source );
646                 WriteBSPFile( source );
647                 
648                 /* return to sender */
649                 return 0;
650         }
651         
652         /* normal convert */
653         return convertFunc( source );
654 }
655
656
657
658 /*
659 main()
660 q3map mojo...
661 */
662
663 int main( int argc, char **argv )
664 {
665         int             i, r;
666         double  start, end;
667         
668         
669         /* we want consistent 'randomness' */
670         srand( 0 );
671         
672         /* start timer */
673         start = I_FloatTime();
674
675         /* this was changed to emit version number over the network */
676         printf( Q3MAP_VERSION "\n" );
677         
678         /* set exit call */
679         atexit( ExitQ3Map );
680         
681         /* read general options first */
682         for( i = 1; i < argc; i++ )
683         {
684                 /* -connect */
685                 if( !strcmp( argv[ i ], "-connect" ) )
686                 {
687                         argv[ i ] = NULL;
688                         i++;
689                         Broadcast_Setup( argv[ i ] );
690                         argv[ i ] = NULL;
691                 }
692                 
693                 /* verbose */
694                 else if( !strcmp( argv[ i ], "-v" ) )
695                 {
696                         verbose = qtrue;
697                         argv[ i ] = NULL;
698                 }
699                 
700                 /* force */
701                 else if( !strcmp( argv[ i ], "-force" ) )
702                 {
703                         force = qtrue;
704                         argv[ i ] = NULL;
705                 }
706                 
707                 /* patch subdivisions */
708                 else if( !strcmp( argv[ i ], "-subdivisions" ) )
709                 {
710                         argv[ i ] = NULL;
711                         i++;
712                         patchSubdivisions = atoi( argv[ i ] );
713                         argv[ i ] = NULL;
714                         if( patchSubdivisions <= 0 )
715                                 patchSubdivisions = 1;
716                 }
717                 
718                 /* threads */
719                 else if( !strcmp( argv[ i ], "-threads" ) )
720                 {
721                         argv[ i ] = NULL;
722                         i++;
723                         numthreads = atoi( argv[ i ] );
724                         argv[ i ] = NULL;
725                 }
726         }
727         
728         /* init model library */
729         PicoInit();
730         PicoSetMallocFunc( safe_malloc );
731         PicoSetFreeFunc( free );
732         PicoSetPrintFunc( PicoPrintFunc );
733         PicoSetLoadFileFunc( PicoLoadFileFunc );
734         PicoSetFreeFileFunc( free );
735         
736         /* set number of threads */
737         ThreadSetDefault();
738         
739         /* generate sinusoid jitter table */
740         for( i = 0; i < MAX_JITTERS; i++ )
741         {
742                 jitters[ i ] = sin( i * 139.54152147 );
743                 //%     Sys_Printf( "Jitter %4d: %f\n", i, jitters[ i ] );
744         }
745         
746         /* we print out two versions, q3map's main version (since it evolves a bit out of GtkRadiant)
747            and we put the GtkRadiant version to make it easy to track with what version of Radiant it was built with */
748         
749         Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
750         Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
751         Sys_Printf( "NetRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
752         Sys_Printf( "%s\n", Q3MAP_MOTD );
753         
754         /* ydnar: new path initialization */
755         InitPaths( &argc, argv );
756         
757         /* check if we have enough options left to attempt something */
758         if( argc < 2 )
759                 Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );
760         
761         /* fixaas */
762         if( !strcmp( argv[ 1 ], "-fixaas" ) )
763                 r = FixAAS( argc - 1, argv + 1 );
764         
765         /* analyze */
766         else if( !strcmp( argv[ 1 ], "-analyze" ) )
767                 r = AnalyzeBSP( argc - 1, argv + 1 );
768         
769         /* info */
770         else if( !strcmp( argv[ 1 ], "-info" ) )
771                 r = BSPInfo( argc - 2, argv + 2 );
772         
773         /* vis */
774         else if( !strcmp( argv[ 1 ], "-vis" ) )
775                 r = VisMain( argc - 1, argv + 1 );
776         
777         /* light */
778         else if( !strcmp( argv[ 1 ], "-light" ) )
779                 r = LightMain( argc - 1, argv + 1 );
780         
781         /* vlight */
782         else if( !strcmp( argv[ 1 ], "-vlight" ) )
783         {
784                 Sys_Printf( "WARNING: VLight is no longer supported, defaulting to -light -fast instead\n\n" );
785                 argv[ 1 ] = "-fast";    /* eek a hack */
786                 r = LightMain( argc, argv );
787         }
788         
789         /* ydnar: lightmap export */
790         else if( !strcmp( argv[ 1 ], "-export" ) )
791                 r = ExportLightmapsMain( argc - 1, argv + 1 );
792         
793         /* ydnar: lightmap import */
794         else if( !strcmp( argv[ 1 ], "-import" ) )
795                 r = ImportLightmapsMain( argc - 1, argv + 1 );
796         
797         /* ydnar: bsp scaling */
798         else if( !strcmp( argv[ 1 ], "-scale" ) )
799                 r = ScaleBSPMain( argc - 1, argv + 1 );
800         
801         /* ydnar: bsp conversion */
802         else if( !strcmp( argv[ 1 ], "-convert" ) )
803                 r = ConvertBSPMain( argc - 1, argv + 1 );
804         
805         /* ydnar: otherwise create a bsp */
806         else
807                 r = BSPMain( argc, argv );
808         
809         /* emit time */
810         end = I_FloatTime();
811         Sys_Printf( "%9.0f seconds elapsed\n", end - start );
812         
813         /* shut down connection */
814         Broadcast_Shutdown();
815         
816         /* return any error code */
817         return r;
818 }