diff --git a/src/dehacked.c b/src/dehacked.c
index 61775bd56413113287fddbe2d038f31123072a4c..78120c5c44aefae1072668c99e5c916be2ea0e92 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -5756,10 +5756,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_FANG_PINCHPATHINGSTART1",
 	"S_FANG_PINCHPATHINGSTART2",
 	"S_FANG_PINCHPATHING",
+	"S_FANG_PINCHBOUNCE0",
 	"S_FANG_PINCHBOUNCE1",
 	"S_FANG_PINCHBOUNCE2",
 	"S_FANG_PINCHBOUNCE3",
 	"S_FANG_PINCHBOUNCE4",
+	"S_FANG_PINCHFALL0",
 	"S_FANG_PINCHFALL1",
 	"S_FANG_PINCHFALL2",
 	"S_FANG_PINCHSKID1",
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index b89ffe9e6d595558cad558c5b86d4a8bf924379a..12f03ab94859538ede0a4690a330f144675900f3 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -4402,28 +4402,66 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse
 	numpolyplanes++;
 }
 
+// putting sortindex and sortnode here so the comparator function can see them
+gr_drawnode_t *sortnode;
+size_t *sortindex;
+
+static int CompareDrawNodes(const void *p1, const void *p2)
+{
+	size_t n1 = *(const size_t*)p1;
+	size_t n2 = *(const size_t*)p2;
+	INT32 v1 = 0;
+	INT32 v2 = 0;
+	INT32 diff;
+	if (sortnode[n1].plane)
+		v1 = sortnode[n1].plane->drawcount;
+	else if (sortnode[n1].polyplane)
+		v1 = sortnode[n1].polyplane->drawcount;
+	else if (sortnode[n1].wall)
+		v1 = sortnode[n1].wall->drawcount;
+	else I_Error("CompareDrawNodes: n1 unknown");
+
+	if (sortnode[n2].plane)
+		v2 = sortnode[n2].plane->drawcount;
+	else if (sortnode[n2].polyplane)
+		v2 = sortnode[n2].polyplane->drawcount;
+	else if (sortnode[n2].wall)
+		v2 = sortnode[n2].wall->drawcount;
+	else I_Error("CompareDrawNodes: n2 unknown");
+
+	diff = v2 - v1;
+	if (diff == 0) I_Error("CompareDrawNodes: diff is zero");
+	return diff;
+}
+
+static int CompareDrawNodePlanes(const void *p1, const void *p2)
+{
+	size_t n1 = *(const size_t*)p1;
+	size_t n2 = *(const size_t*)p2;
+	if (!sortnode[n1].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n1)");
+	if (!sortnode[n2].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n2)");
+	return ABS(sortnode[n2].plane->fixedheight - viewz) - ABS(sortnode[n1].plane->fixedheight - viewz);
+}
+
 //
 // HWR_CreateDrawNodes
 // Creates and sorts a list of drawnodes for the scene being rendered.
 static void HWR_CreateDrawNodes(void)
 {
-	UINT32 i = 0, p = 0, prev = 0, loop;
-	const fixed_t pviewz = dup_viewz;
+	UINT32 i = 0, p = 0;
+	size_t run_start = 0;
 
 	// Dump EVERYTHING into a huge drawnode list. Then we'll sort it!
 	// Could this be optimized into _AddTransparentWall/_AddTransparentPlane?
 	// Hell yes! But sort algorithm must be modified to use a linked list.
-	gr_drawnode_t *sortnode = Z_Calloc((sizeof(planeinfo_t)*numplanes)
-									+ (sizeof(polyplaneinfo_t)*numpolyplanes)
-									+ (sizeof(wallinfo_t)*numwalls)
-									,PU_STATIC, NULL);
+	sortnode = Z_Calloc((sizeof(planeinfo_t)*numplanes)
+					+ (sizeof(polyplaneinfo_t)*numpolyplanes)
+					+ (sizeof(wallinfo_t)*numwalls)
+					,PU_STATIC, NULL);
 	// todo:
 	// However, in reality we shouldn't be re-copying and shifting all this information
 	// that is already lying around. This should all be in some sort of linked list or lists.
-	size_t *sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL);
-
-	// If true, swap the draw order.
-	boolean shift = false;
+	sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL);
 	
 	rs_hw_nodesorttime = I_GetTimeMicros();
 
