diff --git a/src/r_textures.c b/src/r_textures.c
index 28f37cdaed2fa0b73bb503b9c8e9a0a8b22748ec..6facb166834fe8b1fa7dae50f6551646be425e9e 100644
--- a/src/r_textures.c
+++ b/src/r_textures.c
@@ -545,17 +545,21 @@ UINT8 *R_GetFlatForTexture(size_t texnum)
 		UINT16 wadnum = patch->wad;
 		lumpnum_t lumpnum = patch->lump;
 		UINT8 *pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
+		size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum);
 
 #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;
+		{
+			texture->flat = Z_Malloc(lumplength, PU_STATIC, NULL);
+			memcpy(texture->flat, pdata, lumplength);
+		}
+
+		Z_SetUser(texture->flat, &texture->flat);
+
+		Z_Free(pdata);
 	}
 	else
 		texture->flat = (UINT8 *)Picture_TextureToFlat(texnum);
@@ -718,7 +722,10 @@ void R_FlushTextureCache(void)
 
 	if (numtextures)
 		for (i = 0; i < numtextures; i++)
+		{
+			Z_Free(textures[i]->flat);
 			Z_Free(texturecache[i]);
+		}
 }
 
 // Need these prototypes for later; defining them here instead of r_textures.h so they're "private"
@@ -728,83 +735,81 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index);
 static INT32
 Rloadflats (INT32 i, INT32 w)
 {
-	UINT16 j;
-	UINT16 texstart, texend;
-	texture_t *texture;
-	texpatch_t *patch;
+	UINT16 j, numlumps = 0;
+	UINT16 texstart = 0, texend = 0;
+	UINT32 *list = NULL;
 #ifndef NO_PNG_LUMPS
 	UINT8 header[PNG_HEADER_SIZE];
 #endif
 
+	// Get every lump inside the Flats/ folder
 	if (W_FileHasFolders(wadfiles[w]))
 	{
-		texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
-		texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
+		W_GetFolderLumpsPwad("Flats/", (UINT16)w, &list, NULL, &numlumps);
 	}
 	else
 	{
+		// Else, get the lumps between F_START/F_END markers
 		texstart = W_CheckNumForMarkerStartPwad("F_START", (UINT16)w, 0);
 		texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
+		if (texstart == INT16_MAX || texend == INT16_MAX)
+			return i;
+
+		numlumps = texend - texstart;
 	}
 
-	if (!( texstart == INT16_MAX || texend == INT16_MAX ))
+	// Now add every entry as a texture
+	for (j = 0; j < numlumps; j++)
 	{
-		// Work through each lump between the markers in the WAD.
-		for (j = 0; j < (texend - texstart); j++)
-		{
-			UINT16 wadnum = (UINT16)w;
-			lumpnum_t lumpnum = texstart + j;
-
-			if (W_FileHasFolders(wadfiles[w]))
-			{
-				if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
-					continue; // If it is then SKIP IT
-			}
+		UINT16 wadnum = list ? WADFILENUM(list[j]) : (UINT16)w;
+		lumpnum_t lumpnum = list ? LUMPNUM(list[j]) : (texstart + j);
 
-			size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum);
-			size_t 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);
+		//CONS_Printf("\n\"%s\" is a flat, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),flatsize,flatsize);
+		texture_t *texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
 
-			// Set texture properties.
-			M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
-			texture->hash = quickncasehash(texture->name, 8);
+		// Set texture properties.
+		M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
+		texture->hash = quickncasehash(texture->name, 8);
 
 #ifndef NO_PNG_LUMPS
-			W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0);
+		W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0);
 
-			if (Picture_IsLumpPNG(header, lumplength))
-			{
-				UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
-				INT32 width, height;
-				Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, NULL, NULL, lumplength);
-				texture->width = (INT16)width;
-				texture->height = (INT16)height;
-				Z_Free(flatlump);
-			}
-			else
+		if (Picture_IsLumpPNG(header, lumplength))
+		{
+			UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
+			INT32 width, height;
+			Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, NULL, NULL, lumplength);
+			texture->width = (INT16)width;
+			texture->height = (INT16)height;
+			Z_Free(flatlump);
+		}
+		else
 #endif
-				texture->width = texture->height = flatsize;
+			texture->width = texture->height = flatsize;
 
-			texture->type = TEXTURETYPE_FLAT;
-			texture->patchcount = 1;
-			texture->flip = 0;
+		texture->type = TEXTURETYPE_FLAT;
+		texture->patchcount = 1;
+		texture->flip = 0;
 
-			// Allocate information for the texture's patches.
-			patch = &texture->patches[0];
+		// Allocate information for the texture's patches.
+		texpatch_t *patch = &texture->patches[0];
 
-			patch->originx = patch->originy = 0;
-			patch->wad = (UINT16)w;
-			patch->lump = texstart + j;
-			patch->flip = 0;
+		patch->originx = patch->originy = 0;
+		patch->wad = wadnum;
+		patch->lump = lumpnum;
+		patch->flip = 0;
 
