shithub: qk1

Download patch

ref: a9de1dc067febe2b0a58ce944468fe3deec0d26c
parent: 67889c603188245b568d12d9fd0d1654805cc7c4
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sat Oct 14 13:00:51 EDT 2023

add bsp2 support

--- a/bspfile.h
+++ b/bspfile.h
@@ -30,6 +30,7 @@
 //=============================================================================
 
 #define BSPVERSION	29
+#define BSP2VERSION ('B'|'S'<<8|'P'<<16|'2'<<24)
 #define	TOOLVERSION	2
 
 #pragma pack on
@@ -141,9 +142,24 @@
 typedef struct
 {
 	int			planenum;
+	int			children[2];	// negative numbers are -(leafs+1), not nodes
+	float		mins[3];		// for sphere culling
+	float		maxs[3];
+	unsigned int	firstface;
+	unsigned int	numfaces;	// counting both sides
+} bsp2_dnode_t;
+
+typedef struct
+{
+	int			planenum;
 	short		children[2];	// negative numbers are contents
 } dclipnode_t;
 
+typedef struct
+{
+	int		planenum;
+	int		children[2];	// negative numbers are contents
+} bsp2_dclipnode_t;
 
 typedef struct texinfo_s
 {
@@ -160,6 +176,11 @@
 	unsigned short	v[2];		// vertex numbers
 } dedge_t;
 
+typedef struct
+{
+	unsigned int v[2];
+} bsp2_dedge_t;
+
 #define	MAXLIGHTMAPS	4
 typedef struct
 {
@@ -175,6 +196,20 @@
 	int			lightofs;		// start of [numstyles*surfsize] samples
 } dface_t;
 
+typedef struct
+{
+	int		planenum;
+	int		side;
+
+	int			firstedge;		// we must support > 64k edges
+	int		numedges;	
+	int		texinfo;
+
+// lighting info
+	byte		styles[MAXLIGHTMAPS];
+	int			lightofs;		// start of [numstyles*surfsize] samples
+} bsp2_dface_t;
+
 // leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
 // all other leafs need visibility info
 typedef struct
@@ -190,6 +225,20 @@
 
 	byte		ambient_level[Namb];
 } dleaf_t;
+
+typedef struct
+{
+	int			contents;
+	int			visofs;				// -1 = no visibility info
+
+	float		mins[3];			// for frustum culling
+	float		maxs[3];
+
+	unsigned int		firstmarksurface;
+	unsigned int		nummarksurfaces;
+
+	byte		ambient_level[Namb];
+} bsp2_dleaf_t;
 
 #pragma pack off
 
--- a/common.c
+++ b/common.c
@@ -497,3 +497,14 @@
 
 	return s;  
 }
+
+float
+f32le(u32int u)
+{
+	union {
+		float f;
+		u32int u;
+	}x;
+	x.u = u;
+	return x.f;
+}
--- a/common.h
+++ b/common.h
@@ -61,6 +61,14 @@
 extern	float	(*BigFloat) (float l);
 extern	float	(*LittleFloat) (float l);
 
+float f32le(u32int u);
+
+#define le32(p) (p += 4, (int)(p[-4]|p[-3]<<8|p[-2]<<16|p[-1]<<24))
+#define le32u(p) (u32int)le32(p)
+#define le16(p) (p += 2, (short)(p[-2]|p[-1]<<8))
+#define le16u(p) (u16int)le16(p)
+#define f32(p) f32le(le32(p))
+
 //============================================================================
 
 void MSG_WriteChar (sizebuf_t *sb, int c);
--- a/model.c
+++ b/model.c
@@ -12,9 +12,6 @@
 void Mod_LoadAliasModel (model_t *mod, void *buffer);
 model_t *Mod_LoadModel (model_t *mod, qboolean crash);
 
-static byte *mod_novis;
-static int mod_novis_size;
-
 #define	MAX_MOD_KNOWN	4096
 model_t	*mod_known;
 int		mod_numknown;
@@ -95,39 +92,31 @@
 	byte	*out;
 	int		row;
 
-	row = (model->numleafs+7)>>3;	
+	row = (model->numleafs+7)/8;	
 	if(decompressed == nil || row > decompressed_size){
-		decompressed_size = (row + 15) & ~15;
+		decompressed_size = row;
 		decompressed = realloc(decompressed, decompressed_size);
 	}
 	out = decompressed;
 
