diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c
index b74f949a5daccc64e71f32f3876b99374ec9248a..f6b700f2859a29dfe058a9e823c5b683b8a19620 100644
--- a/src/hardware/hw_cache.c
+++ b/src/hardware/hw_cache.c
@@ -924,29 +924,6 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
 	return grtex;
 }
 
-// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch.
-lumpnum_t gr_patchflat;
-
-static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
-{
-	UINT8 *flat;
-	patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC);
-#ifndef NO_PNG_LUMPS
-	size_t lumplength = W_LumpLength(flatlumpnum);
-
-	if (R_IsLumpPNG((UINT8 *)patch, lumplength))
-		patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL, false);
-#endif
-
-	grMipmap->width  = (UINT16)SHORT(patch->width);
-	grMipmap->height = (UINT16)SHORT(patch->height);
-
-	flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data);
-	memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height);
-
-	R_PatchToFlat(patch, flat);
-}
-
 static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
 {
 	size_t size, pflatsize;
@@ -987,40 +964,15 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
 			break;
 	}
 
-	if (R_CheckIfPatch(flatlumpnum))
-		HWR_LoadPatchFlat(grMipmap, flatlumpnum);
-	else
-	{
-		grMipmap->width  = (UINT16)pflatsize;
-		grMipmap->height = (UINT16)pflatsize;
-
-		// the flat raw data needn't be converted with palettized textures
-		W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
-			PU_HWRCACHE, &grMipmap->grInfo.data));
-	}
-}
-
-// Download a Doom 'flat' to the hardware cache and make it ready for use
-void HWR_GetFlat(lumpnum_t flatlumpnum)
-{
-	GLMipmap_t *grmip;
-
-	grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
-
-	if (!grmip->downloaded && !grmip->grInfo.data)
-		HWR_CacheFlat(grmip, flatlumpnum);
-
-	HWD.pfnSetTexture(grmip);
-
-	// The system-memory data can be purged now.
-	Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
+	grMipmap->width  = (UINT16)pflatsize;
+	grMipmap->height = (UINT16)pflatsize;
 
-	gr_patchflat = 0;
-	if (R_CheckIfPatch(flatlumpnum))
-		gr_patchflat = flatlumpnum;
+	// the flat raw data needn't be converted with palettized textures
+	W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
+		PU_HWRCACHE, &grMipmap->grInfo.data));
 }
 
-static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
+static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
 {
 	UINT8 *flat;
 
@@ -1042,24 +994,53 @@ static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
 	R_TextureToFlat(texturenum, flat);
 }
 
-void HWR_GetTextureFlat(INT32 texturenum)
+// Download a Doom 'flat' to the hardware cache and make it ready for use
+void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum)
 {
-	GLTexture_t *grtex;
-#ifdef PARANOIA
-	if ((unsigned)texturenum >= gr_numtextures)
-		I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n");
-#endif
-	if (texturenum == 0 || texturenum == -1)
+	GLMipmap_t *grmip;
+	if (flatlumpnum == LUMPERROR)
 		return;
-	grtex = &gr_textures2[texturenum];
 
-	if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
-		HWR_LoadTextureFlat(&grtex->mipmap, texturenum);
+	grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
+	if (!grmip->downloaded && !grmip->grInfo.data)
+		HWR_CacheFlat(grmip, flatlumpnum);
 
-	HWD.pfnSetTexture(&grtex->mipmap);
+	HWD.pfnSetTexture(grmip);
 
 	// The system-memory data can be purged now.
-	Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
+	Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
+}
+
+void HWR_GetLevelFlat(levelflat_t *levelflat)
+{
+	// Who knows?
+	if (levelflat == NULL)
+		return;
+
+	if (levelflat->type == LEVELFLAT_FLAT)
+		HWR_LiterallyGetFlat(levelflat->u.flat.lumpnum);
+	else if (levelflat->type == LEVELFLAT_TEXTURE)
+	{
+		GLTexture_t *grtex;
+		INT32 texturenum = levelflat->u.texture.num;
+#ifdef PARANOIA
+		if ((unsigned)texturenum >= gr_numtextures)
+			I_Error("HWR_GetLevelFlat: texturenum >= numtextures\n");
+#endif
+		if (texturenum == 0 || texturenum == -1)
+			return;
+		grtex = &gr_textures2[texturenum];
+
+		if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
+			HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum);
+
+		HWD.pfnSetTexture(&grtex->mipmap);
+
+		// The system-memory data can be purged now.
+		Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
+	}
+	else // set no texture
+		HWD.pfnSetTexture(NULL);
 }
 
 //
diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c
index d9e688c0aaa5d8745754c662f50472b621ae47ba..3b0620cc134c96c480aade16dce049e4d443e71c 100644
--- a/src/hardware/hw_draw.c
+++ b/src/hardware/hw_draw.c
@@ -647,7 +647,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
 	v[0].tow = v[1].tow = (float)((y & flatflag)/dflatsize);
 	v[2].tow = v[3].tow = (float)(v[0].tow + h/dflatsize);
 
-	HWR_GetFlat(flatlumpnum);
+	HWR_LiterallyGetFlat(flatlumpnum);
 
 	//Hurdler: Boris, the same comment as above... but maybe for pics
 	// it not a problem since they don't have any transparent pixel
diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h
index c7b06edfd1f1455e5d399a0a51e58771fce88786..72365013d2d2e866439cc90b453c828617db1172 100644
--- a/src/hardware/hw_glob.h
+++ b/src/hardware/hw_glob.h
@@ -23,6 +23,7 @@
 #include "hw_defs.h"
 #include "hw_main.h"
 #include "../m_misc.h"
