diff --git a/src/doomdef.h b/src/doomdef.h
index 84404d6edb62d82633b3f2643b9133a14d6b7ed3..c29bf96256f1306faeac8b48ea0161c544b58bb3 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -701,9 +701,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
 #define NO_PNG_LUMPS
 #endif
 
-/// Render flats on walls
-#define WALLFLATS
-
 /// Maintain compatibility with older 2.2 demos
 #define OLD22DEMOCOMPAT
 
diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c
index 8ac5b0ec832e3634a6d810e80e31fbf160118657..a9e5babc1d5f7f00c4eb627f47e5095825c21d13 100644
--- a/src/hardware/hw_cache.c
+++ b/src/hardware/hw_cache.c
@@ -484,11 +484,9 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
 			realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
 		else
 #endif
-#ifdef WALLFLATS
 		if (texture->type == TEXTURETYPE_FLAT)
 			realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0);
 		else
-#endif
 			realpatch = (patch_t *)Picture_Convert(PICFMT_DOOMPATCH, pdata, PICFMT_PATCH, 0, NULL, 0, 0, 0, 0, 0);
 
 		HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch);
@@ -723,7 +721,7 @@ void HWR_LoadMapTextures(size_t pnumtextures)
 	gl_textures = calloc(gl_numtextures, sizeof(*gl_textures));
 	gl_flats = calloc(gl_numtextures, sizeof(*gl_flats));
 
-	if ((gl_textures == NULL) || (gl_flats == NULL))
+	if (gl_textures == NULL || gl_flats == NULL)
 		I_Error("HWR_LoadMapTextures: ran out of memory for OpenGL textures");
 
 	gl_maptexturesloaded = true;
@@ -788,26 +786,6 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
 	W_ReadLump(flatlumpnum, Z_Malloc(size, PU_HWRCACHE, &grMipmap->data));
 }
 
-static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
-{
-	UINT8 *flat;
-	UINT8 *converted;
-	size_t size;
-
-	// setup the texture info
-	grMipmap->format = GL_TEXFMT_P_8;
-	grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
-
-	grMipmap->width  = (UINT16)textures[texturenum]->width;
-	grMipmap->height = (UINT16)textures[texturenum]->height;
-	size = (grMipmap->width * grMipmap->height);
-
-	flat = Z_Malloc(size, PU_HWRCACHE, &grMipmap->data);
-	converted = (UINT8 *)Picture_TextureToFlat(texturenum);
-	M_Memcpy(flat, converted, size);
-	Z_Free(converted);
-}
-
 // Download a Doom 'flat' to the hardware cache and make it ready for use
 void HWR_GetRawFlat(lumpnum_t flatlumpnum)
 {
@@ -833,96 +811,40 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum)
 
 void HWR_GetLevelFlat(levelflat_t *levelflat)
 {
-	// Who knows?
-	if (levelflat == NULL)
-		return;
-
-	if (levelflat->type == LEVELFLAT_FLAT)
-		HWR_GetRawFlat(levelflat->u.flat.lumpnum);
-	else if (levelflat->type == LEVELFLAT_TEXTURE)
+	if (levelflat->type == LEVELFLAT_NONE)
 	{
-		GLMapTexture_t *grtex;
-		INT32 texturenum = levelflat->u.texture.num;
-#ifdef PARANOIA
-		if ((unsigned)texturenum >= gl_numtextures)
-			I_Error("HWR_GetLevelFlat: texturenum >= numtextures");
-#endif
-
-		// Who knows?
-		if (texturenum == 0 || texturenum == -1)
-			return;
-
-		// Every texture in memory, stored as a 8-bit flat. Wow!
-		grtex = &gl_flats[texturenum];
-
-		// Generate flat if missing from the cache
-		if (!grtex->mipmap.data && !grtex->mipmap.downloaded)
-			HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum);
-
-		// If hardware does not have the texture, then call pfnSetTexture to upload it
-		if (!grtex->mipmap.downloaded)
-			HWD.pfnSetTexture(&grtex->mipmap);
-		HWR_SetCurrentTexture(&grtex->mipmap);
-
-		// The system-memory data can be purged now.
-		Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED);
+		HWR_SetCurrentTexture(NULL);
+		return;
 	}
-	else if (levelflat->type == LEVELFLAT_PATCH)
+
+	INT32 texturenum = texturetranslation[levelflat->texture_id];
+	if (texturenum <= 0)
 	{
-		patch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE);
-		levelflat->width = (UINT16)(patch->width);
-		levelflat->height = (UINT16)(patch->height);
-		HWR_GetPatch(patch);
+		HWR_SetCurrentTexture(NULL);
+		return;
 	}
-#ifndef NO_PNG_LUMPS
-	else if (levelflat->type == LEVELFLAT_PNG)
-	{
-		GLMipmap_t *mipmap = levelflat->mipmap;
 
-		// Cache the picture.
-		if (!levelflat->mippic)
-		{
-			INT32 pngwidth = 0, pngheight = 0;
-			void *pic = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0);
-
-			Z_ChangeTag(pic, PU_LEVEL);
-			Z_SetUser(pic, &levelflat->mippic);
-
-			levelflat->width = (UINT16)pngwidth;
-			levelflat->height = (UINT16)pngheight;
-		}
+	GLMapTexture_t *grtex = &gl_flats[texturenum];
+	GLMipmap_t *grMipmap = &grtex->mipmap;
 