-	if (!in)
-	{	// no vis info, so make all visible
-		while (row)
-		{
-			*out++ = 0xff;
-			row--;
-		}
+	if(!in){ // no vis info, so make all visible
+		memset(out, 0xff, row);
 		return decompressed;		
 	}
 
-	do
-	{
-		if (*in)
-		{
+	do{
+		if (*in){
 			*out++ = *in++;
 			continue;
 		}
-	
+
 		c = in[1];
 		in += 2;
-		while (c)
-		{
+		while(c){
 			*out++ = 0;
 			c--;
 		}
-	} while (out - decompressed < row);
+	}while(out - decompressed < row);
 	
 	return decompressed;
 }
@@ -134,9 +123,11 @@
 
 byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
 {
+	static byte *mod_novis;
+	static int mod_novis_size;
 	int sz;
+
 	sz = (model->numleafs+7)/8;
-	sz = (sz+3)&~3;
 	if (leaf == model->leafs) {
 		if(mod_novis == nil || mod_novis_size < sz){
 			mod_novis = realloc(mod_novis, sz);
@@ -601,25 +592,26 @@
 Mod_LoadEdges
 =================
 */
-void Mod_LoadEdges (lump_t *l)
+void Mod_LoadEdges (lump_t *l, int ver)
 {
-	dedge_t *in;
+	byte *in;
 	medge_t *out;
-	int 	i, count;
+	int 	i, count, sz;
 
 	in = (void *)(mod_base + l->fileofs);
-	if (l->filelen % sizeof(*in))
+	sz = ver == BSP2VERSION ? sizeof(bsp2_dedge_t) : sizeof(dedge_t);
+	if (l->filelen % sz)
 		fatal("Mod_LoadEdges: funny lump size in %s", loadmodel->name);
-	count = l->filelen / sizeof(*in);
+	count = l->filelen / sz;
 	out = Hunk_Alloc((count+1) * sizeof *out);
 
 	loadmodel->edges = out;
 	loadmodel->numedges = count;
 
-	for ( i=0 ; i<count ; i++, in++, out++)
+	for ( i=0 ; i<count ; i++, out++)
 	{
-		out->v[0] = (unsigned short)LittleShort(in->v[0]);
-		out->v[1] = (unsigned short)LittleShort(in->v[1]);
+		out->v[0] = ver == BSP2VERSION ? le32u(in) : le16u(in);
+		out->v[1] = ver == BSP2VERSION ? le32u(in) : le16u(in);
 	}
 }
 
@@ -748,66 +740,48 @@
 Mod_LoadFaces
 =================
 */
-void Mod_LoadFaces (lump_t *l)
+void Mod_LoadFaces (lump_t *l, int ver)
 {
-	dface_t		*in;
+	byte		*in;
 	msurface_t 	*out;
-	int			i, count, surfnum;
-	int			planenum, side;
+	int			i, count, surfnum, sz;
 
 	in = (void *)(mod_base + l->fileofs);
-	if (l->filelen % sizeof(*in))
+	sz = ver == BSP2VERSION ? sizeof(bsp2_dface_t) : sizeof(dface_t);
+	if (l->filelen % sz)
 		fatal("Mod_LoadFaces: funny lump size in %s", loadmodel->name);
-	count = l->filelen / sizeof(*in);
+	count = l->filelen / sz;
 	out = Hunk_Alloc(count * sizeof *out);
 
 	loadmodel->surfaces = out;
 	loadmodel->numsurfaces = count;
 
-	for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
+	for ( surfnum=0 ; surfnum<count ; surfnum++, out++)
 	{
-		out->firstedge = LittleLong(in->firstedge);
-		out->numedges = LittleShort(in->numedges);		
-		out->flags = 0;
+		out->plane = loadmodel->planes + (ver == BSP2VERSION ? le32u(in) : le16u(in));
+		out->flags = (ver == BSP2VERSION ? le32u(in) : le16u(in)) ? SURF_PLANEBACK : 0;
+		out->firstedge = le32u(in);
+		out->numedges = ver == BSP2VERSION ? le32u(in) : le16u(in);
+		out->texinfo = loadmodel->texinfo + (ver == BSP2VERSION ? le32u(in) : le16u(in));
 
-		planenum = LittleShort(in->planenum);
-		side = LittleShort(in->side);
-		if (side)
-			out->flags |= SURF_PLANEBACK;			
-
-		out->plane = loadmodel->planes + planenum;
-
-		out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
-
 		CalcSurfaceExtents (out);
-				
+
 	// lighting info
 
-		for (i=0 ; i<MAXLIGHTMAPS ; i++)
-			out->styles[i] = in->styles[i];
-		i = LittleLong(in->lightofs);
-		if (i == -1)
-			out->samples = nil;
-		else
-			out->samples = loadmodel->lightdata + i;
-		
+		memmove(out->styles, in, MAXLIGHTMAPS);
+		in += MAXLIGHTMAPS;
+		out->samples = (i = le32(in)) < 0 ? nil : loadmodel->lightdata + i;
+
 	// set the drawing flags flag
 		
 		if(strncmp(out->texinfo->texture->name, "sky", 3) == 0)
-		{
-			out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
-			continue;
-		}
-		
-		if(strncmp(out->texinfo->texture->name, "*", 1) == 0)	// turbulent
-		{
-			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
-			for (i=0 ; i<2 ; i++)
-			{
+			out->flags |= SURF_DRAWSKY | SURF_DRAWTILED;
+		else if(strncmp(out->texinfo->texture->name, "*", 1) == 0){	// turbulent
+			out->flags |= SURF_DRAWTURB | SURF_DRAWTILED;
+			for (i=0 ; i<2 ; i++){
 				out->extents[i] = 16384;
 				out->texturemins[i] = -8192;
 			}
-			continue;
 		}
 	}
 }
@@ -832,50 +806,50 @@
 Mod_LoadNodes
 =================
 */
-void Mod_LoadNodes (lump_t *l)
+void Mod_LoadNodes (lump_t *l, int ver)
 {
-	int			i, j, count, p;
-	dnode_t		*in;
+	int			i, j, count, p, sz;
+	byte		*in;
 	mnode_t 	*out;
 
 	in = (void *)(mod_base + l->fileofs);
-	if (l->filelen % sizeof(*in))
+	sz = ver == BSP2VERSION ? sizeof(bsp2_dnode_t) : sizeof(dnode_t);
+	if (l->filelen % sz)
 		fatal("Mod_LoadNodes: funny lump size in %s", loadmodel->name);
-	count = l->filelen / sizeof(*in);
+	count = l->filelen / sz;
 	out = Hunk_Alloc(count * sizeof *out);
 
 	loadmodel->nodes = out;
 	loadmodel->numnodes = count;
 
-	for ( i=0 ; i<count ; i++, in++, out++)
+	for ( i=0 ; i<count ; i++, out++)
 	{
-		for (j=0 ; j<3 ; j++)
-		{
-			out->minmaxs[j] = LittleShort (in->mins[j]);
-			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
-		}
-	
-		p = LittleLong(in->planenum);
-		out->plane = loadmodel->planes + p;
+		out->plane = loadmodel->planes + le32u(in);
 
-		out->firstsurface = (ushort)LittleShort (in->firstface);
-		out->numsurfaces = (ushort)LittleShort (in->numfaces);
-		
-		for (j=0 ; j<2 ; j++)
-		{
-			p = (ushort)LittleShort (in->children[j]);
-			if (p < count)
+		for (j=0 ; j<2 ; j++){
+			p = ver == BSP2VERSION ? le32(in) : le16u(in);
+			if(p >= 0 && p < count)
 				out->children[j] = loadmodel->nodes + p;
 			else{
-				p = -1 - (signed)(0xffff0000 | p);
+				p = ver == BSP2VERSION ? -1-p : 0xffff-p;
 				if(p >= 0 && p < loadmodel->numleafs)
 					out->children[j] = (mnode_t *)(loadmodel->leafs + p);
-				else
+				else{
 					Con_Printf("Mod_LoadNodes: invalid node child\n");
+					out->children[j] = (mnode_t *)loadmodel->leafs;
+				}
 			}
 		}
+
+		for(j=0 ; j<3 ; j++)
+			out->minmaxs[0+j] = ver == BSP2VERSION ? f32(in) : le16(in);
+		for(j=0 ; j<3 ; j++)
+			out->minmaxs[3+j] = ver == BSP2VERSION ? f32(in) : le16(in);
+
+		out->firstsurface = ver == BSP2VERSION ? le32u(in) : le16u(in);
+		out->numsurfaces = ver == BSP2VERSION ? le32u(in) : le16u(in);
 	}
-	
+
 	Mod_SetParent (loadmodel->nodes, nil);	// sets nodes and leafs
 }
 
@@ -884,45 +858,37 @@
 Mod_LoadLeafs
 =================
 */
-void Mod_LoadLeafs (lump_t *l)
+void Mod_LoadLeafs (lump_t *l, int ver)
 {
-	dleaf_t 	*in;
+	byte	 	*in;
 	mleaf_t 	*out;
-	int			i, j, count, p;
+	int			i, j, count, p, sz;
 
 	in = (void *)(mod_base + l->fileofs);
-	if (l->filelen % sizeof(*in))
+	sz = ver == BSP2VERSION ? sizeof(bsp2_dleaf_t) : sizeof(dleaf_t);
+	if (l->filelen % sz)
 		fatal("Mod_LoadLeafs: funny lump size in %s", loadmodel->name);
-	count = l->filelen / sizeof(*in);
+	count = l->filelen / sz;
 	out = Hunk_Alloc(count * sizeof *out);
 
 	loadmodel->leafs = out;
 	loadmodel->numleafs = count;
 
-	for ( i=0 ; i<count ; i++, in++, out++)
+	for ( i=0 ; i<count ; i++, out++)
 	{
-		for (j=0 ; j<3 ; j++)
-		{
-			out->minmaxs[j] = LittleShort (in->mins[j]);
-			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
-		}
+		out->contents = le32(in);
+		out->compressed_vis = (p = le32(in)) < 0 ? nil : loadmodel->visdata + p;
 
-		p = LittleLong(in->contents);
-		out->contents = p;
+		for(j=0 ; j<3 ; j++)
+			out->minmaxs[0+j] = ver == BSP2VERSION ? f32(in) : le16(in);
+		for(j=0 ; j<3 ; j++)
+			out->minmaxs[3+j] = ver == BSP2VERSION ? f32(in) : le16(in);
 
-		out->firstmarksurface = loadmodel->marksurfaces +
-			(ushort)LittleShort(in->firstmarksurface);
-		out->nummarksurfaces = (ushort)LittleShort(in->nummarksurfaces);
-		
-		p = LittleLong(in->visofs);
-		if (p == -1)
-			out->compressed_vis = nil;
-		else
-			out->compressed_vis = loadmodel->visdata + p;
-		out->efrags = nil;
-		
-		for (j=0 ; j<4 ; j++)
-			out->ambient_sound_level[j] = in->ambient_level[j];
+		out->firstmarksurface = loadmodel->marksurfaces + (ver == BSP2VERSION ? le32u(in) : le16u(in));
+		out->nummarksurfaces = ver == BSP2VERSION ? le32u(in) : le16u(in);
+
+		memmove(out->ambient_sound_level, in, 4);
+		in += 4;
 	}	
 }
 
@@ -931,17 +897,18 @@
 Mod_LoadClipnodes
 =================
 */
-void Mod_LoadClipnodes (lump_t *l)
+void Mod_LoadClipnodes (lump_t *l, int ver)
 {
-	dclipnode_t *in;
+	byte *in;
 	mclipnode_t	*out;
-	int			i, count;
+	int			i, count, sz;
 	hull_t		*hull;
 
 	in = (void *)(mod_base + l->fileofs);
-	if (l->filelen % sizeof(*in))
+	sz = ver == BSP2VERSION ? sizeof(bsp2_dclipnode_t) : sizeof(dclipnode_t);
+	if (l->filelen % sz)
 		fatal("Mod_LoadClipnodes: funny lump size in %s", loadmodel->name);
-	count = l->filelen / sizeof(*in);
+	count = l->filelen / sz;
 	out = Hunk_Alloc(count * sizeof *out);
 
 	loadmodel->clipnodes = out;
@@ -971,11 +938,11 @@
 	hull->clip_maxs[1] = 32;
 	hull->clip_maxs[2] = 64;
 
-	for (i=0 ; i<count ; i++, out++, in++)
+	for (i=0 ; i<count ; i++, out++)
 	{
-		out->planenum = LittleLong(in->planenum);
-		out->children[0] = (unsigned short)LittleShort(in->children[0]);
-		out->children[1] = (unsigned short)LittleShort(in->children[1]);
+		out->planenum = le32u(in);
+		out->children[0] = ver == BSP2VERSION ? le32u(in) : le16u(in);
+		out->children[1] = ver == BSP2VERSION ? le32u(in) : le16u(in);
 		if(out->children[0] >= count)
 			out->children[0] -= 0x10000;
 		if(out->children[1] >= count)
@@ -1027,16 +994,17 @@
 Mod_LoadMarksurfaces
 =================
 */
-void Mod_LoadMarksurfaces (lump_t *l)
+void Mod_LoadMarksurfaces (lump_t *l, int ver)
 {	
-	int		i, j, count;
-	short		*in;
+	int		i, j, count, sz;
+	byte		*in;
 	msurface_t **out;
-	
+
 	in = (void *)(mod_base + l->fileofs);
-	if (l->filelen % sizeof(*in))
+	sz = ver == BSP2VERSION ? sizeof(u32int) : sizeof(u16int);
+	if (l->filelen % sz)
 		fatal("Mod_LoadMarksurfaces: funny lump size in %s", loadmodel->name);
-	count = l->filelen / sizeof(*in);
+	count = l->filelen / sz;
 	out = Hunk_Alloc(count * sizeof *out);
 
 	loadmodel->marksurfaces = out;
@@ -1044,9 +1012,9 @@
 
 	for ( i=0 ; i<count ; i++)
 	{
-		j = (ushort)LittleShort(in[i]);
-		if (j >= loadmodel->numsurfaces)
-			fatal ("Mod_ParseMarksurfaces: bad surface number");
+		j = ver == BSP2VERSION ? le32u(in) : le16u(in);
+		if(j < 0 || j >= loadmodel->numsurfaces)
+			fatal("Mod_ParseMarksurfaces: bad surface number");
 		out[i] = loadmodel->surfaces + j;
 	}
 }
@@ -1137,7 +1105,7 @@
 */
 void Mod_LoadBrushModel (model_t *mod, void *buffer)
 {
-	int			i, j;
+	int			i, j, ver;
 	dheader_t	*header;
 	dmodel_t 	*bm;
 	
@@ -1145,9 +1113,9 @@
 	
 	header = (dheader_t *)buffer;
 
-	i = LittleLong (header->version);
-	if (i != BSPVERSION)
-		fatal("Mod_LoadBrushModel: %s has wrong version number (%d should be %d)", mod->name, i, BSPVERSION);
+	ver = LittleLong (header->version);
+	if (ver != BSPVERSION && ver != BSP2VERSION)
+		fatal("Mod_LoadBrushModel: %s has wrong version number (%ux should be %ux or %ux)", mod->name, ver, BSPVERSION, BSP2VERSION);
 
 // swap all the lumps
 	mod_base = (byte *)header;
@@ -1158,18 +1126,18 @@
 // load into heap
 	
 	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
-	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
+	Mod_LoadEdges (&header->lumps[LUMP_EDGES], ver);
 	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
 	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
 	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
 	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
 	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
-	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
-	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
+	Mod_LoadFaces (&header->lumps[LUMP_FACES], ver);
+	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES], ver);
 	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
-	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
-	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
-	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
+	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS], ver);
+	Mod_LoadNodes (&header->lumps[LUMP_NODES], ver);
+	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES], ver);
 	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
 	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
 
--- a/model.h
+++ b/model.h
@@ -95,7 +95,7 @@
 	struct surfcache_s	*cachespots[MIPLEVELS];
 
 	int		texturemins[2];
-	short		extents[2];
+	int		extents[2];
 
 	mtexinfo_t	*texinfo;
 	
@@ -110,7 +110,7 @@
 	int			contents;		// 0, to differentiate from leafs
 	int			visframe;		// node needs to be traversed if current
 	
-	int		minmaxs[6];		// for bounding box culling
+	float		minmaxs[6];		// for bounding box culling
 
 	struct mnode_s	*parent;
 
@@ -130,7 +130,7 @@
 	int			contents;		// wil be a negative contents number
 	int			visframe;		// node needs to be traversed if current
 
-	int		minmaxs[6];		// for bounding box culling
+	float		minmaxs[6];		// for bounding box culling
 
 	struct mnode_s	*parent;
 
--- a/world.c
+++ b/world.c
@@ -264,7 +264,7 @@
 	int			old_self, old_other;
 
 // touch linked edicts
-	for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next)
+	for (l = node->trigger_edicts.next ; l != nil && l != &node->trigger_edicts ; l = next)
 	{
 		next = l->next;
 		touch = EDICT_FROM_AREA(l);