+#include "../p_setup.h"
 
 // the original aspect ratio of Doom graphics isn't square
 #define ORIGINAL_ASPECT (320.0f/200.0f)
@@ -100,8 +101,8 @@ void HWR_InitTextureCache(void);
 void HWR_FreeTextureCache(void);
 void HWR_FreeExtraSubsectors(void);
 
-void HWR_GetFlat(lumpnum_t flatlumpnum);
-void HWR_GetTextureFlat(INT32 texturenum);
+void HWR_GetLevelFlat(levelflat_t *levelflat);
+void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum);
 GLTexture_t *HWR_GetTexture(INT32 tex);
 void HWR_GetPatch(GLPatch_t *gpatch);
 void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap);
@@ -115,8 +116,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
 // --------
 // hw_draw.c
 // --------
-extern lumpnum_t gr_patchflat;
-
 extern float gr_patch_scalex;
 extern float gr_patch_scaley;
 
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 4b4011eeaa73a0c7e9c61001472d129e04585ad0..a337fbfe05f64ae02cbc94cf82e1b5c8af128d09 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -70,12 +70,12 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
 #endif
 
 #ifdef SORTING
-void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
+void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
                              INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
-void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
+void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
                              INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap);
 #else
-static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight,
+static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub, fixed_t fixedheight,
                            INT32 lightlevel, INT32 alpha, sector_t *FOFSector);
 static void HWR_Render3DWater(void);
 static void HWR_RenderTransparentWalls(void);
@@ -522,7 +522,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c
 // HWR_RenderPlane  : Render a floor or ceiling convex polygon
 // -----------------+
 static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
-                           FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
+                           FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
 {
 	polyvertex_t *  pv;
 	float           height; //constant y for all points on the convex flat polygon
@@ -530,9 +530,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 	INT32             nrPlaneVerts;   //verts original define of convex flat polygon
 	INT32             i;
 	float           flatxref,flatyref;
-	float fflatwidth, fflatheight;
-	INT32 flatflag;
-	boolean texflat = true;
+	float fflatwidth = 64.0f, fflatheight = 64.0f;
+	INT32 flatflag = 63;
+	boolean texflat = false;
 	size_t len;
 	float scrollx = 0.0f, scrolly = 0.0f;
 	angle_t angle = 0;
@@ -541,7 +541,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 #ifdef ESLOPE
 	pslope_t *slope = NULL;
 #endif
-	patch_t *patch;
 
 	static FOutVector *planeVerts = NULL;
 	static UINT16 numAllocedPlaneVerts = 0;
@@ -597,48 +596,49 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 		Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
 	}
 
-	len = W_LumpLength(lumpnum);
-
-	switch (len)
+	// set texture for polygon
+	if (levelflat != NULL)
 	{
-		case 4194304: // 2048x2048 lump
-			fflatwidth = fflatheight = 2048.0f;
-			break;
-		case 1048576: // 1024x1024 lump
-			fflatwidth = fflatheight = 1024.0f;
-			break;
-		case 262144:// 512x512 lump
-			fflatwidth = fflatheight = 512.0f;
-			break;
-		case 65536: // 256x256 lump
-			fflatwidth = fflatheight = 256.0f;
-			break;
-		case 16384: // 128x128 lump
-			fflatwidth = fflatheight = 128.0f;
-			break;
-		case 1024: // 32x32 lump
-			fflatwidth = fflatheight = 32.0f;
-			break;
-		default: // 64x64 lump
-			fflatwidth = fflatheight = 64.0f;
-			break;
-	}
+		if (levelflat->type == LEVELFLAT_TEXTURE)
+		{
+			fflatwidth = textures[levelflat->u.texture.num]->width;
+			fflatheight = textures[levelflat->u.texture.num]->height;
+			texflat = true;
+		}
+		else if (levelflat->type == LEVELFLAT_FLAT)
+		{
+			len = W_LumpLength(levelflat->u.flat.lumpnum);
 
-	flatflag = ((INT32)fflatwidth)-1;
+			switch (len)
+			{
+				case 4194304: // 2048x2048 lump
+					fflatwidth = fflatheight = 2048.0f;
+					break;
+				case 1048576: // 1024x1024 lump
+					fflatwidth = fflatheight = 1024.0f;
+					break;
+				case 262144:// 512x512 lump
+					fflatwidth = fflatheight = 512.0f;
+					break;
+				case 65536: // 256x256 lump
+					fflatwidth = fflatheight = 256.0f;
+					break;
+				case 16384: // 128x128 lump
+					fflatwidth = fflatheight = 128.0f;
+					break;
+				case 1024: // 32x32 lump
+					fflatwidth = fflatheight = 32.0f;
+					break;
+				default: // 64x64 lump
+					fflatwidth = fflatheight = 64.0f;
+					break;
+			}
 
-	if (texturenum != 0 && texturenum != -1)
-	{
-		fflatwidth = textures[texturenum]->width;
-		fflatheight = textures[texturenum]->height;
-	}
-	else if (gr_patchflat && R_CheckIfPatch(gr_patchflat))		// Just in case?
-	{
-		patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
-		fflatwidth = SHORT(patch->width);
-		fflatheight = SHORT(patch->height);
+			flatflag = ((INT32)fflatwidth)-1;
+		}
 	}
-	else
-		texflat = false;
+	else // set no texture
+		HWD.pfnSetTexture(NULL);
 
 	// reference point for flat texture coord for each vertex around the polygon
 	flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth);
@@ -3183,23 +3183,22 @@ static inline void HWR_AddPolyObjectSegs(void)
 
 #ifdef POLYOBJECTS_PLANES
 static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