-		// Make the mipmap.
-		if (mipmap == NULL)
-		{
-			mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_STATIC, NULL);
-			mipmap->format = GL_TEXFMT_P_8;
-			mipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
-			levelflat->mipmap = mipmap;
-		}
+	if (!grMipmap->data && !grMipmap->downloaded)
+	{
+		grMipmap->format = GL_TEXFMT_P_8;
+		grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
 
-		if (!mipmap->data && !mipmap->downloaded)
-		{
-			UINT8 *flat;
-			size_t size;
+		grMipmap->width  = (UINT16)textures[texturenum]->width;
+		grMipmap->height = (UINT16)textures[texturenum]->height;
 
-			if (levelflat->mippic == NULL)
-				I_Error("HWR_GetLevelFlat: levelflat->mippic == NULL");
+		size_t size = grMipmap->width * grMipmap->height;
+		memcpy(Z_Malloc(size, PU_HWRCACHE, &grMipmap->data), R_GetFlatForTexture(texturenum), size);
+	}
 
-			mipmap->width = levelflat->width;
-			mipmap->height = levelflat->height;
+	if (!grMipmap->downloaded)
+		HWD.pfnSetTexture(&grtex->mipmap);
 
-			size = (mipmap->width * mipmap->height);
-			flat = Z_Malloc(size, PU_LEVEL, &mipmap->data);
-			M_Memcpy(flat, levelflat->mippic, size);
-		}
+	HWR_SetCurrentTexture(&grtex->mipmap);
 
-		// Tell the hardware driver to bind the current texture to the flat's mipmap
-		HWR_SetCurrentTexture(mipmap);
-	}
-#endif
-	else // set no texture
-		HWR_SetCurrentTexture(NULL);
+	Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
 }
 
 // --------------------+
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 36ff86abd7d0770351234913b03d837e2086b62d..575498c6ff0fae3a1c39cf36d5f6e776b32f6da8 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -373,9 +373,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 	float height; // constant y for all points on the convex flat polygon
 	float flatxref, flatyref, anglef = 0.0f;
 	float fflatwidth = 64.0f, fflatheight = 64.0f;
-	UINT16 flatflag = 63;
-
-	boolean texflat = false;
 
 	float tempxsow, tempytow;
 	float scrollx = 0.0f, scrolly = 0.0f;
@@ -427,33 +424,16 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 	// set texture for polygon
 	if (levelflat != NULL)
 	{
-		if (levelflat->type == LEVELFLAT_FLAT)
-		{
-			size_t len = W_LumpLength(levelflat->u.flat.lumpnum);
-			flatflag = R_GetFlatSize(len) - 1;
-			fflatwidth = fflatheight = (float)(flatflag + 1);
-		}
-		else
-		{
-			if (levelflat->type == LEVELFLAT_TEXTURE)
-			{
-				fflatwidth = textures[levelflat->u.texture.num]->width;
-				fflatheight = textures[levelflat->u.texture.num]->height;
-			}
-			else if (levelflat->type == LEVELFLAT_PATCH || levelflat->type == LEVELFLAT_PNG)
-			{
-				fflatwidth = levelflat->width;
-				fflatheight = levelflat->height;
-			}
-			texflat = true;
-		}
+		texture_t *texture = textures[R_GetTextureNumForFlat(levelflat)];
+		fflatwidth = texture->width;
+		fflatheight = texture->height;
 	}
 	else // set no texture
 		HWR_SetCurrentTexture(NULL);
 
 	// reference point for flat texture coord for each vertex around the polygon
-	flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth);
-	flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight);
+	flatxref = 0.0;
+	flatyref = 0.0;
 
 	// transform
 	if (FOFsector != NULL)
@@ -487,30 +467,13 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 		}
 	}
 
-	if (angle) // Only needs to be done if there's an altered angle
-	{
-		tempxsow = flatxref;
-		tempytow = flatyref;
-
-		anglef = ANG2RAD(InvAngle(angle));
-
-		flatxref = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));
-		flatyref = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));
-	}
+	anglef = ANG2RAD(InvAngle(angle));
 
 #define SETUP3DVERT(vert, vx, vy) {\
-		/* Hurdler: add scrolling texture on floor/ceiling */\
-		if (texflat)\
-		{\
-			vert->s = (float)((vx) / fflatwidth) + scrollx;\
-			vert->t = -(float)((vy) / fflatheight) + scrolly;\
-		}\
-		else\
-		{\
-			vert->s = (float)(((vx) / fflatwidth) - flatxref + scrollx);\
-			vert->t = (float)(flatyref - ((vy) / fflatheight) + scrolly);\
-		}\
-\
+		/* Hurdler: add scrolling texture on floor/ceiling */ \
+		vert->s = (float)(((vx) / fflatwidth) - flatxref + scrollx);\
+		vert->t = (float)(flatyref - ((vy) / fflatheight) + scrolly);\
+ \
 		/* Need to rotate before translate */\
 		if (angle) /* Only needs to be done if there's an altered angle */\
 		{\
@@ -2652,9 +2615,6 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
 	float height = FIXED_TO_FLOAT(fixedheight); // constant y for all points on the convex flat polygon
 	float flatxref, flatyref;
 	float fflatwidth = 64.0f, fflatheight = 64.0f;
-	UINT16 flatflag = 63;
-
-	boolean texflat = false;
 
 	float scrollx = 0.0f, scrolly = 0.0f;
 	float tempxsow, tempytow, anglef = 0.0f;
@@ -2682,36 +2642,16 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
 	// set texture for polygon
 	if (levelflat != NULL)
 	{
-		if (levelflat->type == LEVELFLAT_FLAT)
-		{
-			size_t len = W_LumpLength(levelflat->u.flat.lumpnum);
-			flatflag = R_GetFlatSize(len) - 1;
-			fflatwidth = fflatheight = (float)(flatflag + 1);
-		}
-		else
-		{
-			if (levelflat->type == LEVELFLAT_TEXTURE)
-			{
-				fflatwidth = textures[levelflat->u.texture.num]->width;
-				fflatheight = textures[levelflat->u.texture.num]->height;
-			}
-			else if (levelflat->type == LEVELFLAT_PATCH || levelflat->type == LEVELFLAT_PNG)
-			{
-				fflatwidth = levelflat->width;
-				fflatheight = levelflat->height;
-			}
-			texflat = true;
-		}
+		texture_t *texture = textures[R_GetTextureNumForFlat(levelflat)];
+		fflatwidth = texture->width;
+		fflatheight = texture->height;
 	}
 	else // set no texture
 		HWR_SetCurrentTexture(NULL);
 
 	// reference point for flat texture coord for each vertex around the polygon
-	flatxref = FIXED_TO_FLOAT(polysector->origVerts[0].x);
-	flatyref = FIXED_TO_FLOAT(polysector->origVerts[0].y);
-
-	flatxref = (float)(((fixed_t)flatxref & (~flatflag)) / fflatwidth);
-	flatyref = (float)(((fixed_t)flatyref & (~flatflag)) / fflatheight);
+	flatxref = 0.0;
+	flatyref = 0.0;
 
 	// transform
 	v3d = planeVerts;
@@ -2747,31 +2687,12 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
 		}
 	}
 