@@ -4449,104 +4487,36 @@ static void HWR_CreateDrawNodes(void)
 
 	// p is the number of stuff to sort
 
-	// Add the 3D floors, thicksides, and masked textures...
-	// Instead of going through drawsegs, we need to iterate
-	// through the lists of masked textures and
-	// translucent ffloors being drawn.
-
-	// This is a bubble sort! Wahoo!
+	// sort the list based on the value of the 'drawcount' member of the drawnodes.
+	qsort(sortindex, p, sizeof(size_t), CompareDrawNodes);
 
-	// Stuff is sorted:
-	//      sortnode[sortindex[0]]   = farthest away
-	//      sortnode[sortindex[p-1]] = closest
-	// "i" should be closer. "prev" should be further.
-	// The lower drawcount is, the further it is from the screen.
-
-	for (loop = 0; loop < p; loop++)
+	// an additional pass is needed to correct the order of consecutive planes in the list.
+	// for each consecutive run of planes in the list, sort that run based on plane height and view height.
+	while (run_start < p-1)// p-1 because a 1 plane run at the end of the list does not count
 	{
-		for (i = 1; i < p; i++)
+		// locate run start
+		if (sortnode[sortindex[run_start]].plane)
 		{
-			prev = i-1;
-			if (sortnode[sortindex[i]].plane)
+			// found it, now look for run end
+			size_t run_end;// (inclusive)
+			for (i = run_start+1; i < p; i++)// size_t and UINT32 being used mixed here... shouldnt break anything though..
 			{
-				// What are we comparing it with?
-				if (sortnode[sortindex[prev]].plane)
-				{
-					// Plane (i) is further away than plane (prev)
-					if (ABS(sortnode[sortindex[i]].plane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].plane->fixedheight - pviewz))
-						shift = true;
-				}
-				if (sortnode[sortindex[prev]].polyplane)
-				{
-					// Plane (i) is further away than polyplane (prev)
-					if (ABS(sortnode[sortindex[i]].plane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].polyplane->fixedheight - pviewz))
-						shift = true;
-				}
-				else if (sortnode[sortindex[prev]].wall)
-				{
-					// Plane (i) is further than wall (prev)
-					if (sortnode[sortindex[i]].plane->drawcount > sortnode[sortindex[prev]].wall->drawcount)
-						shift = true;
-				}
+				if (!sortnode[sortindex[i]].plane) break;
 			}
-			else if (sortnode[sortindex[i]].polyplane)
+			run_end = i-1;
+			if (run_end > run_start)// if there are multiple consecutive planes, not just one
 			{
-				// What are we comparing it with?
-				if (sortnode[sortindex[prev]].plane)
-				{
-					// Plane (i) is further away than plane (prev)
-					if (ABS(sortnode[sortindex[i]].polyplane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].plane->fixedheight - pviewz))
-						shift = true;
-				}
-				if (sortnode[sortindex[prev]].polyplane)
-				{
-					// Plane (i) is further away than polyplane (prev)
-					if (ABS(sortnode[sortindex[i]].polyplane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].polyplane->fixedheight - pviewz))
-						shift = true;
-				}
-				else if (sortnode[sortindex[prev]].wall)
-				{
-					// Plane (i) is further than wall (prev)
-					if (sortnode[sortindex[i]].polyplane->drawcount > sortnode[sortindex[prev]].wall->drawcount)
-						shift = true;
-				}
-			}
-			else if (sortnode[sortindex[i]].wall)
-			{
-				// What are we comparing it with?
-				if (sortnode[sortindex[prev]].plane)
-				{
-					// Wall (i) is further than plane(prev)
-					if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].plane->drawcount)
-						shift = true;
-				}
-				if (sortnode[sortindex[prev]].polyplane)
-				{
-					// Wall (i) is further than polyplane(prev)
-					if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].polyplane->drawcount)
-						shift = true;
-				}
-				else if (sortnode[sortindex[prev]].wall)
-				{
-					// Wall (i) is further than wall (prev)
-					if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].wall->drawcount)
-						shift = true;
-				}
-			}
-
-			if (shift)
-			{
-				size_t temp;
-
-				temp = sortindex[prev];
-				sortindex[prev] = sortindex[i];
-				sortindex[i] = temp;
-
-				shift = false;
+				// consecutive run of planes found, now sort it
+				qsort(sortindex + run_start, run_end - run_start + 1, sizeof(size_t), CompareDrawNodePlanes);
 			}