-									FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector,
+									FBITFIELD blendmode, UINT8 lightlevel, levelflat_t *levelflat, sector_t *FOFsector,
 									UINT8 alpha, extracolormap_t *planecolormap)
 {
 	float           height; //constant y for all points on the convex flat polygon
 	FOutVector      *v3d;
 	INT32             i;
 	float           flatxref,flatyref;
-	float fflatwidth, fflatheight;
-	INT32 flatflag;
-	boolean texflat = true;
+	float fflatwidth = 64.0f, fflatheight = 64.0f;
+	INT32 flatflag = 63;
+	boolean texflat = false;
 	size_t len;
 	float scrollx = 0.0f, scrolly = 0.0f;
 	angle_t angle = 0;
 	FSurfaceInfo    Surf;
 	fixed_t tempxsow, tempytow;
 	size_t nrPlaneVerts;
-	patch_t *patch;
 
 	static FOutVector *planeVerts = NULL;
 	static UINT16 numAllocedPlaneVerts = 0;
@@ -3225,48 +3224,49 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
 		Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
 	}
 
-	len = W_LumpLength(lumpnum);
-
-	switch (len)
+	// set texture for polygon
+	if (levelflat != NULL)
 	{
-		case 4194304: // 2048x2048 lump
-			fflatwidth = fflatheight = 2048.0f;
-			break;
-		case 1048576: // 1024x1024 lump
-			fflatwidth = fflatheight = 1024.0f;
-			break;
-		case 262144:// 512x512 lump
-			fflatwidth = fflatheight = 512.0f;
-			break;
-		case 65536: // 256x256 lump
-			fflatwidth = fflatheight = 256.0f;
-			break;
-		case 16384: // 128x128 lump
-			fflatwidth = fflatheight = 128.0f;
-			break;
-		case 1024: // 32x32 lump
-			fflatwidth = fflatheight = 32.0f;
-			break;
-		default: // 64x64 lump
-			fflatwidth = fflatheight = 64.0f;
-			break;
-	}
+		if (levelflat->type == LEVELFLAT_TEXTURE)
+		{
+			fflatwidth = textures[levelflat->u.texture.num]->width;
+			fflatheight = textures[levelflat->u.texture.num]->height;
+			texflat = true;
+		}
+		else if (levelflat->type == LEVELFLAT_FLAT)
+		{
+			len = W_LumpLength(levelflat->u.flat.lumpnum);
 
-	flatflag = ((INT32)fflatwidth)-1;
+			switch (len)
+			{
+				case 4194304: // 2048x2048 lump
+					fflatwidth = fflatheight = 2048.0f;
+					break;
+				case 1048576: // 1024x1024 lump
+					fflatwidth = fflatheight = 1024.0f;
+					break;
+				case 262144:// 512x512 lump
+					fflatwidth = fflatheight = 512.0f;
+					break;
+				case 65536: // 256x256 lump
+					fflatwidth = fflatheight = 256.0f;
+					break;
+				case 16384: // 128x128 lump
+					fflatwidth = fflatheight = 128.0f;
+					break;
+				case 1024: // 32x32 lump
+					fflatwidth = fflatheight = 32.0f;
+					break;
+				default: // 64x64 lump
+					fflatwidth = fflatheight = 64.0f;
+					break;
+			}
 
-	if (texturenum != 0 && texturenum != -1)
-	{
-		fflatwidth = textures[texturenum]->width;
-		fflatheight = textures[texturenum]->height;
-	}
-	else if (gr_patchflat && R_CheckIfPatch(gr_patchflat))		// Just in case?
-	{
-		patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
-		fflatwidth = SHORT(patch->width);
-		fflatheight = SHORT(patch->height);
+			flatflag = ((INT32)fflatwidth)-1;
+		}
 	}
-	else
-		texflat = false;
+	else // set no texture
+		HWD.pfnSetTexture(NULL);
 
 	// reference point for flat texture coord for each vertex around the polygon
 	flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth);
@@ -3400,15 +3400,14 @@ static void HWR_AddPolyObjectPlanes(void)
 				FBITFIELD blendmode;
 				memset(&Surf, 0x00, sizeof(Surf));
 				blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
-				HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], false, polyobjsector->floorheight,
+				HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->floorpic], po_ptrs[i], false, polyobjsector->floorheight,
 													(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
 			}
 			else
 			{
-				HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum);
-				HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum);
+				HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic]);
 				HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude,
-										(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
+										(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic],
 										polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
 			}
 		}
@@ -3424,15 +3423,14 @@ static void HWR_AddPolyObjectPlanes(void)
 				FBITFIELD blendmode;
 				memset(&Surf, 0x00, sizeof(Surf));
 				blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
-				HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], true, polyobjsector->ceilingheight,
+				HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->ceilingpic], po_ptrs[i], true, polyobjsector->ceilingheight,
 				                                  (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
 			}
 			else
 			{
-				HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum);
-				HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum);
+				HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic]);
 				HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude,
-				                          (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
+				                          (light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic],
 				                          polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
 			}
 		}
@@ -3583,13 +3581,12 @@ static void HWR_Subsector(size_t num)
 		{
 			if (sub->validcount != validcount)
 			{
-				HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum);
-				HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum);
+				HWR_GetLevelFlat(&levelflats[gr_frontsector->floorpic]);
 				HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false,
 					// Hack to make things continue to work around slopes.
 					locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight,
 					// We now return you to your regularly scheduled rendering.
-					PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap);
+					PF_Occlude, floorlightlevel, &levelflats[gr_frontsector->floorpic], NULL, 255, false, floorcolormap);
 			}
 		}
 		else