-	if (angle) // Only needs to be done if there's an altered angle
-	{
-		tempxsow = flatxref;
-		tempytow = flatyref;
-
-		anglef = ANG2RAD(InvAngle(angle));
-
-		flatxref = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));
-		flatyref = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));
-	}
-
 	for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++)
 	{
 		// Go from the polysector's original vertex locations
 		// Means the flat is offset based on the original vertex locations
-		if (texflat)
-		{
-			v3d->s = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx;
-			v3d->t = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly;
-		}
-		else
-		{
-			v3d->s = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx);
-			v3d->t = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly);
-		}
+		v3d->s = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx);
+		v3d->t = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly);
 
 		// Need to rotate before translate
 		if (angle) // Only needs to be done if there's an altered angle
@@ -2779,6 +2700,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
 			tempxsow = v3d->s;
 			tempytow = v3d->t;
 
+			anglef = ANG2RAD(InvAngle(angle));
+
 			v3d->s = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));
 			v3d->t = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));
 		}
diff --git a/src/p_setup.c b/src/p_setup.c
index 175ab3328b627d7aceabeae3fd865ca71aba7b0b..e3dd1abf198bb10463f8be01525ec4c8620241d0 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -533,20 +533,14 @@ levelflat_t *foundflats;
 //SoM: Other files want this info.
 size_t P_PrecacheLevelFlats(void)
 {
-	lumpnum_t lump;
 	size_t i;
 
 	//SoM: 4/18/2000: New flat code to make use of levelflats.
 	flatmemory = 0;
 	for (i = 0; i < numlevelflats; i++)
 	{
-		if (levelflats[i].type == LEVELFLAT_FLAT)
-		{
-			lump = levelflats[i].u.flat.lumpnum;
-			if (devparm)
-				flatmemory += W_LumpLength(lump);
-			R_GetFlat(lump);
-		}
+		if (levelflats[i].type != LEVELFLAT_NONE)
+			R_GetFlat(&levelflats[i]);
 	}
 	return flatmemory;
 }
@@ -558,19 +552,8 @@ or NULL if we want to allocate it now.
 static INT32
 Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
 {
-#ifndef NO_PNG_LUMPS
-	UINT8         buffer[8];
-#endif
-
-	lumpnum_t    flatnum;
-	int       texturenum;
-	UINT8     *flatpatch;
-	size_t    lumplength;
-
-	size_t i;
-
 	// Scan through the already found flats, return if it matches.
-	for (i = 0; i < numlevelflats; i++)
+	for (size_t i = 0; i < numlevelflats; i++)
 	{
 		if (strnicmp(levelflat[i].name, flatname, 8) == 0)
 			return i;
@@ -594,64 +577,35 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
 	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(levelflat->name) ) == LUMPERROR)
+	levelflat->type = LEVELFLAT_TEXTURE;
+
+	// Look for a flat
+	int texturenum = R_CheckFlatNumForName(levelflat->name);
+	if (texturenum <= 0)
 	{
-		if (( texturenum = R_CheckTextureNumForName(levelflat->name) ) == -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
+		// If we can't find a flat, try looking for a texture!
+		texturenum = R_CheckTextureNumForName(levelflat->name);
+		if (texturenum <= 0)
 		{
-texturefound:
-			levelflat->type = LEVELFLAT_TEXTURE;
-			levelflat->u.texture.    num = texturenum;
-			levelflat->u.texture.lastnum = texturenum;
-			/* start out unanimated */
-			levelflat->u.texture.basenum = -1;
+			// Use "not found" texture
+			texturenum = R_CheckTextureNumForName("REDWALL");
+
+			// Give up?
+			if (texturenum <= 0)
+			{
+				levelflat->type = LEVELFLAT_NONE;
+				texturenum = -1;
+			}
 		}
 	}
-	else
-	{
-flatfound:
-		/* This could be a flat, patch, or PNG. */
-		flatpatch = W_CacheLumpNum(flatnum, PU_CACHE);
-		lumplength = W_LumpLength(flatnum);
-		if (Picture_CheckIfDoomPatch((softwarepatch_t *)flatpatch, lumplength))
-			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 (Picture_IsLumpPNG(buffer, lumplength))
-				levelflat->type = LEVELFLAT_PNG;
-			else
-#endif/*NO_PNG_LUMPS*/
-				levelflat->type = LEVELFLAT_FLAT;/* phew */
-		}
-		if (flatpatch)
-			Z_Free(flatpatch);
 
-		levelflat->u.flat.    lumpnum = flatnum;
-		levelflat->u.flat.baselumpnum = LUMPERROR;
-	}
+	levelflat->texture_id = texturenum;
 
 #ifndef ZDEBUG
 	CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
 #endif
 