-
-		} //i++
-	} // loop++
+			run_start = run_end + 1;// continue looking for runs coming right after this one
+		}
+		else
+		{
+			// this wasnt the run start, try next one
+			run_start++;
+		}
+	}
 
 	rs_hw_nodesorttime = I_GetTimeMicros() - rs_hw_nodesorttime;
 	
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 76c7f89b4b61526447d0aa421467d2ccd7c0ed81..68b426f0c7fea5e015f758b474c0b24f8384a898 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -375,7 +375,10 @@ static void md2_loadTexture(md2_t *model)
 #endif
 		grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch);
 		if (grpatch->mipmap->grInfo.format == 0)
+		{
+			model->notexturefile = true; // mark it so its not searched for again repeatedly
 			return;
+		}
 
 		grpatch->mipmap->downloaded = 0;
 		grpatch->mipmap->flags = 0;
@@ -430,6 +433,7 @@ static void md2_loadBlendTexture(md2_t *model)
 		grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch);
 		if (grpatch->mipmap->grInfo.format == 0)
 		{
+			model->noblendfile = true; // mark it so its not searched for again repeatedly
 			Z_Free(filename);
 			return;
 		}
@@ -465,6 +469,8 @@ void HWR_InitModels(void)
 		md2_playermodels[s].scale = -1.0f;
 		md2_playermodels[s].model = NULL;
 		md2_playermodels[s].grpatch = NULL;
+		md2_playermodels[s].notexturefile = false;
+		md2_playermodels[s].noblendfile = false;
 		md2_playermodels[s].skin = -1;
 		md2_playermodels[s].notfound = true;
 		md2_playermodels[s].error = false;
@@ -474,6 +480,8 @@ void HWR_InitModels(void)
 		md2_models[i].scale = -1.0f;
 		md2_models[i].model = NULL;
 		md2_models[i].grpatch = NULL;
+		md2_models[i].notexturefile = false;
+		md2_models[i].noblendfile = false;
 		md2_models[i].skin = -1;
 		md2_models[i].notfound = true;
 		md2_models[i].error = false;
@@ -1298,12 +1306,14 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
 		finalscale = md2->scale;
 		//Hurdler: arf, I don't like that implementation at all... too much crappy
 		gpatch = md2->grpatch;