@@ -3606,13 +3603,12 @@ static void HWR_Subsector(size_t num)
 		{
 			if (sub->validcount != validcount)
 			{
-				HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum);
-				HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum);
+				HWR_GetLevelFlat(&levelflats[gr_frontsector->ceilingpic]);
 				HWR_RenderPlane(NULL, &extrasubsectors[num], true,
 					// Hack to make things continue to work around slopes.
 					locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight,
 					// We now return you to your regularly scheduled rendering.
-					PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap);
+					PF_Occlude, ceilinglightlevel, &levelflats[gr_frontsector->ceilingpic], NULL, 255, false, ceilingcolormap);
 			}
 		}
 		else
@@ -3671,7 +3667,7 @@ static void HWR_Subsector(size_t num)
 					else
 						alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
 
-					HWR_AddTransparentFloor(0, 0,
+					HWR_AddTransparentFloor(NULL,
 					                       &extrasubsectors[num],
 										   false,
 					                       *rover->bottomheight,
@@ -3683,14 +3679,13 @@ static void HWR_Subsector(size_t num)
 				{
 					light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
 #ifndef SORTING
-					HWR_Add3DWater(levelflats[*rover->bottompic].lumpnum,
+					HWR_Add3DWater(&levelflats[*rover->bottompic],
 					               &extrasubsectors[num],
 					               *rover->bottomheight,
 					               *gr_frontsector->lightlist[light].lightlevel,
 					               rover->alpha-1, rover->master->frontsector);
 #else
-					HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum,
-											levelflats[*rover->bottompic].texturenum,
+					HWR_AddTransparentFloor(&levelflats[*rover->bottompic],
 					                       &extrasubsectors[num],
 										   false,
 					                       *rover->bottomheight,
@@ -3701,10 +3696,9 @@ static void HWR_Subsector(size_t num)
 				}
 				else
 				{
-					HWR_GetFlat(levelflats[*rover->bottompic].lumpnum);
-					HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum);
+					HWR_GetLevelFlat(&levelflats[*rover->bottompic]);
 					light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
-					HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum,
+					HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
 					                rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
 				}
 			}
@@ -3736,7 +3730,7 @@ static void HWR_Subsector(size_t num)
 					else
 						alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
 
-					HWR_AddTransparentFloor(0, 0,
+					HWR_AddTransparentFloor(NULL,
 					                       &extrasubsectors[num],
 										   true,
 					                       *rover->topheight,
@@ -3748,14 +3742,13 @@ static void HWR_Subsector(size_t num)
 				{
 					light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
 #ifndef SORTING
-					HWR_Add3DWater(levelflats[*rover->toppic].lumpnum,
+					HWR_Add3DWater(&levelflats[*rover->toppic],
 					                          &extrasubsectors[num],
 					                          *rover->topheight,
 					                          *gr_frontsector->lightlist[light].lightlevel,
 					                          rover->alpha-1, rover->master->frontsector);
 #else
-					HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum,
-											levelflats[*rover->bottompic].texturenum,
+					HWR_AddTransparentFloor(&levelflats[*rover->toppic],
 					                        &extrasubsectors[num],
 											true,
 					                        *rover->topheight,
@@ -3767,10 +3760,9 @@ static void HWR_Subsector(size_t num)
 				}
 				else
 				{
-					HWR_GetFlat(levelflats[*rover->toppic].lumpnum);
-					HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum);
+					HWR_GetLevelFlat(&levelflats[*rover->toppic]);
 					light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
-					HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum,
+					HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
 					                  rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
 				}
 			}
@@ -5098,8 +5090,7 @@ typedef struct
 	boolean isceiling;
 	fixed_t fixedheight;
 	INT32 lightlevel;
-	lumpnum_t lumpnum;
-	INT32 texturenum;
+	levelflat_t *levelflat;
 	INT32 alpha;
 	sector_t *FOFSector;
 	FBITFIELD blend;
@@ -5117,8 +5108,7 @@ typedef struct
 	boolean isceiling;
 	fixed_t fixedheight;
 	INT32 lightlevel;
-	lumpnum_t lumpnum;
-	INT32 texturenum;
+	levelflat_t *levelflat;
 	INT32 alpha;
 	sector_t *FOFSector;
 	FBITFIELD blend;
@@ -5149,7 +5139,7 @@ static INT32 drawcount = 0;
 #define MAX_TRANSPARENTFLOOR 512
 
 // This will likely turn into a copy of HWR_Add3DWater and replace it.
-void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling,
+void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling,
 	fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap)
 {
 	static size_t allocedplanes = 0;
@@ -5167,8 +5157,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector
 	planeinfo[numplanes].isceiling = isceiling;
 	planeinfo[numplanes].fixedheight = fixedheight;
 	planeinfo[numplanes].lightlevel = lightlevel;
-	planeinfo[numplanes].lumpnum = lumpnum;
-	planeinfo[numplanes].texturenum = texturenum;
+	planeinfo[numplanes].levelflat = levelflat;
 	planeinfo[numplanes].xsub = xsub;
 	planeinfo[numplanes].alpha = alpha;
 	planeinfo[numplanes].FOFSector = FOFSector;
@@ -5182,7 +5171,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector
 
 // Adding this for now until I can create extrasubsector info for polyobjects
 // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane
-void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling,
+void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling,
 	fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap)
 {
 	static size_t allocedpolyplanes = 0;
@@ -5200,8 +5189,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, poly
 	polyplaneinfo[numpolyplanes].isceiling = isceiling;
 	polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
 	polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
-	polyplaneinfo[numpolyplanes].lumpnum = lumpnum;
-	polyplaneinfo[numpolyplanes].texturenum = texturenum;
+	polyplaneinfo[numpolyplanes].levelflat = levelflat;
 	polyplaneinfo[numpolyplanes].polysector = polysector;
 	polyplaneinfo[numpolyplanes].alpha = alpha;
 	polyplaneinfo[numpolyplanes].FOFSector = FOFSector;
@@ -5363,12 +5351,9 @@ static void HWR_CreateDrawNodes(void)
 			gr_frontsector = NULL;
 
 			if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture))
-			{
-				HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum);
-				HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum);
-			}
+				HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat);
 			HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel,
