Index: common/bspfile.c
===================================================================
--- common/bspfile.c	(revision 814)
+++ common/bspfile.c	(working copy)
@@ -904,6 +904,17 @@
 	  BSPVersionString(bspdata->version), BSPVersionString(version));
 }
 
+static int 
+isHexen2(const dheader_t *header)
+{
+	/*
+	the world should always have some face.
+	however, if the sizes are wrong then we're actually reading headnode[6]. hexen2 only used 5 hulls, so this should be 0 in hexen2, and not in quake.
+	*/
+	const dmodelq1_t *modelsq1 = (const dmodelq1_t*)((const byte *)header + header->lumps[LUMP_MODELS].fileofs);
+	return !modelsq1->numfaces;
+}
+
 /*
  * =========================================================================
  * ...
@@ -990,12 +1001,45 @@
     length = header->lumps[lumpnum].filelen;
     ofs = header->lumps[lumpnum].fileofs;
 
+	if (buffer)
+		free(buffer);
+
+	if (lumpnum == LUMP_MODELS && !isHexen2(header))
+	{	/*convert in-place. no need to care about endian here.*/
+		const dmodelq1_t *in = (const dmodelq1_t*)((const byte *)header + ofs);
+		dmodel_t *out;
+		int i, j;
+		if (length % sizeof(dmodelq1_t))
+			Error("%s: odd %s lump size", __func__, lumpspec->name);
+		length /= sizeof(dmodelq1_t);
+
+		buffer = *bufferptr = malloc(length * sizeof(dmodel_t));
+		if (!buffer)
+			Error("%s: allocation of %i bytes failed.", __func__, length);
+		out = (dmodel_t*)buffer;
+		for (i = 0; i < length; i++)
+		{
+			for (j = 0; j < 3; j++)
+			{
+				out[i].mins[j] = in[i].mins[j];
+				out[i].maxs[j] = in[i].maxs[j];
+				out[i].origin[j] = in[i].origin[j];
+			}
+			for (j = 0; j < MAX_MAP_HULLS_Q1; j++)
+				out[i].headnode[j] = in[i].headnode[j];
+			for (     ; j < MAX_MAP_HULLS_H2; j++)
+				out[i].headnode[j] = 0;
+			out[i].visleafs = in[i].visleafs;
+			out[i].firstface = in[i].firstface;
+			out[i].numfaces = in[i].numfaces;
+		}
+		return length;
+	}
+	else
+	{
     if (length % lumpspec->size)
 	Error("%s: odd %s lump size", __func__, lumpspec->name);
 
-    if (buffer)
-	free(buffer);
-
     buffer = *bufferptr = malloc(length + 1);
     if (!buffer)
 	Error("%s: allocation of %i bytes failed.", __func__, length);
@@ -1004,6 +1048,7 @@
     buffer[length] = 0; /* In case of corrupt entity lump */
 
     return length / lumpspec->size;
+	}
 }
 
 /*
@@ -1032,6 +1077,14 @@
 	header->lumps[i].filelen = LittleLong(header->lumps[i].filelen);
     }
 
+	if (isHexen2(header))
+	{
+		logprint("BSP appears to be from hexen2\n");
+		bspdata->hullcount = MAX_MAP_HULLS_H2;
+	}
+	else
+		bspdata->hullcount = MAX_MAP_HULLS_Q1;
+
     /* copy the data */
     if (header->version == BSPVERSION) {
 	bsp29_t *bsp = &bspdata->data.bsp29;
@@ -1147,6 +1200,39 @@
 	SafeWrite(bspfile->file, pad, size % 4);
 }
 