-	return ( numlevelflats++ );
+	return numlevelflats++;
 }
 
 // Auxiliary function. Find a flat in the active wad files,
@@ -3149,9 +3103,6 @@ static boolean P_LoadMapData(const virtres_t *virt)
 	levelflats = M_Memcpy(Z_Calloc(numlevelflats * sizeof (*levelflats), PU_LEVEL, NULL), foundflats, numlevelflats * sizeof (levelflat_t));
 	free(foundflats);
 
-	// search for animated flats and set up
-	P_SetupLevelFlatAnims();
-
 	return true;
 }
 
diff --git a/src/p_setup.h b/src/p_setup.h
index c6f4f741c01c56fecfc5b0fa0fb267fb1c975b16..f9e51024d2dbcf55f61bd193d1e32edc278a31be 100644
--- a/src/p_setup.h
+++ b/src/p_setup.h
@@ -35,9 +35,6 @@ extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame
 enum
 {
 	LEVELFLAT_NONE,/* HOM time my friend */
-	LEVELFLAT_FLAT,
-	LEVELFLAT_PATCH,
-	LEVELFLAT_PNG,
 	LEVELFLAT_TEXTURE,
 };
 
@@ -47,41 +44,8 @@ enum
 typedef struct
 {
 	char name[9]; // resource name from wad
-
-	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;
-
-	// for flat animation
-	INT32 animseq; // start pos. in the anim sequence
-	INT32 numpics;
-	INT32 speed;
-
-	// for textures
-	UINT8 *picture;
-#ifdef HWRENDER
-	void *mipmap;
-	void *mippic;
-#endif
+	UINT8 type;
+	INT32 texture_id;
 } levelflat_t;
 
 extern size_t numlevelflats;
diff --git a/src/p_spec.c b/src/p_spec.c
index 6709515201c5343d2970e993dacdbf309568a34f..5493b536699f87d802f54d444f266ba7b38975bb 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -152,7 +152,6 @@ void P_ParseAnimationDefintion(SINT8 istexture);
   *
   * Issues an error if any animation cycles are invalid.
   *
-  * \sa P_FindAnimatedFlat, P_SetupLevelFlatAnims
   * \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs), JTE (had to rewrite it to handle multiple WADs _correctly_)
   */
 void P_InitPicAnims(void)
@@ -205,11 +204,11 @@ void P_InitPicAnims(void)
 		}
 		else
 		{
-			if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR)
+			if (R_CheckFlatNumForName(animdefs[i].startname) == -1)
 				continue;
 
-			lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname);
-			lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname);
+			lastanim->picnum = R_CheckFlatNumForName(animdefs[i].endname);
+			lastanim->basepic = R_CheckFlatNumForName(animdefs[i].startname);
 		}
 
 		lastanim->istexture = animdefs[i].istexture;
@@ -437,82 +436,13 @@ void P_ParseAnimationDefintion(SINT8 istexture)
 	animdefs[i].speed = animSpeed;
 	Z_Free(animdefsToken);
 
-#ifdef WALLFLATS
-	// hehe... uhh.....
+	// Add it as a texture too
 	if (!istexture)
 	{
 		GrowAnimDefs();
 		M_Memcpy(&animdefs[maxanims-1], &animdefs[i], sizeof(animdef_t));
 		animdefs[maxanims-1].istexture = 1;
 	}
-#endif
-}
-
-/** Checks for flats in levelflats that are part of a flat animation sequence
-  * and sets them up for animation.
-  *
-  * \param animnum Index into ::anims to find flats for.
-  * \sa P_SetupLevelFlatAnims
-  */
-static inline void P_FindAnimatedFlat(INT32 animnum)
-{
-	size_t i;
-	lumpnum_t startflatnum, endflatnum;
-	levelflat_t *foundflats;
-
-	foundflats = levelflats;
-	startflatnum = anims[animnum].basepic;
-	endflatnum = anims[animnum].picnum;
-
-	// note: high word of lumpnum is the wad number
-	if ((startflatnum>>16) != (endflatnum>>16))
-		I_Error("AnimatedFlat start %s not in same wad as end %s\n",
-			animdefs[animnum].startname, animdefs[animnum].endname);
-
-	//
-	// now search through the levelflats if this anim flat sequence is used
-	//
-	for (i = 0; i < numlevelflats; i++, foundflats++)
-	{
-		// is that levelflat from the flat anim sequence ?
-		if ((anims[animnum].istexture) && (foundflats->type == LEVELFLAT_TEXTURE)
-			&& ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum))
-		{
-			foundflats->u.texture.basenum = startflatnum;
-			foundflats->animseq = foundflats->u.texture.num - startflatnum;
-			foundflats->numpics = endflatnum - startflatnum + 1;
-			foundflats->speed = anims[animnum].speed;
-
-			CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n",
-					atoi(sizeu1(i)), foundflats->name, foundflats->animseq,
-					foundflats->numpics,foundflats->speed);
-		}
-		else if ((!anims[animnum].istexture) && (foundflats->type == LEVELFLAT_FLAT)
-			&& (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum))
-		{
-			foundflats->u.flat.baselumpnum = startflatnum;
-			foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum;
-			foundflats->numpics = endflatnum - startflatnum + 1;
-			foundflats->speed = anims[animnum].speed;
-
-			CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n",
-					atoi(sizeu1(i)), foundflats->name, foundflats->animseq,
-					foundflats->numpics,foundflats->speed);
-		}
-	}
-}
-
-/** Sets up all flats used in a level.
-  *
-  * \sa P_InitPicAnims, P_FindAnimatedFlat
-  */
-void P_SetupLevelFlatAnims(void)
-{
-	INT32 i;
-
-	// the original game flat anim sequences
-	for (i = 0; anims[i].istexture != -1; i++)
-		P_FindAnimatedFlat(i);
 }
 
 //
