Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "bsp-version.h"
00035
00036 #include <iostream>
00037
00038 #include "perf/perf.h"
00039
00040
00041 namespace quake {
00042
00043
00044 struct lump_meta_t {
00045 eLumpType type;
00046 const char * name;
00047 };
00048
00049
00050 #define LUMP_META( type ) { eLump_ ## type , #type },
00051
00052 static const lump_meta_t s_lumpMap[] = {
00053 LUMP_META(Entities)
00054 LUMP_META(Textures)
00055 LUMP_META(Planes)
00056 LUMP_META(Nodes)
00057 LUMP_META(Leafs)
00058 LUMP_META(Leaffaces)
00059 LUMP_META(Leafbrushes)
00060 LUMP_META(Models)
00061 LUMP_META(Brushes)
00062 LUMP_META(Brushsides)
00063 LUMP_META(Vertices)
00064 LUMP_META(Meshverts)
00065 LUMP_META(Effects)
00066 LUMP_META(Faces)
00067 LUMP_META(Lightmaps)
00068 LUMP_META(Lightvols)
00069 LUMP_META(Visdata)
00070
00071
00072 { eLump_Invalid, "Invalid" }
00073 };
00074
00075
00076 enum eEndian {
00077 eLittleEndian = 1,
00078 eBigEndian = 2,
00079
00080 eEndian_Invalid = 0
00081 };
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 void
00092 littleEndianToHostEndian
00093 (
00094 IO byte_t * raw
00095 )
00096 {
00097 ASSERT(raw, "null");
00098
00099
00100
00101 static eEndian endian = eEndian_Invalid;
00102 if (eEndian_Invalid == endian) {
00103 DPRINTF("determining local host byte order...");
00104 short test = 256;
00105 byte_t b[2];
00106 short * p = (short *) b;
00107 *p = test;
00108 if (b[0]) {
00109 DPRINTF("Big endian!");
00110 endian = eBigEndian;
00111 } else if (b[1]) {
00112 DPRINTF("Little endian!");
00113 endian = eLittleEndian;
00114 }
00115 }
00116 ASSERT(endian, "should have determined endian-ness");
00117
00118
00119 if (eLittleEndian == endian) {
00120 return;
00121 }
00122
00123
00124 byte_t save0 = raw[0];
00125 byte_t save1 = raw[1];
00126 raw[0] = raw[3];
00127 raw[1] = raw[2];
00128 raw[2] = save1;
00129 raw[3] = save0;
00130 }
00131
00132
00133
00134 static eBspVendor
00135 parseVendor
00136 (
00137 IO std::istream& in
00138 )
00139 {
00140 ASSERT_THROW(in.good(), "bad input BSP stream");
00141
00142 char buffer[5];
00143 in.read(buffer, 4);
00144 buffer[4] = 0;
00145
00146 if (!strcmp("IBSP", buffer)) {
00147 return eBspVendor_Id;
00148 } else if (!strcmp("VBSP", buffer)) {
00149 return eBspVendor_Valve;
00150 }
00151
00152
00153 ASSERT_THROW(false, "Unknown BSP vendor: '" << buffer << "'");
00154 return eBspVendor_Invalid;
00155 }
00156
00157
00158
00159 static eBspVersion
00160 parseVersion
00161 (
00162 IN eBspVendor vendor,
00163 IN int val
00164 )
00165 {
00166 switch (vendor) {
00167 case eBspVendor_Id:
00168 {
00169 switch (val) {
00170 case 0x2e:
00171 return eBspVersion_IdQuake3;
00172 default:
00173 ASSERT_THROW(false,
00174 "Unrecognized Id version: " << val);
00175 }
00176 }
00177 break;
00178
00179 case eBspVendor_Valve:
00180 {
00181 switch (val) {
00182 default:
00183 ASSERT_THROW(false,
00184 "Unrecognized Valve version: " << val);
00185 }
00186 }
00187 break;
00188
00189 default:
00190 ASSERT_THROW(false,
00191 "Unknown or invalid BSP vendor: " << vendor);
00192 }
00193
00194
00195 ASSERT(false, "should never get here");
00196 return eBspVersion_Invalid;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 void
00208 BspVersion::clear
00209 (
00210 void
00211 )
00212 throw()
00213 {
00214 m_vendor = eBspVendor_Invalid;
00215 m_version = eBspVersion_Invalid;
00216 }
00217
00218
00219
00220 bool
00221 BspVersion::isValid
00222 (
00223 void
00224 )
00225 const
00226 throw()
00227 {
00228 return (eBspVendor_Invalid != m_vendor &&
00229 eBspVersion_Invalid != m_version);
00230 }
00231
00232
00233
00234 void
00235 BspVersion::read
00236 (
00237 IO std::istream& in
00238 )
00239 {
00240 ASSERT_THROW(in.good(), "bad input BSP stream");
00241
00242 m_vendor = parseVendor(in);
00243 m_version = parseVersion(m_vendor, readInt(in));
00244 }
00245
00246
00247
00248 #define ADDLUMP( type ) lumps.push_back( eLump_ ## type );
00249
00250 bool
00251 BspVersion::getLumpTypes
00252 (
00253 OUT vec_lump_type_t& lumps
00254 )
00255 const
00256 {
00257 lumps.clear();
00258
00259 switch (m_version) {
00260 case eBspVersion_IdQuake3:
00261 ADDLUMP(Entities)
00262 ADDLUMP(Textures)
00263 ADDLUMP(Planes)
00264 ADDLUMP(Nodes)
00265 ADDLUMP(Leafs)
00266 ADDLUMP(Leaffaces)
00267 ADDLUMP(Leafbrushes)
00268 ADDLUMP(Models)
00269 ADDLUMP(Brushes)
00270 ADDLUMP(Brushsides)
00271 ADDLUMP(Vertices)
00272 ADDLUMP(Meshverts)
00273 ADDLUMP(Effects)
00274 ADDLUMP(Faces)
00275 ADDLUMP(Lightmaps)
00276 ADDLUMP(Lightvols)
00277 ADDLUMP(Visdata)
00278 return true;
00279
00280 default:
00281 break;
00282 }
00283
00284
00285 DPRINTF("Can't determine lumps from bsp vendor + version");
00286 return false;
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 const char *
00298 getLumpName
00299 (
00300 IN eLumpType type
00301 )
00302 {
00303 for (const lump_meta_t * p = s_lumpMap; eLump_Invalid != p->type; ++p)
00304 {
00305 if (p->type == type) {
00306 return p->name;
00307 }
00308 }
00309
00310 DPRINTF("Unknown lump type: %d", type);
00311 return "(unknown)";
00312 }
00313
00314
00315
00316 int
00317 readInt
00318 (
00319 IO std::istream& in
00320 )
00321 {
00322 ASSERT_THROW(in.good(), "bad BSP input stream");
00323
00324
00325 byte_t raw[4];
00326 in.read((char *) raw, 4);
00327
00328
00329 littleEndianToHostEndian(raw);
00330
00331
00332 int32_t * pi = (int32_t *) raw;
00333 return *pi;
00334 }
00335
00336
00337
00338 float
00339 readFloat
00340 (
00341 IO std::istream& in
00342 )
00343 {
00344 ASSERT_THROW(in.good(), "bad BSP input stream");
00345
00346
00347 byte_t raw[4];
00348 in.read((char *) raw, 4);
00349
00350
00351 littleEndianToHostEndian(raw);
00352
00353
00354 float * pf = (float *) raw;
00355 return *pf;
00356 }
00357
00358
00359
00360 point3d_t
00361 readPoint3d
00362 (
00363 IO std::istream& in
00364 )
00365 {
00366 point3d_t p;
00367 p.x = readFloat(in);
00368 p.z = readFloat(in);
00369 p.y = readFloat(in);
00370
00371 return p;
00372 }
00373
00374
00375
00376 };
00377