q3map2: fix not displaying default args for some q3map2 stages
[xonotic/netradiant.git] / tools / quake3 / q3map2 / bsp_analyze.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 /* dependencies */
32 #include "q3map2.h"
33
34
35
36 /*
37    AnalyzeBSPMain() - ydnar
38    analyzes a Quake engine BSP file
39  */
40
41 typedef struct abspHeader_s
42 {
43         char ident[ 4 ];
44         int version;
45
46         bspLump_t lumps[ 1 ];       /* unknown size */
47 }
48 abspHeader_t;
49
50 typedef struct abspLumpTest_s
51 {
52         int radix, minCount;
53         char            *name;
54 }
55 abspLumpTest_t;
56
57 int AnalyzeBSPMain( int argc, char **argv ){
58         abspHeader_t            *header;
59         int size, i, version, offset, length, lumpInt, count;
60         char ident[ 5 ];
61         void                    *lump;
62         float lumpFloat;
63         char lumpString[ 1024 ], source[ 1024 ];
64         qboolean lumpSwap = qfalse;
65         abspLumpTest_t          *lumpTest;
66         static abspLumpTest_t lumpTests[] =
67         {
68                 { sizeof( bspPlane_t ),         6,      "IBSP LUMP_PLANES" },
69                 { sizeof( bspBrush_t ),         1,      "IBSP LUMP_BRUSHES" },
70                 { 8,                            6,      "IBSP LUMP_BRUSHSIDES" },
71                 { sizeof( bspBrushSide_t ),     6,      "RBSP LUMP_BRUSHSIDES" },
72                 { sizeof( bspModel_t ),         1,      "IBSP LUMP_MODELS" },
73                 { sizeof( bspNode_t ),          2,      "IBSP LUMP_NODES" },
74                 { sizeof( bspLeaf_t ),          1,      "IBSP LUMP_LEAFS" },
75                 { 104,                          3,      "IBSP LUMP_DRAWSURFS" },
76                 { 44,                           3,      "IBSP LUMP_DRAWVERTS" },
77                 { 4,                            6,      "IBSP LUMP_DRAWINDEXES" },
78                 { 128 * 128 * 3,                1,      "IBSP LUMP_LIGHTMAPS" },
79                 { 256 * 256 * 3,                1,      "IBSP LUMP_LIGHTMAPS (256 x 256)" },
80                 { 512 * 512 * 3,                1,      "IBSP LUMP_LIGHTMAPS (512 x 512)" },
81                 { 0, 0, NULL }
82         };
83
84
85         /* arg checking */
86         if ( argc < 2 ) {
87                 Sys_Printf( "Usage: q3map -analyze [-lumpswap] [-v] <mapname>\n" );
88                 return 0;
89         }
90
91         /* process arguments */
92         for ( i = 1; i < ( argc - 1 ); i++ )
93         {
94                 /* -format map|ase|... */
95                 if ( !strcmp( argv[ i ],  "-lumpswap" ) ) {
96                         Sys_Printf( "Swapped lump structs enabled\n" );
97                         lumpSwap = qtrue;
98                 }
99         }
100
101         /* clean up map name */
102         strcpy( source, ExpandArg( argv[ i ] ) );
103         Sys_Printf( "Loading %s\n", source );
104
105         /* load the file */
106         size = LoadFile( source, (void**) &header );
107         if ( size == 0 || header == NULL ) {
108                 Sys_Printf( "Unable to load %s.\n", source );
109                 return -1;
110         }
111
112         /* analyze ident/version */
113         memcpy( ident, header->ident, 4 );
114         ident[ 4 ] = '\0';
115         version = LittleLong( header->version );
116
117         Sys_Printf( "Identity:      %s\n", ident );
118         Sys_Printf( "Version:       %d\n", version );
119         Sys_Printf( "---------------------------------------\n" );
120
121         /* analyze each lump */
122         for ( i = 0; i < 100; i++ )
123         {
124                 /* call of duty swapped lump pairs */
125                 if ( lumpSwap ) {
126                         offset = LittleLong( header->lumps[ i ].length );
127                         length = LittleLong( header->lumps[ i ].offset );
128                 }
129
130                 /* standard lump pairs */
131                 else
132                 {
133                         offset = LittleLong( header->lumps[ i ].offset );
134                         length = LittleLong( header->lumps[ i ].length );
135                 }
136
137                 /* extract data */
138                 lump = (byte*) header + offset;
139                 lumpInt = LittleLong( (int) *( (int*) lump ) );
140                 lumpFloat = LittleFloat( (float) *( (float*) lump ) );
141                 memcpy( lumpString, (char*) lump, ( (size_t)length < sizeof( lumpString ) ? (size_t)length : sizeof( lumpString ) - 1 ) );
142                 lumpString[ sizeof( lumpString ) - 1 ] = '\0';
143
144                 /* print basic lump info */
145                 Sys_Printf( "Lump:          %d\n", i );
146                 Sys_Printf( "Offset:        %d bytes\n", offset );
147                 Sys_Printf( "Length:        %d bytes\n", length );
148
149                 /* only operate on valid lumps */
150                 if ( length > 0 ) {
151                         /* print data in 4 formats */
152                         Sys_Printf( "As hex:        %08X\n", lumpInt );
153                         Sys_Printf( "As int:        %d\n", lumpInt );
154                         Sys_Printf( "As float:      %f\n", lumpFloat );
155                         Sys_Printf( "As string:     %s\n", lumpString );
156
157                         /* guess lump type */
158                         if ( lumpString[ 0 ] == '{' && lumpString[ 2 ] == '"' ) {
159                                 Sys_Printf( "Type guess:    IBSP LUMP_ENTITIES\n" );
160                         }
161                         else if ( strstr( lumpString, "textures/" ) ) {
162                                 Sys_Printf( "Type guess:    IBSP LUMP_SHADERS\n" );
163                         }
164                         else
165                         {
166                                 /* guess based on size/count */
167                                 for ( lumpTest = lumpTests; lumpTest->radix > 0; lumpTest++ )
168                                 {
169                                         if ( ( length % lumpTest->radix ) != 0 ) {
170                                                 continue;
171                                         }
172                                         count = length / lumpTest->radix;
173                                         if ( count < lumpTest->minCount ) {
174                                                 continue;
175                                         }
176                                         Sys_Printf( "Type guess:    %s (%d x %d)\n", lumpTest->name, count, lumpTest->radix );
177                                 }
178                         }
179                 }
180
181                 Sys_Printf( "---------------------------------------\n" );
182
183                 /* end of file */
184                 if ( offset + length >= size ) {
185                         break;
186                 }
187         }
188
189         /* last stats */
190         Sys_Printf( "Lump count:    %d\n", i + 1 );
191         Sys_Printf( "File size:     %d bytes\n", size );
192
193         /* return to caller */
194         return 0;
195 }