@@ -5392,13 +5322,6 @@ void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable)
   */
 void P_UpdateSpecials(void)
 {
-	anim_t *anim;
-	INT32 i;
-	INT32 pic;
-	size_t j;
-
-	levelflat_t *foundflats; // for flat animation
-
 	// LEVEL TIMER
 	P_CheckTimeLimit();
 
@@ -5406,37 +5329,19 @@ void P_UpdateSpecials(void)
 	P_CheckPointLimit();
 
 	// ANIMATE TEXTURES
-	for (anim = anims; anim < lastanim; anim++)
+	for (anim_t *anim = anims; anim < lastanim; anim++)
 	{
-		for (i = 0; i < anim->numpics; i++)
+		for (INT32 i = 0; i < anim->numpics; i++)
 		{
-			pic = anim->basepic + ((leveltime/anim->speed + i) % anim->numpics);
+			INT32 pic = anim->basepic + ((leveltime/anim->speed + i) % anim->numpics);
 			if (anim->istexture)
 				texturetranslation[anim->basepic+i] = pic;
 		}
 	}
-
-	// ANIMATE FLATS
-	/// \todo do not check the non-animate flat.. link the animated ones?
-	/// \note its faster than the original anywaysince it animates only
-	///    flats used in the level, and there's usually very few of them
-	foundflats = levelflats;
-	for (j = 0; j < numlevelflats; j++, foundflats++)
-	{
-		if (foundflats->speed) // it is an animated flat
-		{
-			// update the levelflat texture number
-			if ((foundflats->type == LEVELFLAT_TEXTURE) && (foundflats->u.texture.basenum != -1))
-				foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics);
-			// update the levelflat lump number
-			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);
-		}
-	}
 }
 
 //
-// Floor over floors (FOFs), 3Dfloors, 3Dblocks, fake floors (ffloors), rovers, or whatever you want to call them
+// 3D floors
 //
 
 /** Gets the ID number for a 3Dfloor in its target sector.
diff --git a/src/p_spec.h b/src/p_spec.h
index 50ab6410f145b0d2ad180b492525cec51d786365..054fa767e3612290bb3973dd296f983a66e5a3f5 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -484,9 +484,6 @@ typedef enum
 // at game start
 void P_InitPicAnims(void);
 
-// at map load (sectors)
-void P_SetupLevelFlatAnims(void);
-
 // at map load
 void P_InitSpecials(void);
 void P_ApplyFlatAlignment(sector_t* sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs, boolean floor, boolean ceiling);
diff --git a/src/r_picformats.c b/src/r_picformats.c
index b11eae138c1c477a93216383d122ce226043d868..eb561f2630829f7f72454e5c8643ce0cb0228e53 100644
--- a/src/r_picformats.c
+++ b/src/r_picformats.c
@@ -754,7 +754,7 @@ void *Picture_TextureToFlat(size_t texnum)
 	R_CheckTextureCache(texnum);
 
 	// Allocate the flat
-	flatsize = (texture->width * texture->height);
+	flatsize = texture->width * texture->height;
 	converted = Z_Malloc(flatsize, PU_STATIC, NULL);
 	memset(converted, TRANSPARENTPIXEL, flatsize);
 
diff --git a/src/r_plane.c b/src/r_plane.c
index 12c06c283bbd57410aceb8a5446f4f7a167e402a..28ab45ec15ddd28b5256eaab4f51726e862d362a 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -978,30 +978,21 @@ void R_DrawSinglePlane(visplane_t *pl)
 	{
 		levelflat_t *levelflat = &levelflats[pl->picnum];
 
-		/* :james: */
-		switch (levelflat->type)
+		// Get the texture
+		ds_source = (UINT8 *)R_GetFlat(levelflat);
+		if (ds_source == NULL)
+			return;
+
+		texture_t *texture = textures[R_GetTextureNumForFlat(levelflat)];
+		ds_flatwidth = texture->width;
+		ds_flatheight = texture->height;
+
+		if (R_CheckSolidColorFlat())
+			ds_solidcolor = true;
+		else if (R_CheckPowersOfTwo())
 		{
-			case LEVELFLAT_NONE:
-				return;
-			case LEVELFLAT_FLAT:
-				ds_source = (UINT8 *)R_GetFlat(levelflat->u.flat.lumpnum);
-				R_SetFlatVars(W_LumpLength(levelflat->u.flat.lumpnum));
-				if (R_CheckSolidColorFlat())
-					ds_solidcolor = true;
-				else
-					ds_powersoftwo = true;
-				break;
-			default:
-				ds_source = (UINT8 *)R_GetLevelFlat(levelflat);
-				if (!ds_source)
-					return;
-				else if (R_CheckSolidColorFlat())
-					ds_solidcolor = true;
-				else if (R_CheckPowersOfTwo())
-				{
-					R_SetFlatVars(ds_flatwidth * ds_flatheight);
-					ds_powersoftwo = true;
-				}
+			R_SetFlatVars(ds_flatwidth * ds_flatheight);
+			ds_powersoftwo = true;
 		}
 
 		// Don't mess with angle on slopes! We'll handle this ourselves later