-				sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
+				sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
 		}
 		else if (sortnode[sortindex[i]].polyplane)
 		{
@@ -5376,12 +5361,9 @@ static void HWR_CreateDrawNodes(void)
 			gr_frontsector = NULL;
 
 			if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture))
-			{
-				HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum);
-				HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum);
-			}
+				HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat);
 			HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel,
-				sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
+				sortnode[sortindex[i]].polyplane->levelflat, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
 		}
 		else if (sortnode[sortindex[i]].wall)
 		{
@@ -6669,10 +6651,11 @@ void transform(float *cx, float *cy, float *cz)
 
 
 //Hurdler: 3D Water stuff
+#ifndef SORTING
+
 #define MAX_3DWATER 512
 
-#ifndef SORTING
-static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub,
+static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub,
 	fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector)
 {
 	static size_t allocedplanes = 0;
@@ -6688,17 +6671,15 @@ static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub,
 	}
 	planeinfo[numfloors].fixedheight = fixedheight;
 	planeinfo[numfloors].lightlevel = lightlevel;
-	planeinfo[numfloors].lumpnum = lumpnum;
+	planeinfo[numfloors].levelflat = levelflat;
 	planeinfo[numfloors].xsub = xsub;
 	planeinfo[numfloors].alpha = alpha;
 	planeinfo[numfloors].FOFSector = FOFSector;
 	numfloors++;
 }
-#endif
 
 #define DIST_PLANE(i) ABS(planeinfo[(i)].fixedheight-dup_viewz)
 
-#if 0
 static void HWR_QuickSortPlane(INT32 start, INT32 finish)
 {
 	INT32 left = start;
@@ -6728,9 +6709,7 @@ static void HWR_QuickSortPlane(INT32 start, INT32 finish)
 	if (start < right) HWR_QuickSortPlane(start, right);
 	if (left < finish) HWR_QuickSortPlane(left, finish);
 }
-#endif
 
-#ifndef SORTING
 static void HWR_Render3DWater(void)
 {
 	size_t i;
@@ -6761,8 +6740,8 @@ static void HWR_Render3DWater(void)
 	gr_frontsector = NULL; //Hurdler: gr_fronsector is no longer valid
 	for (i = 0; i < numfloors; i++)
 	{
-		HWR_GetFlat(planeinfo[i].lumpnum);
-		HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].lumpnum,
+		HWR_GetLevelFlat(planeinfo[i].levelflat);
+		HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].levelflat,
 			planeinfo[i].FOFSector, planeinfo[i].alpha, planeinfo[i].fogplane, planeinfo[i].planecolormap);
 	}
 	numfloors = 0;
@@ -6795,6 +6774,7 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, I
 	wallinfo[numwalls].wallcolormap = wallcolormap;
 	numwalls++;
 }
+
 #ifndef SORTING
 static void HWR_RenderTransparentWalls(void)
 {
@@ -6827,6 +6807,7 @@ static void HWR_RenderTransparentWalls(void)
 	numwalls = 0;
 }
 #endif
+
 static void HWR_RenderWall(wallVert3D   *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap)
 {
 	FOutVector  trVerts[4];
diff --git a/src/p_setup.c b/src/p_setup.c
index cef17663635907eaa19feb77a40a33b22a636dc5..2c5305499a09e697ae3176723fdc6e77e0bdc67c 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -546,52 +546,118 @@ size_t P_PrecacheLevelFlats(void)
 	//SoM: 4/18/2000: New flat code to make use of levelflats.
 	for (i = 0; i < numlevelflats; i++)
 	{
-		lump = levelflats[i].lumpnum;
-		if (devparm)
-			flatmemory += W_LumpLength(lump);
-		R_GetFlat(lump);
+		if (levelflats[i].type == LEVELFLAT_FLAT)
+		{
+			lump = levelflats[i].u.flat.lumpnum;
+			if (devparm)
+				flatmemory += W_LumpLength(lump);
+			R_GetFlat(lump);
+		}
 	}
 	return flatmemory;
 }
 