+static void
+AddModelsLump(bspfile_t *bspfile, bspdata_t *bspdata, const void *data, int count)
+{
+	if (bspdata->hullcount == MAX_MAP_HULLS_Q1)
+	{	/*convert in-place. no need to care about endian here.*/
+		lump_t *lump = &bspfile->header.lumps[LUMP_MODELS];
+		const dmodel_t *in = data;
+		dmodelq1_t *out = malloc(count * sizeof(dmodelq1_t));
+		int i, j;
+		for (i = 0; i < count; i++)
+		{
+			for (j = 0; j < 3; j++)
+			{
+				out[i].mins[j] = in[i].mins[j];
+				out[i].maxs[j] = in[i].maxs[j];
+				out[i].origin[j] = in[i].origin[j];
+			}
+			for (j = 0; j < MAX_MAP_HULLS_Q1; j++)
+				out[i].headnode[j] = in[i].headnode[j];
+			out[i].visleafs = in[i].visleafs;
+			out[i].firstface = in[i].firstface;
+			out[i].numfaces = in[i].numfaces;
+		}
+		lump->fileofs = LittleLong(ftell(bspfile->file));
+		lump->filelen = LittleLong(sizeof(dmodelq1_t) * count);
+		SafeWrite(bspfile->file, out, lump->filelen);
+		free(out);
+		return;
+	}
+	else
+		AddLump(bspfile, LUMP_MODELS, data, count);
+}
+
 /*
  * =============
  * WriteBSPFile
@@ -1182,7 +1268,7 @@
 	AddLump(&bspfile, LUMP_MARKSURFACES, bsp->dmarksurfaces, bsp->nummarksurfaces);
 	AddLump(&bspfile, LUMP_SURFEDGES, bsp->dsurfedges, bsp->numsurfedges);
 	AddLump(&bspfile, LUMP_EDGES, bsp->dedges, bsp->numedges);
-	AddLump(&bspfile, LUMP_MODELS, bsp->dmodels, bsp->nummodels);
+	AddModelsLump(&bspfile, bspdata, bsp->dmodels, bsp->nummodels);
 
 	AddLump(&bspfile, LUMP_LIGHTING, bsp->dlightdata, bsp->lightdatasize);
 	AddLump(&bspfile, LUMP_VISIBILITY, bsp->dvisdata, bsp->visdatasize);
@@ -1203,7 +1289,7 @@
 	AddLump(&bspfile, LUMP_MARKSURFACES, bsp->dmarksurfaces, bsp->nummarksurfaces);
 	AddLump(&bspfile, LUMP_SURFEDGES, bsp->dsurfedges, bsp->numsurfedges);
 	AddLump(&bspfile, LUMP_EDGES, bsp->dedges, bsp->numedges);
-	AddLump(&bspfile, LUMP_MODELS, bsp->dmodels, bsp->nummodels);
+	AddModelsLump(&bspfile, bspdata, bsp->dmodels, bsp->nummodels);
 
 	AddLump(&bspfile, LUMP_LIGHTING, bsp->dlightdata, bsp->lightdatasize);
 	AddLump(&bspfile, LUMP_VISIBILITY, bsp->dvisdata, bsp->visdatasize);
@@ -1224,7 +1310,7 @@
 	AddLump(&bspfile, LUMP_MARKSURFACES, bsp->dmarksurfaces, bsp->nummarksurfaces);
 	AddLump(&bspfile, LUMP_SURFEDGES, bsp->dsurfedges, bsp->numsurfedges);
 	AddLump(&bspfile, LUMP_EDGES, bsp->dedges, bsp->numedges);
-	AddLump(&bspfile, LUMP_MODELS, bsp->dmodels, bsp->nummodels);
+	AddModelsLump(&bspfile, bspdata, bsp->dmodels, bsp->nummodels);
 
 	AddLump(&bspfile, LUMP_LIGHTING, bsp->dlightdata, bsp->lightdatasize);
 	AddLump(&bspfile, LUMP_VISIBILITY, bsp->dvisdata, bsp->visdatasize);
Index: include/common/bspfile.h
===================================================================
--- include/common/bspfile.h	(revision 814)
+++ include/common/bspfile.h	(working copy)
@@ -27,7 +27,10 @@
 
 /* upper design bounds */
 
-#define MAX_MAP_HULLS              4
+#define MAX_MAP_HULLS_Q1              4
+#define MAX_MAP_HULLS_H2              8
+#define MAX_MAP_HULLS MAX_MAP_HULLS_H2
+
 #define MAX_MAP_MODELS           256
 #define MAX_MAP_BRUSHES         4096
 #define MAX_MAP_PLANES         16384
@@ -88,11 +91,21 @@
     float mins[3];
     float maxs[3];
     float origin[3];