diff --git a/src/r_textures.c b/src/r_textures.c
index 4021dc916029c474c67bdc8971bbeff3bf47fa53..bc573c1c5c9d94330b673582b80d1421738f6765 100644
--- a/src/r_textures.c
+++ b/src/r_textures.c
@@ -61,6 +61,7 @@ static struct {
 	char name[9];
 	UINT32 hash;
 	INT32 id;
+	UINT8 type;
 } *tidcache = NULL;
 static INT32 tidcachelen = 0;
 
@@ -248,7 +249,8 @@ UINT8 *R_GenerateTexture(size_t texnum)
 	texture = textures[texnum];
 	I_Assert(texture != NULL);
 
-	// allocate texture column offset lookup
+	if (texture->type == TEXTURETYPE_FLAT)
+		goto multipatch;
 
 	// single-patch textures can have holes in them and may be used on
 	// 2sided lines so they need to be kept in 'packed' format
@@ -266,11 +268,8 @@ UINT8 *R_GenerateTexture(size_t texnum)
 		softwarepatch_t *realpatch = (softwarepatch_t *)pdata;
 
 #ifndef NO_PNG_LUMPS
-		if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength))
-			goto multipatch;
-#endif
-#ifdef WALLFLATS
-		if (texture->type == TEXTURETYPE_FLAT)
+		// TODO: Is it worth converting those?
+		if (Picture_IsLumpPNG(pdata, lumplength))
 			goto multipatch;
 #endif
 
@@ -375,11 +374,9 @@ UINT8 *R_GenerateTexture(size_t texnum)
 			realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
 		else
 #endif
-#ifdef WALLFLATS
 		if (texture->type == TEXTURETYPE_FLAT)
 			realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0);
 		else
-#endif
 			realpatch = (patch_t *)Picture_Convert(PICFMT_DOOMPATCH, pdata, PICFMT_PATCH, 0, NULL, 0, 0, 0, 0, 0);
 
 		x1 = patch->originx;
@@ -432,29 +429,38 @@ done:
 	return blocktex;
 }
 
-//
-// R_GenerateTextureAsFlat
-//
-// Generates a flat picture for a texture.
-//
-UINT8 *R_GenerateTextureAsFlat(size_t texnum)
+UINT8 *R_GetFlatForTexture(size_t texnum)
 {
 	texture_t *texture = textures[texnum];
-	UINT8 *converted = NULL;
-	size_t size = (texture->width * texture->height);
 
-	// The flat picture for this texture was not generated yet.
-	if (!texture->flat)
+	if (texture->flat != NULL)
+		return texture->flat;
+
+	if (texture->type == TEXTURETYPE_FLAT)
 	{
-		// Well, let's do it now, then.
-		texture->flat = Z_Malloc(size, PU_STATIC, NULL);
+		texpatch_t *patch = &texture->patches[0];
+		UINT16 wadnum = patch->wad;
+		lumpnum_t lumpnum = patch->lump;
+		UINT8 *pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
 
-		// Picture_TextureToFlat handles everything for us.
-		converted = (UINT8 *)Picture_TextureToFlat(texnum);
-		M_Memcpy(texture->flat, converted, size);
-		Z_Free(converted);
+#ifndef NO_PNG_LUMPS
+		size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum);
+		if (Picture_IsLumpPNG(pdata, lumplength))
+		{
+			texture->flat = Picture_PNGConvert(pdata, PICFMT_FLAT, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
+			Z_Free(pdata);
+		}
+		else
+#endif
+			texture->flat = pdata;
+
+		return texture->flat;
 	}
 
+	texture->flat = (UINT8 *)Picture_TextureToFlat(texnum);
+
+	flatmemory += texture->width + texture->height;
+
 	return texture->flat;
 }
 
@@ -499,90 +505,17 @@ column_t *R_GetColumn(fixed_t tex, INT32 col)
 	return &texturecolumns[tex][col];
 }
 
-void *R_GetFlat(lumpnum_t flatlumpnum)
+INT32 R_GetTextureNumForFlat(levelflat_t *levelflat)
 {
-	return W_CacheLumpNum(flatlumpnum, PU_CACHE);
+	return texturetranslation[levelflat->texture_id];
 }
 
