diff --git a/src/doomdata.h b/src/doomdata.h index d066277a7..6b3002cdb 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -29,6 +29,7 @@ // Some global defines, that configure the game. #include "doomdef.h" +#include "m_swap.h" // // Map level types. @@ -220,6 +221,13 @@ struct mapsubsector_t WORD firstseg; // index of first one, segs are stored sequentially }; +#pragma pack(1) +struct mapsubsector4_t +{ + WORD numsegs; + DWORD firstseg; // index of first one, segs are stored sequentially +}; +#pragma pack() // LineSeg, generated by splitting LineDefs // using partition lines selected by BSP builder. @@ -231,6 +239,22 @@ struct mapseg_t WORD linedef; SWORD side; SWORD offset; + + int V1() { return LittleShort(v1); } + int V2() { return LittleShort(v2); } +}; + +struct mapseg4_t +{ + SDWORD v1; + SDWORD v2; + SWORD angle; + WORD linedef; + SWORD side; + SWORD offset; + + int V1() { return LittleLong(v1); } + int V2() { return LittleLong(v2); } }; @@ -238,18 +262,40 @@ struct mapseg_t // BSP node structure. // Indicate a leaf. -#define NF_SUBSECTOR 0x8000 struct mapnode_t { + enum + { + NF_SUBSECTOR = 0x8000, + NF_LUMPOFFSET = 0 + }; SWORD x,y,dx,dy; // partition line SWORD bbox[2][4]; // bounding box for each child // If NF_SUBSECTOR is or'ed in, it's a subsector, // else it's a node of another subtree. WORD children[2]; + + DWORD Child(int num) { return LittleShort(children[num]); } }; +struct mapnode4_t +{ + enum + { + NF_SUBSECTOR = 0x80000000, + NF_LUMPOFFSET = 8 + }; + SWORD x,y,dx,dy; // partition line + SWORD bbox[2][4]; // bounding box for each child + // If NF_SUBSECTOR is or'ed in, it's a subsector, + // else it's a node of another subtree. + DWORD children[2]; + + DWORD Child(int num) { return LittleLong(children[num]); } +}; + // Thing definition, position, orientation and type, diff --git a/src/p_setup.cpp b/src/p_setup.cpp index d9b285c03..5a6cc671f 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1029,6 +1029,22 @@ static void P_LoadZNodes (FileReader &dalump, DWORD id) } +//=========================================================================== +// +// P_CheckV4Nodes +// http://www.sbsoftware.com/files/DeePBSPV4specs.txt +// +//=========================================================================== + +static bool P_CheckV4Nodes(MapData *map) +{ + char header[8]; + + map->Read(ML_NODES, header, 8); + return !memcmp(header, "xNd4\0\0\0\0", 8); +} + + //=========================================================================== // // P_LoadSegs @@ -1037,6 +1053,7 @@ static void P_LoadZNodes (FileReader &dalump, DWORD id) // //=========================================================================== +template void P_LoadSegs (MapData * map) { int i; @@ -1053,7 +1070,7 @@ void P_LoadSegs (MapData * map) memset (vertchanged,0,numvertexes); // phares 10/4/98 - numsegs = lumplen / sizeof(mapseg_t); + numsegs = lumplen / sizeof(segtype); if (numsegs == 0) { @@ -1085,14 +1102,14 @@ void P_LoadSegs (MapData * map) { for (i = 0; i < numsegs; i++) { - seg_t *li = segs+i; - mapseg_t *ml = (mapseg_t *) data + i; + seg_t *li = segs + i; + segtype *ml = ((segtype *) data) + i; int side, linedef; line_t *ldef; - vnum1 = LittleShort(ml->v1); - vnum2 = LittleShort(ml->v2); + vnum1 = ml->V1(); + vnum2 = ml->V2(); if (vnum1 >= numvertexes || vnum2 >= numvertexes) { @@ -1222,12 +1239,13 @@ void P_LoadSegs (MapData * map) // //=========================================================================== +template void P_LoadSubsectors (MapData * map) { int i; - DWORD maxseg = map->Size(ML_SEGS) / sizeof(mapseg_t); + DWORD maxseg = map->Size(ML_SEGS) / sizeof(segtype); - numsubsectors = map->MapLumps[ML_SSECTORS].Size / sizeof(mapsubsector_t); + numsubsectors = map->MapLumps[ML_SSECTORS].Size / sizeof(subsectortype); if (numsubsectors == 0 || maxseg == 0 ) { @@ -1244,11 +1262,11 @@ void P_LoadSubsectors (MapData * map) for (i = 0; i < numsubsectors; i++) { - WORD numsegs, firstseg; + subsectortype subd; - (*map->file) >> numsegs >> firstseg; + (*map->file) >> subd.numsegs >> subd.firstseg; - if (numsegs == 0) + if (subd.numsegs == 0) { Printf ("Subsector %i is empty.\n", i); delete[] subsectors; @@ -1257,8 +1275,8 @@ void P_LoadSubsectors (MapData * map) return; } - subsectors[i].numlines = numsegs; - subsectors[i].firstline = firstseg; + subsectors[i].numlines = subd.numsegs; + subsectors[i].firstline = subd.firstseg; if (subsectors[i].firstline >= maxseg) { @@ -1390,6 +1408,7 @@ void P_LoadSectors (MapData * map) // //=========================================================================== +template void P_LoadNodes (MapData * map) { FMemLump data; @@ -1397,13 +1416,13 @@ void P_LoadNodes (MapData * map) int j; int k; char *mnp; - mapnode_t *mn; + nodetype *mn; node_t* no; WORD* used; int lumplen = map->Size(ML_NODES); - int maxss = map->Size(ML_SSECTORS) / sizeof(mapsubsector_t); + int maxss = map->Size(ML_SSECTORS) / sizeof(subsectortype); - numnodes = lumplen / sizeof(mapnode_t); + numnodes = (lumplen - nodetype::NF_LUMPOFFSET) / sizeof(nodetype); if ((numnodes == 0 && maxss != 1) || maxss == 0) { @@ -1416,8 +1435,8 @@ void P_LoadNodes (MapData * map) memset (used, 0, sizeof(WORD)*numnodes); mnp = new char[lumplen]; - mn = (mapnode_t*)mnp; - map->Read(ML_NODES, mn); + mn = (nodetype*)(mnp + nodetype::NF_LUMPOFFSET); + map->Read(ML_NODES, mnp); no = nodes; for (i = 0; i < numnodes; i++, no++, mn++) @@ -1428,10 +1447,10 @@ void P_LoadNodes (MapData * map) no->dy = LittleShort(mn->dy)<children[j]); - if (child & NF_SUBSECTOR) + int child = mn->Child(j); + if (child & nodetype::NF_SUBSECTOR) { - child &= ~NF_SUBSECTOR; + child &= ~nodetype::NF_SUBSECTOR; if (child >= maxss) { Printf ("BSP node %d references invalid subsector %d.\n" @@ -3590,17 +3609,34 @@ void P_SetupLevel (char *lumpname, int position) // This just means that the map has no nodes and the engine is supposed to build them. if (map->Size(ML_SEGS) != 0 || map->Size(ML_SSECTORS) != 0 || map->Size(ML_NODES) != 0) { - times[7].Clock(); - P_LoadSubsectors (map); - times[7].Unclock(); + if (!P_CheckV4Nodes(map)) + { + times[7].Clock(); + P_LoadSubsectors (map); + times[7].Unclock(); - times[8].Clock(); - if (!ForceNodeBuild) P_LoadNodes (map); - times[8].Unclock(); + times[8].Clock(); + if (!ForceNodeBuild) P_LoadNodes (map); + times[8].Unclock(); - times[9].Clock(); - if (!ForceNodeBuild) P_LoadSegs (map); - times[9].Unclock(); + times[9].Clock(); + if (!ForceNodeBuild) P_LoadSegs (map); + times[9].Unclock(); + } + else + { + times[7].Clock(); + P_LoadSubsectors (map); + times[7].Unclock(); + + times[8].Clock(); + if (!ForceNodeBuild) P_LoadNodes (map); + times[8].Unclock(); + + times[9].Clock(); + if (!ForceNodeBuild) P_LoadSegs (map); + times[9].Unclock(); + } } else ForceNodeBuild = true; } diff --git a/src/p_writemap.cpp b/src/p_writemap.cpp index db758631f..7a052cb3b 100644 --- a/src/p_writemap.cpp +++ b/src/p_writemap.cpp @@ -172,8 +172,10 @@ static int WriteVERTEXES (FILE *file) return numvertexes * sizeof(mv); } + static int WriteSEGS (FILE *file) { +#if 0 mapseg_t ms; ms.offset = 0; // unused by ZDoom, so just leave it 0 @@ -190,10 +192,14 @@ static int WriteSEGS (FILE *file) } } return numsegs * sizeof(ms); +#else + return 0; +#endif } static int WriteSSECTORS (FILE *file) { +#if 0 mapsubsector_t mss; for (int i = 0; i < numsubsectors; ++i) @@ -203,10 +209,14 @@ static int WriteSSECTORS (FILE *file) fwrite (&mss, sizeof(mss), 1, file); } return numsubsectors * sizeof(mss); +#else + return 0; +#endif } static int WriteNODES (FILE *file) { +#if 0 mapnode_t mn; for (int i = 0; i < numnodes; ++i) @@ -224,7 +234,7 @@ static int WriteNODES (FILE *file) WORD child; if ((size_t)nodes[i].children[j] & 1) { - child = NF_SUBSECTOR | WORD((subsector_t *)((BYTE *)nodes[i].children[j] - 1) - subsectors); + child = mapnode_t::NF_SUBSECTOR | WORD((subsector_t *)((BYTE *)nodes[i].children[j] - 1) - subsectors); } else { @@ -235,6 +245,9 @@ static int WriteNODES (FILE *file) fwrite (&mn, sizeof(mn), 1, file); } return numnodes * sizeof(mn); +#else + return 0; +#endif } static int WriteSECTORS (FILE *file)