/* Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1997 Greg Lewis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ #include #include "file.h" #include "qbsp.h" dheader_t *header; /* ============= LoadBSPFile ============= */ void LoadBSPFile(void) { int i; int cFileSize, cLumpSize, iLumpOff; // Load the file header StripExtension(options.szBSPName); strcat(options.szBSPName, ".bsp"); cFileSize = LoadFile(options.szBSPName, (void **)&header, true); if (header->version != BSPVERSION) Message(msgError, errBadVersion, options.szBSPName, header->version, BSPVERSION); // Throw all of the data into the first entity to be written out later for (i = 0; i < BSP_LUMPS; i++) { map.cTotal[i] = cLumpSize = header->lumps[i].filelen; iLumpOff = header->lumps[i].fileofs; if (cLumpSize % rgcMemSize[i]) Message(msgError, errDeformedBSPLump, rgcMemSize[i], cLumpSize); map.rgEntities[0].cData[i] = cLumpSize / rgcMemSize[i]; map.rgEntities[0].pData[i] = AllocMem(i, map.rgEntities[0].cData[i], false); memcpy(map.rgEntities[0].pData[i], (byte *)header + iLumpOff, cLumpSize); } FreeMem(header, OTHER, cFileSize + 1); } //============================================================================ // To be used for all dynamic mem data void AddLump(FILE *f, int Type) { lump_t *lump; int cLen = 0, templen; int iEntity; size_t ret; lump = &header->lumps[Type]; lump->fileofs = ftell(f); for (iEntity = 0; iEntity < map.cEntities; iEntity++) { if (map.rgEntities[iEntity].pData[Type] != NULL) { templen = map.rgEntities[iEntity].cData[Type] * rgcMemSize[Type]; ret = fwrite(map.rgEntities[iEntity].pData[Type], 1, templen, f); if (ret != templen) Message(msgError, errWriteFailure); cLen += templen; } } // Add null terminating char for text if (Type == BSPENT) { ret = fwrite("", 1, 1, f); if (ret != 1) Message(msgError, errWriteFailure); cLen++; } lump->filelen = cLen; // Pad to 4-byte boundary if (cLen % 4 != 0) { size_t pad = 4 - (cLen % 4); ret = fwrite(" ", 1, pad, f); if (ret != pad) Message(msgError, errWriteFailure); } } /* ============= WriteBSPFile ============= */ void WriteBSPFile(void) { FILE *f; size_t ret; header = (dheader_t *)AllocMem(OTHER, sizeof(dheader_t), true); header->version = BSPVERSION; StripExtension(options.szBSPName); strcat(options.szBSPName, ".bsp"); f = fopen(options.szBSPName, "wb"); if (f == NULL) Message(msgError, errOpenFailed, options.szBSPName, strerror(errno)); /* write placeholder, header is overwritten later */ ret = fwrite(header, sizeof(dheader_t), 1, f); if (ret != 1) Message(msgError, errWriteFailure); AddLump(f, BSPPLANE); AddLump(f, BSPLEAF); AddLump(f, BSPVERTEX); AddLump(f, BSPNODE); AddLump(f, BSPTEXINFO); AddLump(f, BSPFACE); AddLump(f, BSPCLIPNODE); AddLump(f, BSPMARKSURF); AddLump(f, BSPSURFEDGE); AddLump(f, BSPEDGE); AddLump(f, BSPMODEL); AddLump(f, BSPLIGHT); AddLump(f, BSPVIS); AddLump(f, BSPENT); AddLump(f, BSPTEX); fseek(f, 0, SEEK_SET); ret = fwrite(header, sizeof(dheader_t), 1, f); if (ret != 1) Message(msgError, errWriteFailure); fclose(f); FreeMem(header, OTHER, sizeof(dheader_t)); } //============================================================================ /* ============= PrintBSPFileSizes Dumps info about current file ============= */ void PrintBSPFileSizes(void) { Message(msgStat, "%5i planes %6i", map.cTotal[BSPPLANE], map.cTotal[BSPPLANE] * rgcMemSize[BSPPLANE]); Message(msgStat, "%5i vertexes %6i", map.cTotal[BSPVERTEX], map.cTotal[BSPVERTEX] * rgcMemSize[BSPVERTEX]); Message(msgStat, "%5i nodes %6i", map.cTotal[BSPNODE], map.cTotal[BSPNODE] * rgcMemSize[BSPNODE]); Message(msgStat, "%5i texinfo %6i", map.cTotal[BSPTEXINFO], map.cTotal[BSPTEXINFO] * rgcMemSize[BSPTEXINFO]); Message(msgStat, "%5i faces %6i", map.cTotal[BSPFACE], map.cTotal[BSPFACE] * rgcMemSize[BSPFACE]); Message(msgStat, "%5i clipnodes %6i", map.cTotal[BSPCLIPNODE], map.cTotal[BSPCLIPNODE] * rgcMemSize[BSPCLIPNODE]); Message(msgStat, "%5i leafs %6i", map.cTotal[BSPLEAF], map.cTotal[BSPLEAF] * rgcMemSize[BSPLEAF]); Message(msgStat, "%5i marksurfaces %6i", map.cTotal[BSPMARKSURF], map.cTotal[BSPMARKSURF] * rgcMemSize[BSPMARKSURF]); Message(msgStat, "%5i surfedges %6i", map.cTotal[BSPSURFEDGE], map.cTotal[BSPSURFEDGE] * rgcMemSize[BSPSURFEDGE]); Message(msgStat, "%5i edges %6i", map.cTotal[BSPEDGE], map.cTotal[BSPEDGE] * rgcMemSize[BSPEDGE]); if (!pWorldEnt->cTexdata) Message(msgStat, " 0 textures 0"); else Message(msgStat, "%5i textures %6i", ((dmiptexlump_t *)pWorldEnt->pTexdata)->nummiptex, pWorldEnt->cTexdata); Message(msgStat, " lightdata %6i", map.cTotal[BSPLIGHT]); Message(msgStat, " visdata %6i", map.cTotal[BSPVIS]); Message(msgStat, " entdata %6i", map.cTotal[BSPENT] + 1); // +1 for null terminator }