-// Auxiliary function. Find a flat in the active wad files,
-// allocate an id for it, and set the levelflat (to speedup search)
-INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
+/*
+levelflat refers to an array of level flats,
+or NULL if we want to allocate it now.
+*/
+static INT32
+Ploadflat (levelflat_t *levelflat, const char *flatname)
 {
-	size_t i;
-
-	// Scan through the already found flats, break if it matches.
-	for (i = 0; i < numlevelflats; i++, levelflat++)
-		if (strnicmp(levelflat->name, flatname, 8) == 0)
-			break;
+	UINT8         buffer[8];
 
-	// If there is no match, make room for a new flat.
-	if (i == numlevelflats)
-	{
-		// Store the name.
-		strlcpy(levelflat->name, flatname, sizeof (levelflat->name));
-		strupr(levelflat->name);
+	lumpnum_t    flatnum;
+	int       texturenum;
 
-		// store the flat lump number
-		levelflat->lumpnum = R_GetFlatNumForName(flatname);
-		levelflat->texturenum = R_CheckTextureNumForName(flatname);
-		levelflat->lasttexturenum = levelflat->texturenum;
+	size_t i;
 
-		levelflat->baselumpnum = LUMPERROR;
-		levelflat->basetexturenum = -1;
+	if (levelflat)
+	{
+		// Scan through the already found flats, return if it matches.
+		for (i = 0; i < numlevelflats; i++)
+		{
+			if (strnicmp(levelflat[i].name, flatname, 8) == 0)
+				return i;
+		}
+	}
 
 #ifndef ZDEBUG
-		CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
+	CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
 #endif
 
-		numlevelflats++;
+	if (numlevelflats >= MAXLEVELFLATS)
+		I_Error("Too many flats in level\n");
 
-		if (numlevelflats >= MAXLEVELFLATS)
-			I_Error("Too many flats in level\n");
+	if (levelflat)
+		levelflat += numlevelflats;
+	else
+	{
+		// allocate new flat memory
+		levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL);
+		levelflat  = levelflats + numlevelflats;
 	}
 
-	// level flat id
-	return (INT32)i;
+	// Store the name.
+	strlcpy(levelflat->name, flatname, sizeof (levelflat->name));
+	strupr(levelflat->name);
+
+	/* If we can't find a flat, try looking for a texture! */
+	if (( flatnum = R_GetFlatNumForName(flatname) ) == LUMPERROR)
+	{
+		if (( texturenum = R_CheckTextureNumForName(flatname) ) == -1)
+		{
+			// check for REDWALL
+			if (( texturenum = R_CheckTextureNumForName("REDWALL") ) != -1)
+				goto texturefound;
+			// check for REDFLR
+			else if (( flatnum = R_GetFlatNumForName("REDFLR") ) != LUMPERROR)
+				goto flatfound;
+			// nevermind
+			levelflat->type = LEVELFLAT_NONE;
+		}
+		else
+		{
+texturefound:
+			levelflat->type = LEVELFLAT_TEXTURE;
+			levelflat->u.texture.    num = texturenum;
+			levelflat->u.texture.lastnum = texturenum;
+			/* start out unanimated */
+			levelflat->u.texture.basenum = -1;
+		}
+	}
+	else
+	{
+flatfound:
+		/* This could be a flat, patch, or PNG. */
+		if (R_CheckIfPatch(flatnum))
+			levelflat->type = LEVELFLAT_PATCH;
+		else
+		{
+#ifndef NO_PNG_LUMPS
+			/*
+			Only need eight bytes for PNG headers.
+			FIXME: Put this elsewhere.
+			*/
+			W_ReadLumpHeader(flatnum, buffer, 8, 0);
+			if (R_IsLumpPNG(buffer, W_LumpLength(flatnum)))
+				levelflat->type = LEVELFLAT_PNG;
+			else
+#endif/*NO_PNG_LUMPS*/
+				levelflat->type = LEVELFLAT_FLAT;/* phew */
+		}
+
+		levelflat->u.flat.    lumpnum = flatnum;
+		levelflat->u.flat.baselumpnum = LUMPERROR;
+	}
+
+	return ( numlevelflats++ );
+}
+
+// Auxiliary function. Find a flat in the active wad files,
+// allocate an id for it, and set the levelflat (to speedup search)
+INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
+{
+	return Ploadflat(levelflat, flatname);
 }
 
 // help function for Lua and $$$.sav reading
@@ -600,44 +666,7 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
 //
 INT32 P_AddLevelFlatRuntime(const char *flatname)
 {
-	size_t i;
-	levelflat_t *levelflat = levelflats;
-
-	//
-	//  first scan through the already found flats
-	//
-	for (i = 0; i < numlevelflats; i++, levelflat++)
-		if (strnicmp(levelflat->name,flatname,8)==0)
-			break;
-
-	// that flat was already found in the level, return the id
-	if (i == numlevelflats)
-	{
-		// allocate new flat memory
-		levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL);
-		levelflat = levelflats+i;
-
-		// store the name
-		strlcpy(levelflat->name, flatname, sizeof (levelflat->name));
-		strupr(levelflat->name);
-
-		// store the flat lump number
-		levelflat->lumpnum = R_GetFlatNumForName(flatname);
-		levelflat->texturenum = R_CheckTextureNumForName(flatname);
-		levelflat->lasttexturenum = levelflat->texturenum;
-
-		levelflat->baselumpnum = LUMPERROR;
-		levelflat->basetexturenum = -1;
-
-#ifndef ZDEBUG
-		CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
-#endif
-
-		numlevelflats++;
-	}
-
-	// level flat id
-	return (INT32)i;
+	return Ploadflat(0, flatname);
 }
 
 // help function for $$$.sav checking
diff --git a/src/p_setup.h b/src/p_setup.h
index 7e3a149eb882965e436dbc4ff4327d0fcefa8a00..d8787073b08c823630e4cc41d1484f3ec8bd2c3b 100644
--- a/src/p_setup.h
+++ b/src/p_setup.h
@@ -30,20 +30,51 @@ extern boolean levelloading;
 extern UINT8 levelfadecol;
 
 extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame
