#include #include #include "bsploader.h" #include "dialogs/dialogs-gtk.h" #include "cmdlib.h" int numnodes; int numplanes; int numleafs; int numleafsurfaces; int numVisBytes; int numDrawVerts; int numDrawSurfaces; int numbrushes; int numbrushsides; int numleafbrushes; byte *visBytes = NULL; dnode_t *dnodes = NULL; dplane_t *dplanes = NULL; dleaf_t *dleafs = NULL; qdrawVert_t *drawVerts = NULL; dsurface_t *drawSurfaces = NULL; int *dleafsurfaces = NULL; dbrush_t *dbrushes = NULL; dbrushside_t *dbrushsides = NULL; int *dleafbrushes = NULL; const int BSP_IDENT = (('P' << 24) + ('S' << 16) + ('B' << 8) + 'I'); const int Q3_BSP_VERSION = 46; const int WOLF_BSP_VERSION = 47; /* ================ FileLength ================ */ int FileLength(FILE *f) { int pos; int end; pos = ftell(f); fseek(f, 0, SEEK_END); end = ftell(f); fseek(f, pos, SEEK_SET); return end; } /* ============== LoadFile ============== */ bool LoadFile(const char *filename, byte **bufferptr) { FILE *f; int length; byte *buffer; f = fopen(filename, "rb"); if (!f) { return false; } length = FileLength(f); buffer = new byte[length + 1]; buffer[length] = 0; assert(fread(buffer, 1, length, f)); fclose(f); *bufferptr = buffer; return true; } int LittleLong(int l) { if (GDEF_ARCH_ENDIAN_BIG) { std::reverse(reinterpret_cast( &l ), reinterpret_cast( &l ) + sizeof(int)); } return l; } float LittleFloat(float l) { if (GDEF_ARCH_ENDIAN_BIG) { std::reverse(reinterpret_cast( &l ), reinterpret_cast( &l ) + sizeof(float)); } return l; } /* ============= SwapBlock If all values are 32 bits, this can be used to swap everything ============= */ void SwapBlock(int *block, int sizeOfBlock) { int i; sizeOfBlock >>= 2; for (i = 0; i < sizeOfBlock; i++) { block[i] = LittleLong(block[i]); } } /* ============= SwapBSPFile Byte swaps all data in a bsp file. ============= */ void SwapBSPFile(void) { int i; // models // SwapBlock( (int *)dmodels, nummodels * sizeof( dmodels[0] ) ); // shaders (don't swap the name) // for ( i = 0 ; i < numShaders ; i++ ) { // dshaders[i].contentFlags = LittleLong( dshaders[i].contentFlags ); // dshaders[i].surfaceFlags = LittleLong( dshaders[i].surfaceFlags ); // } // planes SwapBlock((int *) dplanes, numplanes * sizeof(dplanes[0])); // nodes SwapBlock((int *) dnodes, numnodes * sizeof(dnodes[0])); // leafs SwapBlock((int *) dleafs, numleafs * sizeof(dleafs[0])); // leaffaces SwapBlock((int *) dleafsurfaces, numleafsurfaces * sizeof(dleafsurfaces[0])); // leafbrushes SwapBlock((int *) dleafbrushes, numleafbrushes * sizeof(dleafbrushes[0])); // brushes SwapBlock((int *) dbrushes, numbrushes * sizeof(dbrushes[0])); // brushsides SwapBlock((int *) dbrushsides, numbrushsides * sizeof(dbrushsides[0])); // vis ((int *) &visBytes)[0] = LittleLong(((int *) &visBytes)[0]); ((int *) &visBytes)[1] = LittleLong(((int *) &visBytes)[1]); // drawverts (don't swap colors ) for (i = 0; i < numDrawVerts; i++) { drawVerts[i].lightmap[0] = LittleFloat(drawVerts[i].lightmap[0]); drawVerts[i].lightmap[1] = LittleFloat(drawVerts[i].lightmap[1]); drawVerts[i].st[0] = LittleFloat(drawVerts[i].st[0]); drawVerts[i].st[1] = LittleFloat(drawVerts[i].st[1]); drawVerts[i].xyz[0] = LittleFloat(drawVerts[i].xyz[0]); drawVerts[i].xyz[1] = LittleFloat(drawVerts[i].xyz[1]); drawVerts[i].xyz[2] = LittleFloat(drawVerts[i].xyz[2]); drawVerts[i].normal[0] = LittleFloat(drawVerts[i].normal[0]); drawVerts[i].normal[1] = LittleFloat(drawVerts[i].normal[1]); drawVerts[i].normal[2] = LittleFloat(drawVerts[i].normal[2]); } // drawindexes // SwapBlock( (int *)drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) ); // drawsurfs SwapBlock((int *) drawSurfaces, numDrawSurfaces * sizeof(drawSurfaces[0])); // fogs // for ( i = 0 ; i < numFogs ; i++ ) { // dfogs[i].brushNum = LittleLong( dfogs[i].brushNum ); // dfogs[i].visibleSide = LittleLong( dfogs[i].visibleSide ); // } } /* ============= CopyLump ============= */ int CopyLump(dheader_t *header, int lump, void **dest, int size) { int length, ofs; length = header->lumps[lump].filelen; ofs = header->lumps[lump].fileofs; if (length == 0) { return 0; } *dest = new byte[length]; memcpy(*dest, (byte *) header + ofs, length); return length / size; } /* ============= LoadBSPFile ============= */ bool LoadBSPFile(const char *filename) { dheader_t *header; // load the file header if (!LoadFile(filename, (byte **) &header)) { return false; } // swap the header SwapBlock((int *) header, sizeof(*header)); if (header->ident != BSP_IDENT) { DoMessageBox("Cant find a valid IBSP file", "Error", eMB_OK); return false; } if ((header->version != Q3_BSP_VERSION) && (header->version != WOLF_BSP_VERSION)) { DoMessageBox("File is incorrect version", "Error", eMB_OK); return false; } numbrushsides = CopyLump(header, LUMP_BRUSHES, (void **) &dbrushsides, sizeof(dbrushside_t)); numbrushes = CopyLump(header, LUMP_BRUSHES, (void **) &dbrushes, sizeof(dbrush_t)); numplanes = CopyLump(header, LUMP_PLANES, (void **) &dplanes, sizeof(dplane_t)); numleafs = CopyLump(header, LUMP_LEAFS, (void **) &dleafs, sizeof(dleaf_t)); numnodes = CopyLump(header, LUMP_NODES, (void **) &dnodes, sizeof(dnode_t)); numDrawVerts = CopyLump(header, LUMP_DRAWVERTS, (void **) &drawVerts, sizeof(qdrawVert_t)); numDrawSurfaces = CopyLump(header, LUMP_SURFACES, (void **) &drawSurfaces, sizeof(dsurface_t)); numleafsurfaces = CopyLump(header, LUMP_LEAFSURFACES, (void **) &dleafsurfaces, sizeof(int)); numVisBytes = CopyLump(header, LUMP_VISIBILITY, (void **) &visBytes, 1); numleafbrushes = CopyLump(header, LUMP_LEAFBRUSHES, (void **) &dleafbrushes, sizeof(int)); delete header; // everything has been copied out // swap everything SwapBSPFile(); return true; } void FreeBSPData() { if (visBytes) { delete visBytes; } if (dnodes) { delete dnodes; } if (dplanes) { delete dplanes; } if (dleafs) { delete dleafs; } if (drawVerts) { delete drawVerts; } if (drawSurfaces) { delete drawSurfaces; } if (dleafsurfaces) { delete dleafsurfaces; } if (dleafbrushes) { delete dleafbrushes; } if (dbrushes) { delete dbrushes; } if (dbrushsides) { delete dbrushsides; } }