-			texturewidth[i] = texture->width;
-			textureheight[i] = texture->height << FRACBITS;
-			i++;
-		}
+		texturewidth[i] = texture->width;
+		textureheight[i] = texture->height << FRACBITS;
+		i++;
 	}
 
+	if (list)
+		Z_Free(list);
+
 	return i;
 }
 
@@ -814,17 +819,16 @@ Rloadflats (INT32 i, INT32 w)
 static INT32
 Rloadtextures (INT32 i, INT32 w)
 {
-	UINT16 j;
-	UINT16 texstart, texend, texturesLumpPos;
-	texture_t *texture;
-	texpatch_t *patch;
-	softwarepatch_t patchlump;
+	UINT16 j, numlumps = 0;
+	UINT16 texstart = 0, texend = 0;
+	UINT16 texturesLumpPos;
+	UINT32 *list = NULL;
 
-	// Get the lump numbers for the markers in the WAD, if they exist.
+	// Get every lump inside the Textures/ folder
 	if (W_FileHasFolders(wadfiles[w]))
 	{
-		texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
-		texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
+		W_GetFolderLumpsPwad("Textures/", (UINT16)w, &list, NULL, &numlumps);
+
 		texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
 		while (texturesLumpPos != INT16_MAX)
 		{
@@ -832,79 +836,82 @@ Rloadtextures (INT32 i, INT32 w)
 			texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
 		}
 	}
+	// Else, get the lumps between TX_START/TX_END markers
 	else
 	{
-		texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0);
-		texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
 		texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
 		if (texturesLumpPos != INT16_MAX)
 			R_ParseTEXTURESLump(w, texturesLumpPos, &i);
+
+		texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0);
+		texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, texstart);
+		if (texstart == INT16_MAX || texend == INT16_MAX)
+			return i;
+
+		numlumps = texend - texstart;
 	}
 
-	if (!( texstart == INT16_MAX || texend == INT16_MAX ))
+	// Now add every entry as a texture
+	for (j = 0; j < numlumps; j++)
 	{
-		// Work through each lump between the markers in the WAD.
-		for (j = 0; j < (texend - texstart); j++)
-		{
-			UINT16 wadnum = (UINT16)w;
-			lumpnum_t lumpnum = texstart + j;
+		UINT16 wadnum = list ? WADFILENUM(list[j]) : (UINT16)w;
+		lumpnum_t lumpnum = list ? LUMPNUM(list[j]) : (texstart + j);
+
+		softwarepatch_t patchlump;
+
 #ifndef NO_PNG_LUMPS
-			size_t lumplength;
+		size_t lumplength;
 #endif
 
-			if (W_FileHasFolders(wadfiles[w]))
-			{
-				if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
-					continue; // If it is then SKIP IT
-			}
-
-			W_ReadLumpHeaderPwad(wadnum, lumpnum, &patchlump, PNG_HEADER_SIZE, 0);
+		W_ReadLumpHeaderPwad(wadnum, lumpnum, &patchlump, PNG_HEADER_SIZE, 0);
 #ifndef NO_PNG_LUMPS
-			lumplength = W_LumpLengthPwad(wadnum, lumpnum);
+		lumplength = W_LumpLengthPwad(wadnum, lumpnum);
 #endif
 
-			//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
-			texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
+		//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
+		texture_t *texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
 
-			// Set texture properties.
-			M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
-			texture->hash = quickncasehash(texture->name, 8);
+		// Set texture properties.
+		M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
+		texture->hash = quickncasehash(texture->name, 8);
 
 #ifndef NO_PNG_LUMPS
-			if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength))
-			{
-				UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
-				INT32 width, height;
-				Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength);
-				texture->width = (INT16)width;
-				texture->height = (INT16)height;
-				Z_Free(png);
-			}
-			else
+		if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength))
+		{
+			UINT8 *png = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
+			INT32 width, height;
+			Picture_PNGDimensions(png, &width, &height, NULL, NULL, lumplength);
+			texture->width = (INT16)width;
+			texture->height = (INT16)height;
+			Z_Free(png);
+		}
+		else
 #endif
-			{
-				texture->width = SHORT(patchlump.width);
-				texture->height = SHORT(patchlump.height);
-			}
+		{
+			texture->width = SHORT(patchlump.width);
+			texture->height = SHORT(patchlump.height);
+		}
 
-			texture->type = TEXTURETYPE_SINGLEPATCH;
-			texture->patchcount = 1;
-			texture->flip = 0;
+		texture->type = TEXTURETYPE_SINGLEPATCH;
+		texture->patchcount = 1;
+		texture->flip = 0;
 
-			// Allocate information for the texture's patches.
-			patch = &texture->patches[0];
+		// Allocate information for the texture's patches.
+		texpatch_t *patch = &texture->patches[0];
 
-			patch->originx = patch->originy = 0;
-			patch->wad = (UINT16)w;
-			patch->lump = texstart + j;
-			patch->flip = 0;
+		patch->originx = patch->originy = 0;
+		patch->wad = wadnum;
+		patch->lump = lumpnum;
+		patch->flip = 0;
 