+
+/* for levelflat type */
+enum
+{
+	LEVELFLAT_NONE,/* HOM time my friend */
+	LEVELFLAT_FLAT,
+	LEVELFLAT_PATCH,
+#ifndef NO_PNG_LUMPS
+	LEVELFLAT_PNG,
+#endif
+	LEVELFLAT_TEXTURE,
+};
+
 //
 // MAP used flats lookup table
 //
 typedef struct
 {
 	char name[9]; // resource name from wad
-	lumpnum_t lumpnum; // lump number of the flat
-	INT32 texturenum, lasttexturenum; // texture number of the flat
+
+	UINT8  type;
+	union
+	{
+		struct
+		{
+			lumpnum_t     lumpnum; // lump number of the flat
+			// for flat animation
+			lumpnum_t baselumpnum;
+		}
+		flat;
+		struct
+		{
+			INT32             num;
+			INT32         lastnum; // texture number of the flat
+			// for flat animation
+			INT32         basenum;
+		}
+		texture;
+	}
+	u;
+
 	UINT16 width, height;
 	fixed_t topoffset, leftoffset;
 
 	// for flat animation
-	lumpnum_t baselumpnum;
-	INT32 basetexturenum;
 	INT32 animseq; // start pos. in the anim sequence
 	INT32 numpics;
 	INT32 speed;
diff --git a/src/p_spec.c b/src/p_spec.c
index 366377bedbf926228dc5253173ece07678f8dccd..d6a8cb48e4979f2d14ecb29bbbe6b5549ad0e0f0 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -464,11 +464,11 @@ static inline void P_FindAnimatedFlat(INT32 animnum)
 	for (i = 0; i < numlevelflats; i++, foundflats++)
 	{
 		// is that levelflat from the flat anim sequence ?
-		if ((anims[animnum].istexture) && (foundflats->texturenum != 0 && foundflats->texturenum != -1)
-			&& ((UINT16)foundflats->texturenum >= startflatnum && (UINT16)foundflats->texturenum <= endflatnum))
+		if ((anims[animnum].istexture) && (foundflats->type == LEVELFLAT_TEXTURE)
+			&& ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum))
 		{
-			foundflats->basetexturenum = startflatnum;
-			foundflats->animseq = foundflats->texturenum - startflatnum;
+			foundflats->u.texture.basenum = startflatnum;
+			foundflats->animseq = foundflats->u.texture.num - startflatnum;
 			foundflats->numpics = endflatnum - startflatnum + 1;
 			foundflats->speed = anims[animnum].speed;
 
@@ -476,10 +476,10 @@ static inline void P_FindAnimatedFlat(INT32 animnum)
 					atoi(sizeu1(i)), foundflats->name, foundflats->animseq,
 					foundflats->numpics,foundflats->speed);
 		}
-		else if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum)
+		else if (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum)
 		{
-			foundflats->baselumpnum = startflatnum;
-			foundflats->animseq = foundflats->lumpnum - startflatnum;
+			foundflats->u.flat.baselumpnum = startflatnum;
+			foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum;
 			foundflats->numpics = endflatnum - startflatnum + 1;
 			foundflats->speed = anims[animnum].speed;
 
@@ -5589,11 +5589,11 @@ void P_UpdateSpecials(void)
 		if (foundflats->speed) // it is an animated flat
 		{
 			// update the levelflat texture number
-			if (foundflats->basetexturenum != -1)
-				foundflats->texturenum = foundflats->basetexturenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
+			if (foundflats->type == LEVELFLAT_TEXTURE)
+				foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
 			// update the levelflat lump number
-			else if (foundflats->baselumpnum != LUMPERROR)
-				foundflats->lumpnum = foundflats->baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
+			else if ((foundflats->type == LEVELFLAT_FLAT) && (foundflats->u.flat.baselumpnum != LUMPERROR))
+				foundflats->u.flat.lumpnum = foundflats->u.flat.baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
 		}
 	}
 }
diff --git a/src/r_data.c b/src/r_data.c
index 15ea511e2ffb377ccf0dc495f5d7fe76dda27bcc..5a5783074334fba0b91b79b9ff54c2e8d1d154c8 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -456,6 +456,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 	texture_t *texture;
 	texpatch_t *patch;
 	patch_t *realpatch;
+	boolean dealloc = false;
 	int x, x1, x2, i, width, height;
 	size_t blocksize;
 	column_t *patchcol;
@@ -487,10 +488,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 
 #ifndef NO_PNG_LUMPS
 		if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
-		{
-			realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false);
 			goto multipatch;
-		}
 #endif
 
 		// Check the patch for holes.
@@ -579,9 +577,14 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 		lumpnum = patch->lump;
 		lumplength = W_LumpLengthPwad(wadnum, lumpnum);
 		realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
+		dealloc = false;
+
 #ifndef NO_PNG_LUMPS
 		if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
+		{
 			realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false);
+			dealloc = true;
+		}
 #endif
 
 		x1 = patch->originx;
@@ -619,6 +622,9 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 			*(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4));
 			ColumnDrawerPointer(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch, texture->height, height);
 		}
+
+		if (dealloc)
+			Z_Free(realpatch);
 	}
 
 done:
@@ -1450,48 +1456,6 @@ lumpnum_t R_GetFlatNumForName(const char *name)
 		lump = LUMPERROR;
 	}
 
-	// Detect textures
-	if (lump == LUMPERROR)
-	{
-		// Scan wad files backwards so patched textures take preference.
-		for (i = numwadfiles - 1; i >= 0; i--)
-		{
-			switch (wadfiles[i]->type)
-			{
-			case RET_WAD:
-				if ((start = W_CheckNumForNamePwad("TX_START", (UINT16)i, 0)) == INT16_MAX)
-					continue;
-				if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX)
-					continue;
-				break;
-			case RET_PK3:
-				if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX)
-					continue;
-				if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX)
-					continue;
-				break;
-			default:
-				continue;
-			}
-
-			// Now find lump with specified name in that range.
-			lump = W_CheckNumForNamePwad(name, (UINT16)i, start);
-			if (lump < end)
-			{
-				lump += (i<<16); // found it, in our constraints
-				break;
-			}
-			lump = LUMPERROR;
-		}
-	}
-
-	if (lump == LUMPERROR)
-	{
-		if (strcmp(name, SKYFLATNAME))
-			CONS_Debug(DBG_SETUP, "R_GetFlatNumForName: Could not find flat %.8s\n", name);
-		lump = W_CheckNumForName("REDFLR");
-	}
-
 	return lump;
 }
 