-    int32_t headnode[MAX_MAP_HULLS];
+    int32_t headnode[MAX_MAP_HULLS_Q1];
     int32_t visleafs;		/* not including the solid leaf 0 */
     int32_t firstface;
     int32_t numfaces;
-} dmodel_t;
+} dmodelq1_t;
+typedef struct {
+    float mins[3];
+    float maxs[3];
+    float origin[3];
+    int32_t headnode[MAX_MAP_HULLS_H2];
+    int32_t visleafs;		/* not including the solid leaf 0 */
+    int32_t firstface;
+    int32_t numfaces;
+} dmodelh2_t;
+typedef dmodelh2_t dmodel_t;
 
 typedef struct {
     int32_t nummiptex;
@@ -418,6 +431,7 @@
 
 typedef struct {
     int32_t version;
+	int hullcount;
     union {
 	bsp29_t bsp29;
 	bsp2rmq_t bsp2rmq;
Index: qbsp/brush.c
===================================================================
--- qbsp/brush.c	(revision 814)
+++ qbsp/brush.c	(working copy)
@@ -838,8 +838,53 @@
 	return NULL;
     }
 
+	if (options.hexen2)
+	{
     if (hullnum == 1) {
 	vec3_t size[2] = { {-16, -16, -32}, {16, 16, 24} };
+			ExpandBrush(&hullbrush, size, facelist);
+			FreeBrushFaces(facelist);
+			facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
+		}
+		else	if (hullnum == 2) {
+			vec3_t size[2] = { {-24, -24, -20}, {24, 24, 20} };
+			ExpandBrush(&hullbrush, size, facelist);
+			FreeBrushFaces(facelist);
+			facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
+		}
+		else	if (hullnum == 3) {
+			vec3_t size[2] = { {-16, -16, -12}, {16, 16, 16} };
+			ExpandBrush(&hullbrush, size, facelist);
+			FreeBrushFaces(facelist);
+			facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
+		}
+		else	if (hullnum == 4) {
+#if 0
+			if (options.hexen2 == 1) { /*original game*/
+				vec3_t size[2] = { {-40, -40, -42}, {40, 40, 42} };
+				ExpandBrush(&hullbrush, size, facelist);
+				FreeBrushFaces(facelist);
+				facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
+			} else
+#endif
+			{	/*mission pack*/
+				vec3_t size[2] = { {-8, -8, -8}, {8, 8, 8} };
+				ExpandBrush(&hullbrush, size, facelist);
+				FreeBrushFaces(facelist);
+				facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
+			}
+		}
+		else	if (hullnum == 5) {
+			vec3_t size[2] = { {-48, -48, -50}, {48, 48, 50} };
+			ExpandBrush(&hullbrush, size, facelist);
+			FreeBrushFaces(facelist);
+			facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
+		}
+	}
+	else
+	{
+		if (hullnum == 1) {
+			vec3_t size[2] = { {-16, -16, -32}, {16, 16, 24} };
 
 	ExpandBrush(&hullbrush, size, facelist);
 	FreeBrushFaces(facelist);
@@ -851,6 +896,7 @@
 	FreeBrushFaces(facelist);
 	facelist = CreateBrushFaces(&hullbrush, rotate_offset, hullnum);
     }
+	}
 
     // create the brush
     brush = AllocMem(BRUSH, 1, true);
Index: qbsp/bspfile.c
===================================================================
--- qbsp/bspfile.c	(revision 814)
+++ qbsp/bspfile.c	(working copy)
@@ -96,12 +96,35 @@
     for (i = 0, entity = map.entities; i < map.numentities; i++, entity++) {
 	entities = &entity->lumps[Type];
 	if (entities->data) {
+			if (Type == LUMP_MODELS && !options.hexen2) {
+				const dmodel_t *in = entities->data;
+				dmodelq1_t out;
+				int j, k;
+				for (j = 0; j < entities->count; j++)
+				{
+					for (k = 0; k < 3; k++) {
+						out.mins[k] = in[j].mins[k];
+						out.maxs[k] = in[j].maxs[k];
+						out.origin[k] = in[j].origin[k];
+					}
+					for (k = 0; k < MAX_MAP_HULLS_Q1; k++)
+						out.headnode[k] = in[j].headnode[k];
+					out.visleafs = in[j].visleafs;
+					out.firstface = in[j].firstface;
+					out.numfaces = in[j].numfaces;
+					ret = fwrite(&out, sizeof(out), 1, f);
+					if (ret != 1)
+						Error("Failure writing to file");
+				}
+				cLen += entities->count * sizeof(out);
+			} else {
 	    ret = fwrite(entities->data, MemSize[Type], entities->count, f);
 	    if (ret != entities->count)
 		Error("Failure writing to file");
 	    cLen += entities->count * MemSize[Type];
 	}
     }
+	}
 
     // Add null terminating char for text
     if (Type == LUMP_ENTITIES) {
Index: qbsp/bspfile.h
===================================================================
--- qbsp/bspfile.h	(revision 814)
+++ qbsp/bspfile.h	(working copy)
@@ -56,12 +56,22 @@
 #define BSP_LUMPS         15
 
 typedef struct {
+#define MAX_MAP_HULLS_Q1 4
     float mins[3], maxs[3];
     float origin[3];
-    int32_t headnode[4];	/* 4 for backward compat, only 3 hulls exist */
+    int32_t headnode[MAX_MAP_HULLS_Q1];	/* 4 for backward compat, only 3 hulls exist */
     int32_t visleafs;		/* not including the solid leaf 0 */
     int32_t firstface, numfaces;
-} dmodel_t;
+} dmodelq1_t;
+typedef struct {
+#define MAX_MAP_HULLS_H2 8
+    float mins[3], maxs[3];
+    float origin[3];
+    int32_t headnode[MAX_MAP_HULLS_H2];	/* hexen2 only uses 6 */
+    int32_t visleafs;		/* not including the solid leaf 0 */
+    int32_t firstface, numfaces;
+} dmodelh2_t;
+typedef dmodelh2_t dmodel_t;
 
 typedef struct {
     int32_t version;
Index: qbsp/qbsp.c
===================================================================
--- qbsp/qbsp.c	(revision 814)
+++ qbsp/qbsp.c	(working copy)
@@ -289,6 +289,13 @@
 
     CreateSingleHull(1);
     CreateSingleHull(2);
+
+	if (options.hexen2)
+	{	/*note: h2mp doesn't use hull 2 automatically, however gamecode can explicitly set ent.hull=3 to access it*/
+		CreateSingleHull(3);
+		CreateSingleHull(4);
+		CreateSingleHull(5);
+	}
 }
 
 
@@ -502,6 +509,8 @@
 		options.fOldleak = true;
 	    else if (!strcasecmp(szTok, "nopercent"))
 		options.fNopercent = true;
+	    else if (!strcasecmp(szTok, "hexen2"))
+	     options.hexen2 = true;
 	    else if (!strcasecmp(szTok, "bsp2")) {
 		options.BSPVersion = BSP2VERSION;
 		MemSize = MemSize_BSP2;
Index: qbsp/qbsp.h
===================================================================
--- qbsp/qbsp.h	(revision 814)
+++ qbsp/qbsp.h	(working copy)
@@ -448,6 +448,7 @@
     bool fNopercent;
     bool forceGoodTree;
     bool fixRotateObjTexture;
+    int hexen2;/*2 if the worldspawn mission pack flag was set*/
     int BSPVersion;
     int dxSubdivide;
     int dxLeakDist;
Index: qbsp/writebsp.c
===================================================================
--- qbsp/writebsp.c	(revision 814)
+++ qbsp/writebsp.c	(working copy)
@@ -235,7 +235,8 @@
 	/* Worth special-casing for entity 0 (no modification needed) */
 	diff = clipcount - model->headnode[1];
 	if (diff != 0) {
-	    model->headnode[1] += diff;
+		for (i = 1; i < hullnum; i++)
+			model->headnode[i] += diff;
 	    if (options.BSPVersion == BSPVERSION) {
 		bsp29_dclipnode_t *clipnode = clipnodes->data;
 		for (i = 0; i < oldcount; i++, clipnode++) {