-			texturewidth[i] = texture->width;
-			textureheight[i] = texture->height << FRACBITS;
-			i++;
-		}
+		texturewidth[i] = texture->width;
+		textureheight[i] = texture->height << FRACBITS;
+		i++;
 	}
 
+	if (list)
+		Z_Free(list);
+
 	return i;
 }
 
@@ -915,37 +922,17 @@ count_range
 		const char * folder,
 		UINT16 wadnum)
 {
-	UINT16 j;
-	UINT16 texstart, texend;
 	INT32 count = 0;
 
-	// Count flats
 	if (W_FileHasFolders(wadfiles[wadnum]))
-	{
-		texstart = W_CheckNumForFolderStartPK3(folder, wadnum, 0);
-		texend = W_CheckNumForFolderEndPK3(folder, wadnum, texstart);
-	}
+		count += W_CountFolderLumpsPwad(folder, wadnum);
 	else
 	{
-		texstart = W_CheckNumForMarkerStartPwad(marker_start, wadnum, 0);
-		texend = W_CheckNumForNamePwad(marker_end, wadnum, texstart);
-	}
+		UINT16 texstart = W_CheckNumForMarkerStartPwad(marker_start, wadnum, 0);
+		UINT16 texend = W_CheckNumForNamePwad(marker_end, wadnum, texstart);
 
-	if (texstart != INT16_MAX && texend != INT16_MAX)
-	{
-		// PK3s have subfolders, so we can't just make a simple sum
-		if (W_FileHasFolders(wadfiles[wadnum]))
-		{
-			for (j = texstart; j < texend; j++)
-			{
-				if (!W_IsLumpFolder(wadnum, j)) // Check if lump is a folder; if not, then count it
-					count++;
-			}
-		}
-		else // Add all the textures between markers
-		{
+		if (texstart != INT16_MAX && texend != INT16_MAX)
 			count += (texend - texstart);
-		}
 	}
 
 	return count;
diff --git a/src/w_wad.c b/src/w_wad.c
index 07573102a04810cdd279673d080232670dd94bfd..629e0b0b4bfcc47f498713041c3b43d8ded3a949 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -1335,6 +1335,72 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
 	return i;
 }
 
+void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps)
+{
+	size_t name_length = strlen(name);
+	lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo;
+
+	UINT16 capacity = list_capacity ? *list_capacity : 0;
+	UINT16 count = *numlumps;
+
+	for (UINT16 i = 0; i < wadfiles[wad]->numlumps; i++, lump_p++)
+	{
+		if (strnicmp(name, lump_p->fullname, name_length) == 0)
+		{
+			if (strlen(lump_p->fullname) > name_length)
+			{
+				if (!capacity || count >= capacity)
+				{
+					capacity = capacity ? (capacity * 2) : 16;
+					*list = Z_Realloc(*list, capacity * sizeof(UINT32), PU_STATIC, NULL);
+				}
+
+				(*list)[count] = (wad << 16) + i;
+				count++;
+			}
+		}
+	}
+
+	if (list_capacity)
+		(*list_capacity) = capacity;
+	(*numlumps) = count;
+}
+
+void W_GetFolderLumps(const char *name, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps)
+{
+	for (UINT16 i = 0; i < numwadfiles; i++)
+		W_GetFolderLumpsPwad(name, i, list, list_capacity, numlumps);
+}
+
+UINT32 W_CountFolderLumpsPwad(const char *name, UINT16 wad)
+{
+	size_t name_length = strlen(name);
+	lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo;
+
+	UINT32 count = 0;
+
+	for (UINT16 i = 0; i < wadfiles[wad]->numlumps; i++, lump_p++)
+	{
+		if (strnicmp(name, lump_p->fullname, name_length) == 0)
+		{
+			if (strlen(lump_p->fullname) > name_length)
+				count++;
+		}
+	}
+
+	return count;
+}
+
+UINT32 W_CountFolderLumps(const char *name)
+{
+	UINT32 count = 0;
+
+	for (UINT16 i = 0; i < numwadfiles; i++)
+		count += W_CountFolderLumpsPwad(name, i);
+
+	return count;
+}
+
 // In a PK3 type of resource file, it looks for an entry with the specified full name.
 // Returns lump position in PK3's lumpinfo, or INT16_MAX if not found.
 UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump)
diff --git a/src/w_wad.h b/src/w_wad.h
index 4c0f9b31465967458334d37c7d7babc2ef2daa4b..52a64d0a23ab79b958c890659687461948ec2041 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -181,6 +181,11 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump);
 UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump);
 UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump);
 
+void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps);
+void W_GetFolderLumps(const char *name, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps);
+UINT32 W_CountFolderLumpsPwad(const char *name, UINT16 wad);
+UINT32 W_CountFolderLumps(const char *name);
+
 lumpnum_t W_CheckNumForMap(const char *name);
 lumpnum_t W_CheckNumForName(const char *name);
 lumpnum_t W_CheckNumForLongName(const char *name);