diff --git a/src/r_plane.c b/src/r_plane.c
index 9f417ee6bff85de8aa409b6d6db677d33b2bff2f..53b58c274386a242f095e777347163072af9f146 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -756,9 +756,9 @@ static UINT8 *R_GenerateFlat(UINT16 width, UINT16 height)
 static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng)
 {
 	UINT8 *flat;
-	textureflat_t *texflat = &texflats[levelflat->texturenum];
+	textureflat_t *texflat = &texflats[levelflat->u.texture.num];
 	patch_t *patch = NULL;
-	boolean texturechanged = (leveltexture ? (levelflat->texturenum != levelflat->lasttexturenum) : false);
+	boolean texturechanged = (leveltexture ? (levelflat->u.texture.num != levelflat->u.texture.lastnum) : false);
 
 	// Check if the texture changed.
 	if (leveltexture && (!texturechanged))
@@ -780,12 +780,12 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo
 		// Level texture
 		if (leveltexture)
 		{
-			texture_t *texture = textures[levelflat->texturenum];
+			texture_t *texture = textures[levelflat->u.texture.num];
 			texflat->width = ds_flatwidth = texture->width;
 			texflat->height = ds_flatheight = texture->height;
 
 			texflat->flat = R_GenerateFlat(ds_flatwidth, ds_flatheight);
-			R_TextureToFlat(levelflat->texturenum, texflat->flat);
+			R_TextureToFlat(levelflat->u.texture.num, texflat->flat);
 			flat = texflat->flat;
 
 			levelflat->flatpatch = flat;
@@ -799,7 +799,7 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo
 #ifndef NO_PNG_LUMPS
 			if (ispng)
 			{
-				levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->lumpnum));
+				levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->u.flat.lumpnum));
 				levelflat->topoffset = levelflat->leftoffset = 0;
 				ds_flatwidth = levelflat->width;
 				ds_flatheight = levelflat->height;
@@ -829,7 +829,7 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo
 	xoffs += levelflat->leftoffset;
 	yoffs += levelflat->topoffset;
 
-	levelflat->lasttexturenum = levelflat->texturenum;
+	levelflat->u.texture.lastnum = levelflat->u.texture.num;
 	return flat;
 }
 
@@ -839,10 +839,9 @@ void R_DrawSinglePlane(visplane_t *pl)
 	INT32 light = 0;
 	INT32 x;
 	INT32 stop, angle;
-	size_t size;
 	ffloor_t *rover;
 	levelflat_t *levelflat;
-	boolean rawflat = false;
+	int type;
 
 	if (!(pl->minx <= pl->maxx))
 		return;
@@ -996,43 +995,45 @@ void R_DrawSinglePlane(visplane_t *pl)
 
 	currentplane = pl;
 	levelflat = &levelflats[pl->picnum];
-	size = W_LumpLength(levelflat->lumpnum);
-	ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag
 
-	// Check if the flat is actually a wall texture.
-	if (levelflat->texturenum != 0 && levelflat->texturenum != -1)
-		flat = R_GetTextureFlat(levelflat, true, false);
+	/* :james: */
+	type = levelflat->type;
+	switch (type)
+	{
+		case LEVELFLAT_NONE:
+			return;
+		case LEVELFLAT_FLAT:
+			ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE);
+			R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum));
+			// Raw flats always have dimensions that are powers-of-two numbers.
+			ds_powersoftwo = true;
+			break;
+		default:
+			switch (type)
+			{
+				case LEVELFLAT_TEXTURE:
+					/* Textures get cached differently and don't need ds_source */
+					ds_source = R_GetTextureFlat(levelflat, true, false);
+					break;
+				default:
+					ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_STATIC);
+					flat      = R_GetTextureFlat(levelflat, false,
 #ifndef NO_PNG_LUMPS
-	// Maybe it's a PNG?!
-	else if (R_IsLumpPNG(ds_source, size))
-		flat = R_GetTextureFlat(levelflat, false, true);
+							( type == LEVELFLAT_PNG )
+#else
+							false
 #endif
-	// Maybe it's just a patch, then?
-	else if (R_CheckIfPatch(levelflat->lumpnum))
-		flat = R_GetTextureFlat(levelflat, false, false);
-	// It's a raw flat.
-	else
-	{
-		rawflat = true;
-		R_CheckFlatLength(size);
-		flat = ds_source;
-	}
-
-	Z_ChangeTag(ds_source, PU_CACHE);
-	ds_source = flat;
-
-	if (ds_source == NULL)
-		return;
-
-	// Raw flats always have dimensions that are powers-of-two numbers.
-	if (rawflat)
-		ds_powersoftwo = true;
-	// Otherwise, check if this texture or patch has such dimensions.
-	else if (R_CheckPowersOfTwo())
-	{
-		R_CheckFlatLength(ds_flatwidth * ds_flatheight);
-		if (spanfunc == basespanfunc)
-			spanfunc = mmxspanfunc;
+					);
+					Z_ChangeTag(ds_source, PU_CACHE);
+					ds_source = flat;
+			}
+			// Check if this texture or patch has power-of-two dimensions.
+			if (R_CheckPowersOfTwo())
+			{
+				R_CheckFlatLength(ds_flatwidth * ds_flatheight);
+				if (spanfunc == basespanfunc)
+					spanfunc = mmxspanfunc;
+			}
 	}
 
 	if (light >= LIGHTLEVELS)