-//
-// R_GetLevelFlat
-//
-// If needed, convert a texture or patch to a flat.
-//
-void *R_GetLevelFlat(levelflat_t *levelflat)
+void *R_GetFlat(levelflat_t *levelflat)
 {
-	boolean isleveltexture = (levelflat->type == LEVELFLAT_TEXTURE);
-	texture_t *texture = (isleveltexture ? textures[levelflat->u.texture.num] : NULL);
-	boolean texturechanged = (isleveltexture ? (levelflat->u.texture.num != levelflat->u.texture.lastnum) : false);
-	UINT8 *flatdata = NULL;
-
-	// Check if the texture changed.
-	if (isleveltexture && (!texturechanged))
-	{
-		if (texture->flat)
-		{
-			flatdata = texture->flat;
-			ds_flatwidth = texture->width;
-			ds_flatheight = texture->height;
-			texturechanged = false;
-		}
-		else
-			texturechanged = true;
-	}
-
-	// If the texture changed, or the flat wasn't generated, convert.
-	if (levelflat->picture == NULL || texturechanged)
-	{
-		// Level texture
-		if (isleveltexture)
-		{
-			levelflat->picture = R_GenerateTextureAsFlat(levelflat->u.texture.num);
-			ds_flatwidth = levelflat->width = texture->width;
-			ds_flatheight = levelflat->height = texture->height;
-		}
-		else
-		{
-#ifndef NO_PNG_LUMPS
-			if (levelflat->type == LEVELFLAT_PNG)
-			{
-				INT32 pngwidth, pngheight;
-
-				levelflat->picture = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0);
-				levelflat->width = (UINT16)pngwidth;
-				levelflat->height = (UINT16)pngheight;
-
-				ds_flatwidth = levelflat->width;
-				ds_flatheight = levelflat->height;
-			}
-			else
-#endif
-			if (levelflat->type == LEVELFLAT_PATCH)
-			{
-				UINT8 *converted;
-				size_t size;
-				softwarepatch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE);
-
-				levelflat->width = ds_flatwidth = SHORT(patch->width);
-				levelflat->height = ds_flatheight = SHORT(patch->height);
-
-				levelflat->picture = Z_Malloc(levelflat->width * levelflat->height, PU_LEVEL, NULL);
-				converted = Picture_FlatConvert(PICFMT_DOOMPATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, SHORT(patch->topoffset), SHORT(patch->leftoffset), 0);
-				M_Memcpy(levelflat->picture, converted, size);
-				Z_Free(converted);
-			}
-		}
-	}
-	else
-	{
-		ds_flatwidth = levelflat->width;
-		ds_flatheight = levelflat->height;
-	}
-
-	levelflat->u.texture.lastnum = levelflat->u.texture.num;
+	if (levelflat->type == LEVELFLAT_NONE)
+		return NULL;
 
-	if (flatdata == NULL)
-		flatdata = levelflat->picture;
-	return flatdata;
+	return R_GetFlatForTexture(R_GetTextureNumForFlat(levelflat));
 }
 
 //
@@ -590,12 +523,12 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
 //
 boolean R_CheckPowersOfTwo(void)
 {
-	boolean wpow2 = !(ds_flatwidth & (ds_flatwidth - 1));
-	boolean hpow2 = !(ds_flatheight & (ds_flatheight - 1));
-
 	if (ds_flatwidth > 2048 || ds_flatheight > 2048)
 		return false;
 
+	boolean wpow2 = !(ds_flatwidth & (ds_flatwidth - 1));
+	boolean hpow2 = !(ds_flatheight & (ds_flatheight - 1));
+
 	return ds_flatwidth == ds_flatheight && wpow2 && hpow2;
 }
 
@@ -695,7 +628,6 @@ void R_FlushTextureCache(void)
 int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum);
 void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index);
 
-#ifdef WALLFLATS
 static INT32
 Rloadflats (INT32 i, INT32 w)
 {
@@ -703,9 +635,10 @@ Rloadflats (INT32 i, INT32 w)
 	UINT16 texstart, texend;
 	texture_t *texture;
 	texpatch_t *patch;
+#ifndef NO_PNG_LUMPS
 	UINT8 header[PNG_HEADER_SIZE];
+#endif
 
-	// Yes
 	if (W_FileHasFolders(wadfiles[w]))
 	{
 		texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
@@ -724,8 +657,6 @@ Rloadflats (INT32 i, INT32 w)
 		{
 			UINT16 wadnum = (UINT16)w;
 			lumpnum_t lumpnum = texstart + j;
-			size_t lumplength;
-			size_t flatsize;
 
 			if (W_FileHasFolders(wadfiles[w]))
 			{
@@ -733,9 +664,8 @@ Rloadflats (INT32 i, INT32 w)
 					continue; // If it is then SKIP IT
 			}
 
-			W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0);
-			lumplength = W_LumpLengthPwad(wadnum, lumpnum);
-			flatsize = R_GetFlatSize(lumplength);
+			size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum);
+			size_t flatsize = R_GetFlatSize(lumplength);
 
 			//CONS_Printf("\n\"%s\" is a flat, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),flatsize,flatsize);
 			texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
@@ -745,6 +675,8 @@ Rloadflats (INT32 i, INT32 w)
 			texture->hash = quickncasehash(texture->name, 8);
 
 #ifndef NO_PNG_LUMPS
+			W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0);
+
 			if (Picture_IsLumpPNG(header, lumplength))
 			{
 				UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
@@ -779,7 +711,6 @@ Rloadflats (INT32 i, INT32 w)
 
 	return i;
 }
-#endif/*WALLFLATS*/
 
 #define TX_START "TX_START"
 #define TX_END "TX_END"
@@ -938,9 +869,7 @@ static INT32 R_CountTextures(UINT16 wadnum)
 	// This system will allocate memory for all duplicate/patched textures even if it never uses them,
 	// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
 
-#ifdef WALLFLATS
 	count += count_range("F_START", "F_END", "flats/", wadnum);
-#endif
 
 	// Count the textures from TEXTURES lumps
 	texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", wadnum, 0);
@@ -1010,9 +939,7 @@ static void R_AllocateTextures(INT32 add)
 
 static INT32 R_DefineTextures(INT32 i, UINT16 w)
 {
-#ifdef WALLFLATS
 	i = Rloadflats(i, w);
-#endif
 	return Rloadtextures(i, w);
 }
 
@@ -1529,55 +1456,6 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex)
 	Z_Free((void *)texturesText);
 }
 