-		if (!gpatch || !gpatch->mipmap->grInfo.format || !gpatch->mipmap->downloaded)
+		if (!gpatch || ((!gpatch->mipmap->grInfo.format || !gpatch->mipmap->downloaded) && !md2->notexturefile))
 			md2_loadTexture(md2);
 		gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
 
 		if ((gpatch && gpatch->mipmap->grInfo.format) // don't load the blend texture if the base texture isn't available
-			&& (!md2->blendgrpatch || !((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded))
+			&& (!md2->blendgrpatch
+			|| ((!((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded)
+			&& !md2->noblendfile)))
 			md2_loadBlendTexture(md2);
 
 		if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h
index faa91caeee42a2ab47321442663584829685c5db..42a9d7c634d3643fd198372e87b5250d8c5f9068 100644
--- a/src/hardware/hw_md2.h
+++ b/src/hardware/hw_md2.h
@@ -28,7 +28,9 @@ typedef struct
 	float       offset;
 	model_t     *model;
 	void        *grpatch;
+	boolean     notexturefile; // true if texture file was not found
 	void        *blendgrpatch;
+	boolean     noblendfile; // true if blend texture file was not found
 	boolean     notfound;
 	INT32       skin;
 	boolean     error;
diff --git a/src/info.c b/src/info.c
index f0272fc79da8aa54131151664f5e41f278a85d5b..7fa31f0553abc30f478582935768cc22a9044af5 100644
--- a/src/info.c
+++ b/src/info.c
@@ -1430,11 +1430,13 @@ state_t states[NUMSTATES] =
 
 	{SPR_FANG,  8,  0, {A_PrepareRepeat}, 1, 0, S_FANG_PINCHPATHINGSTART2}, // S_FANG_PINCHPATHINGSTART1
 	{SPR_FANG,  8,  0, {A_PlayActiveSound}, 0, 0, S_FANG_PINCHPATHING}, // S_FANG_PINCHPATHINGSTART2
-	{SPR_FANG,  8,  0, {A_Boss5FindWaypoint}, 1, 0, S_FANG_PINCHBOUNCE1}, // S_FANG_PINCHPATHING
+	{SPR_FANG,  8,  0, {A_Boss5FindWaypoint}, 1, 0, S_FANG_PINCHBOUNCE0}, // S_FANG_PINCHPATHING
+	{SPR_FANG,  8,  0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 2, S_FANG_PINCHBOUNCE1}, // S_FANG_PINCHBOUNCE0
 	{SPR_FANG,  8,  2, {A_Thrust}, 0, 1, S_FANG_PINCHBOUNCE2}, // S_FANG_PINCHBOUNCE1
 	{SPR_FANG,  9,  2, {NULL}, 0, 0, S_FANG_PINCHBOUNCE3}, // S_FANG_PINCHBOUNCE2
 	{SPR_FANG, 10,  2, {A_Boss5Jump}, 0, 0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE3
-	{SPR_FANG, 10,  1, {A_Boss5CheckFalling}, S_FANG_PINCHSKID1, S_FANG_PINCHFALL1, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE4
+	{SPR_FANG, 10,  1, {A_Boss5CheckFalling}, S_FANG_PINCHSKID1, S_FANG_PINCHFALL0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE4
+	{SPR_FANG, 12,  0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 1, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL0
 	{SPR_FANG, 12,  1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL2}, // S_FANG_PINCHFALL1
 	{SPR_FANG, 13,  1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL2
 	{SPR_FANG,  4,  0, {A_PlayAttackSound}, 0, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID1
@@ -3362,7 +3364,7 @@ state_t states[NUMSTATES] =
 
 	// CTF Sign
 	{SPR_GFLG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG
-	
+
 	// Finish flag
 	{SPR_FNSF,    FF_TRANS30, -1, {NULL}, 0, 0, S_NULL}, // S_FINISHFLAG
 
@@ -18010,7 +18012,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags
 		S_NULL          // raisestate
 	},
-	
+
 	{           // MT_FINISHFLAG
 		-1,             // doomednum
 		S_FINISHFLAG,   // spawnstate
@@ -19855,7 +19857,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
 		S_NULL          // raisestate
 	},
-	
+
 	{           // MT_FLINGNIGHTSSTAR
 		-1,             // doomednum
 		S_NIGHTSSTAR,   // spawnstate
@@ -21691,7 +21693,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = {
 	{"Violet",     {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT,       6,  V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET
 	{"Lilac",      {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR,      4,  V_ROSYMAP,    true}, // SKINCOLOR_LILAC
 	{"Plum",       {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT,       7,  V_ROSYMAP,    true}, // SKINCOLOR_PLUM
-	{"Raspberry",  {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE,      15, V_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY
+	{"Raspberry",  {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE,      13, V_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY
 	{"Rosy",       {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA,       1,  V_ROSYMAP,    true}, // SKINCOLOR_ROSY
 
 	// super
diff --git a/src/info.h b/src/info.h
index 79af9bbbb8ae444fa3e9aee46cc17ca922bf9d68..476ad2b730d8bcb08afbf32503d4edef06165481 100644
--- a/src/info.h
+++ b/src/info.h
@@ -1608,10 +1608,12 @@ typedef enum state
 	S_FANG_PINCHPATHINGSTART1,
 	S_FANG_PINCHPATHINGSTART2,
 	S_FANG_PINCHPATHING,
+	S_FANG_PINCHBOUNCE0,
 	S_FANG_PINCHBOUNCE1,
 	S_FANG_PINCHBOUNCE2,
 	S_FANG_PINCHBOUNCE3,
 	S_FANG_PINCHBOUNCE4,
+	S_FANG_PINCHFALL0,
 	S_FANG_PINCHFALL1,
 	S_FANG_PINCHFALL2,
 	S_FANG_PINCHSKID1,
@@ -3498,7 +3500,7 @@ typedef enum state
 
 	// Got Flag Sign
 	S_GOTFLAG,
-	
+
 	// Finish flag
 	S_FINISHFLAG,
 
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 578874574d70a97e404e6aead5c4d36c359c9746..a9c1602549b1e30796977c58b7c067d0e3b8c03f 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -5142,12 +5142,10 @@ void A_SignPlayer(mobj_t *actor)
 			;
 		else if (!skin->sprites[SPR2_SIGN].numframes)
 			signcolor = facecolor;
-		else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
+		else if ((facecolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
 			signcolor = skin->prefoppositecolor;
-		else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
-			signcolor = skincolors[actor->target->player->skincolor].invcolor;
-		else
-			signcolor = SKINCOLOR_NONE;
+		else if (facecolor) // Set the sign to be an appropriate background color for this player's skincolor.
+			signcolor = skincolors[facecolor].invcolor;
 	}
 	else if (locvar1 != -3) // set to a defined skin
 	{
@@ -5211,6 +5209,7 @@ void A_SignPlayer(mobj_t *actor)
 			P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
 		if (!signcolor)
 			signcolor = SKINCOLOR_CARBON;
+		facecolor = signcolor;
 	}
 
 	actor->tracer->color = signcolor;
diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c
index 5a086880ab5160f1809a6bc222cb91e6e17dd6e5..ef34b266df277eefe4bbbb8a19c8139fac7b0523 100644
--- a/src/sdl/mixer_sound.c
+++ b/src/sdl/mixer_sound.c
@@ -219,6 +219,28 @@ static void var_cleanup(void)
 
 	internal_volume = 100;
 }
+
+static const char* get_zlib_error(int zErr)
+{
+	switch (zErr)
+	{
+		case Z_ERRNO:
+			return "Z_ERRNO";
+		case Z_STREAM_ERROR:
+			return "Z_STREAM_ERROR";
+		case Z_DATA_ERROR:
+			return "Z_DATA_ERROR";
+		case Z_MEM_ERROR:
+			return "Z_MEM_ERROR";
+		case Z_BUF_ERROR:
+			return "Z_BUF_ERROR";
+		case Z_VERSION_ERROR:
+			return "Z_VERSION_ERROR";
+		default:
+			return "unknown error";
+	}
+}
+
 /// ------------------------
 /// Audio System
 /// ------------------------
@@ -475,7 +497,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
 			zErr = inflate(&stream, Z_FINISH);
 			if (zErr == Z_STREAM_END) {
 				// Run GME on new data
-				if (!gme_open_data(inflatedData, inflatedLen, &emu, 44100))
+				if (!gme_open_data(inflatedData, inflatedLen, &emu, SAMPLERATE))
 				{
 					short *mem;
 					UINT32 len;
@@ -498,58 +520,18 @@ void *I_GetSfx(sfxinfo_t *sfx)
 				}
 			}
 			else
-			{
-				const char *errorType;
-				switch (zErr)
-				{
-					case Z_ERRNO:
-						errorType = "Z_ERRNO"; break;
-					case Z_STREAM_ERROR:
-						errorType = "Z_STREAM_ERROR"; break;
-					case Z_DATA_ERROR:
-						errorType = "Z_DATA_ERROR"; break;
-					case Z_MEM_ERROR:
-						errorType = "Z_MEM_ERROR"; break;
-					case Z_BUF_ERROR:
-						errorType = "Z_BUF_ERROR"; break;
-					case Z_VERSION_ERROR:
-						errorType = "Z_VERSION_ERROR"; break;
-					default:
-						errorType = "unknown error";
-				}
-				CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
-			}
+				CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg);
 			(void)inflateEnd(&stream);
 		}
 		else // Hold up, zlib's got a problem
-		{
-			const char *errorType;
-			switch (zErr)
-			{
-				case Z_ERRNO:
-					errorType = "Z_ERRNO"; break;
-				case Z_STREAM_ERROR:
-					errorType = "Z_STREAM_ERROR"; break;
-				case Z_DATA_ERROR:
-					errorType = "Z_DATA_ERROR"; break;
-				case Z_MEM_ERROR:
-					errorType = "Z_MEM_ERROR"; break;
-				case Z_BUF_ERROR:
-					errorType = "Z_BUF_ERROR"; break;
-				case Z_VERSION_ERROR:
-					errorType = "Z_VERSION_ERROR"; break;
-				default:
-					errorType = "unknown error";
-			}
-			CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
-		}
+			CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg);
 		Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
 #else
 		return NULL; // No zlib support
 #endif
 	}
 	// Try to read it as a GME sound
-	else if (!gme_open_data(lump, sfx->length, &emu, 44100))
+	else if (!gme_open_data(lump, sfx->length, &emu, SAMPLERATE))
 	{
 		short *mem;
 		UINT32 len;
@@ -1175,77 +1157,30 @@ boolean I_LoadSong(char *data, size_t len)
 		if (zErr == Z_OK) // We're good to go
 		{
 			zErr = inflate(&stream, Z_FINISH);
-			if (zErr == Z_STREAM_END) {
+			if (zErr == Z_STREAM_END)
+			{
 				// Run GME on new data
-				if (!gme_open_data(inflatedData, inflatedLen, &gme, 44100))
+				if (!gme_open_data(inflatedData, inflatedLen, &gme, SAMPLERATE))
 				{
-					gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
-					gme_start_track(gme, 0);
-					current_track = 0;
-					gme_set_equalizer(gme, &eq);
-					Mix_HookMusic(mix_gme, gme);
 					Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around
 					return true;
 				}
 			}
 			else
-			{
-				const char *errorType;
-				switch (zErr)
-				{
-					case Z_ERRNO:
-						errorType = "Z_ERRNO"; break;
-					case Z_STREAM_ERROR:
-						errorType = "Z_STREAM_ERROR"; break;
-					case Z_DATA_ERROR:
-						errorType = "Z_DATA_ERROR"; break;
-					case Z_MEM_ERROR:
-						errorType = "Z_MEM_ERROR"; break;
-					case Z_BUF_ERROR:
-						errorType = "Z_BUF_ERROR"; break;
-					case Z_VERSION_ERROR:
-						errorType = "Z_VERSION_ERROR"; break;
-					default:
-						errorType = "unknown error";
-				}
-				CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
-			}
+				CONS_Alert(CONS_ERROR, "Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg);
 			(void)inflateEnd(&stream);
 		}
 		else // Hold up, zlib's got a problem
-		{
-			const char *errorType;
-			switch (zErr)
-			{
-				case Z_ERRNO:
-					errorType = "Z_ERRNO"; break;
-				case Z_STREAM_ERROR:
-					errorType = "Z_STREAM_ERROR"; break;
-				case Z_DATA_ERROR:
-					errorType = "Z_DATA_ERROR"; break;
-				case Z_MEM_ERROR:
-					errorType = "Z_MEM_ERROR"; break;
-				case Z_BUF_ERROR:
-					errorType = "Z_BUF_ERROR"; break;
-				case Z_VERSION_ERROR:
-					errorType = "Z_VERSION_ERROR"; break;
-				default:
-					errorType = "unknown error";
-			}
-			CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
-		}
+			CONS_Alert(CONS_ERROR, "Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg);
 		Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
+		return false;
 #else
-		CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n");
-		return true;
+		CONS_Alert(CONS_ERROR, "Cannot decompress VGZ; no zlib support\n");
+		return false;
 #endif
 	}
-	else if (!gme_open_data(data, len, &gme, 44100))
-	{
-		gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
-		gme_set_equalizer(gme, &eq);
+	else if (!gme_open_data(data, len, &gme, SAMPLERATE))
 		return true;
-	}
 #endif
 
 #ifdef HAVE_MIXERX
@@ -1360,6 +1295,8 @@ boolean I_PlaySong(boolean looping)
 #ifdef HAVE_LIBGME
 	if (gme)
 	{
+		gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
+		gme_set_equalizer(gme, &eq);
 		gme_start_track(gme, 0);
 		current_track = 0;
 		Mix_HookMusic(mix_gme, gme);