-// Search for flat name.
-lumpnum_t R_GetFlatNumForName(const char *name)
-{
-	INT32 i;
-	lumpnum_t lump;
-	lumpnum_t start;
-	lumpnum_t end;
-
-	// Scan wad files backwards so patched flats take preference.
-	for (i = numwadfiles - 1; i >= 0; i--)
-	{
-		switch (wadfiles[i]->type)
-		{
-		case RET_WAD:
-			if ((start = W_CheckNumForMarkerStartPwad("F_START", (UINT16)i, 0)) == INT16_MAX)
-			{
-				if ((start = W_CheckNumForMarkerStartPwad("FF_START", (UINT16)i, 0)) == INT16_MAX)
-					continue;
-				else if ((end = W_CheckNumForNamePwad("FF_END", (UINT16)i, start)) == INT16_MAX)
-					continue;
-			}
-			else
-				if ((end = W_CheckNumForNamePwad("F_END", (UINT16)i, start)) == INT16_MAX)
-					continue;
-			break;
-		case RET_PK3:
-		case RET_FOLDER:
-			if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX)
-				continue;
-			if ((end = W_CheckNumForFolderEndPK3("Flats/", 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;
-	}
-
-	return lump;
-}
-
 void R_ClearTextureNumCache(boolean btell)
 {
 	if (tidcache)
@@ -1588,6 +1466,20 @@ void R_ClearTextureNumCache(boolean btell)
 	tidcachelen = 0;
 }
 
+static void AddTextureToCache(const char *name, UINT32 hash, INT32 id, UINT8 type)
+{
+	tidcachelen++;
+	Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache);
+	strncpy(tidcache[tidcachelen-1].name, name, 8);
+	tidcache[tidcachelen-1].name[8] = '\0';
+#ifndef ZDEBUG
+	CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name);
+#endif
+	tidcache[tidcachelen-1].hash = hash;
+	tidcache[tidcachelen-1].id = id;
+	tidcache[tidcachelen-1].type = type;
+}
+
 //
 // R_CheckTextureNumForName
 //
@@ -1609,19 +1501,10 @@ INT32 R_CheckTextureNumForName(const char *name)
 			return tidcache[i].id;
 
 	// Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier
-	//for (i = 0; i < numtextures; i++) <- old
-	for (i = (numtextures - 1); i >= 0; i--) // <- new
+	for (i = numtextures - 1; i >= 0; i--)
 		if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8))
 		{
-			tidcachelen++;
-			Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache);
-			strncpy(tidcache[tidcachelen-1].name, name, 8);
-			tidcache[tidcachelen-1].name[8] = '\0';
-#ifndef ZDEBUG
-			CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name);
-#endif
-			tidcache[tidcachelen-1].hash = hash;
-			tidcache[tidcachelen-1].id = i;
+			AddTextureToCache(name, hash, i, textures[i]->type);
 			return i;
 		}
 
@@ -1678,3 +1561,28 @@ INT32 R_TextureNumForName(const char *name)
 	}
 	return i;
 }
+
+INT32 R_CheckFlatNumForName(const char *name)
+{
+	INT32 i;
+	UINT32 hash;
+
+	// "NoTexture" marker.
+	if (name[0] == '-')
+		return 0;
+
+	hash = quickncasehash(name, 8);
+
+	for (i = 0; i < tidcachelen; i++)
+		if (tidcache[i].type == TEXTURETYPE_FLAT && tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8))
+			return tidcache[i].id;
+
+	for (i = numtextures - 1; i >= 0; i--)
+		if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8) && textures[i]->type == TEXTURETYPE_FLAT)
+		{
+			AddTextureToCache(name, hash, i, TEXTURETYPE_FLAT);
+			return i;
+		}
+
+	return -1;
+}
diff --git a/src/r_textures.h b/src/r_textures.h
index 46b5904d7c63ebbaf0f89796fa7029f499712ccf..ea53efa440f11b64a5b9e78710032a2611d1a36e 100644
--- a/src/r_textures.h
+++ b/src/r_textures.h
@@ -42,9 +42,7 @@ enum
 	TEXTURETYPE_UNKNOWN,
 	TEXTURETYPE_SINGLEPATCH,
 	TEXTURETYPE_COMPOSITE,
-#ifdef WALLFLATS
-	TEXTURETYPE_FLAT,
-#endif
+	TEXTURETYPE_FLAT
 };
 
 // A texture_t describes a rectangular texture,
@@ -82,15 +80,16 @@ void R_FlushTextureCache(void);
 
 // Texture generation
 UINT8 *R_GenerateTexture(size_t texnum);
-UINT8 *R_GenerateTextureAsFlat(size_t texnum);
+UINT8 *R_GetFlatForTexture(size_t texnum);
 INT32 R_GetTextureNum(INT32 texnum);
 void R_CheckTextureCache(INT32 tex);
 void R_ClearTextureNumCache(boolean btell);
 
 // Retrieve texture data.
-void *R_GetLevelFlat(levelflat_t *levelflat);
 column_t *R_GetColumn(fixed_t tex, INT32 col);
-void *R_GetFlat(lumpnum_t flatnum);
+void *R_GetFlat(levelflat_t *levelflat);
+
+INT32 R_GetTextureNumForFlat(levelflat_t *levelflat);
 
 boolean R_CheckPowersOfTwo(void);
 boolean R_CheckSolidColorFlat(void);
@@ -102,7 +101,7 @@ void R_SetFlatVars(size_t length);
 // Returns the texture number for the texture name.
 INT32 R_TextureNumForName(const char *name);
 INT32 R_CheckTextureNumForName(const char *name);
-lumpnum_t R_GetFlatNumForName(const char *name);
+INT32 R_CheckFlatNumForName(const char *name);
 
 // Returns the texture name for the texture number (in case you ever needed it)
 const char *R_CheckTextureNameForNum(INT32 num);