diff --git a/src/filesrch.c b/src/filesrch.c
index ad0cf02a13026dfc7dd109b1ef025061d1e46ca0..9da6d20888307a02d92d68eaa72b0517ba0d7de5 100644
--- a/src/filesrch.c
+++ b/src/filesrch.c
@@ -842,6 +842,8 @@ lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders)
 		if (strstr(fullname, path))
 			fullname += strlen(path) + 1;
 
+		size_t fullnamelength = strlen(fullname);
+
 		// Get the 8-character long lump name.
 		trimname = strrchr(fullname, '/');
 		if (trimname)
@@ -853,21 +855,30 @@ lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders)
 		{
 			char *dotpos = strrchr(trimname, '.');
 			if (dotpos == NULL)
-				dotpos = fullname + strlen(fullname);
+				dotpos = fullname + fullnamelength;
 
 			strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
 
 			// The name of the file, without the extension.
 			lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
 			strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
+			lump_p->longnamelength = strlen(lump_p->longname);
 		}
-		else
+		else {
 			lump_p->longname = Z_Calloc(1, PU_STATIC, NULL);
+			lump_p->longnamelength = 0;
+		}
 
 		// The complete name of the file, with its extension,
 		// excluding the path of the directory where it resides.
 		lump_p->fullname = Z_StrDup(fullname);
-		lump_p->hash = quickncasehash(lump_p->name, 8);
+
+		lump_p->hash.name = W_HashLumpName(lump_p->name);
+		lump_p->hash.fullname = W_HashLumpName(lump_p->fullname);
+		lump_p->hash.longname = W_HashLumpName(lump_p->longname);
+
+		lump_p->namelength = strlen(lump_p->name);
+		lump_p->fullnamelength = fullnamelength;
 
 		lump_p++;
 		i++;
diff --git a/src/g_game.c b/src/g_game.c
index ab1ba8720a7777dbd345b50cda2256d8d8d2af66..5889c5d8c7dc7e9fe9ea46dc62d6fe96494d2370 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -855,30 +855,15 @@ const char *G_BuildClassicMapName(INT32 map)
 	return mapname;
 }
 
-static UINT32 G_HashMapNameString(const char *name, size_t name_length)
+static UINT32 G_HashMapNameString(const char *name)
 {
-	UINT32 hash;
-	size_t i;
-
-	char *buffer = malloc(name_length + 1);
-	if (buffer == NULL)
-		return 0;
-
-	for (i = 0; i < name_length; i++)
-		buffer[i] = tolower(name[i]);
-	buffer[i] = '\0';
-
-	hash = FNV1a_HashString(buffer);
-
-	free(buffer);
-
-	return hash;
+	return FNV1a_HashLowercaseString(name);
 }
 
 static void G_MakeMapName(mapname_t *name, const char *string)
 {
 	name->length = strlen(string);
-	name->hash = G_HashMapNameString(string, name->length);
+	name->hash = G_HashMapNameString(string);
 	name->chars = Z_StrDup(string);
 	strupr(name->chars);
 }
@@ -918,13 +903,13 @@ UINT16 G_GetMapNumber(const char *name)
 {
 	size_t name_length = strlen(name);
 
-	return MapIDForHashedString(name, name_length, G_HashMapNameString(name, name_length));
+	return MapIDForHashedString(name, name_length, G_HashMapNameString(name));
 }
 
 UINT16 G_GetMapNumberForNextMap(const char *name)
 {
 	size_t name_length = strlen(name);
-	UINT32 name_hash = G_HashMapNameString(name, name_length);
+	UINT32 name_hash = G_HashMapNameString(name);
 
 	for (UINT16 i = 0; i < NUM_NEXTMAPS; i++)
 	{
diff --git a/src/m_misc.c b/src/m_misc.c
index 2cf260e949ec63c967d3b4982365085d96d97a13..ad0e8abd3df66a645d149d7bf022f247326fa173 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -2327,3 +2327,17 @@ UINT32 FNV1a_HashString(const char *message)
 
 	return hash;
 }
+
+UINT32 FNV1a_HashLowercaseString(const char *message)
+{
+	UINT32 hash = FNV1A_OFFSET_BASIS;
+
+	while (*message)
+	{
+		hash ^= tolower(*message);
+		hash *= FNV1A_PRIME;
+		message++;
+	}
+
+	return hash;
+}
diff --git a/src/m_misc.h b/src/m_misc.h
index e19b2f3163c9f1324074bb3182043bd928e98535..478e557a5525a81f5d077f64f9b71d8650a8c8b7 100644
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@ -122,6 +122,7 @@ int M_RoundUp(double number);
 // Hashes some message using FNV-1a
 UINT32 FNV1a_Hash(const char *message, size_t size);
 UINT32 FNV1a_HashString(const char *message);
+UINT32 FNV1a_HashLowercaseString(const char *message);
 
 #include "w_wad.h"
 extern char configfile[MAX_WADPATH];
diff --git a/src/w_wad.c b/src/w_wad.c
index 06025b6b1ee4547b6cdaccf6b5788dd6453089c4..f800cb809e5b908f501ec80ad76ff51fd5316f80 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -319,6 +319,11 @@ static void W_InvalidateLumpnumCache(void)
 	memset(lumpnumcache, 0, sizeof (lumpnumcache));
 }
 
+UINT32 W_HashLumpName(const char *name)
+{
+	return FNV1a_HashLowercaseString(name);
+}
+
 /** Detect a file type.
  * \todo Actually detect the wad/pkzip headers and whatnot, instead of just checking the extensions.
  */
@@ -343,18 +348,23 @@ static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const
 	fseek(handle, 0, SEEK_END);
 	lumpinfo->size = ftell(handle);
 	fseek(handle, 0, SEEK_SET);
-	strcpy(lumpinfo->name, lumpname);
-	lumpinfo->hash = quickncasehash(lumpname, 8);
+	strlcpy(lumpinfo->name, lumpname, sizeof(lumpinfo->name));
+	lumpinfo->namelength = strlen(lumpinfo->name);
+	lumpinfo->hash.name = W_HashLumpName(lumpname);
 
 	// Allocate the lump's long name.
-	lumpinfo->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
+	lumpinfo->longname = Z_Malloc((lumpinfo->namelength + 1) * sizeof(char), PU_STATIC, NULL);
 	strcpy(lumpinfo->longname, lumpname);
-	lumpinfo->longname[8] = '\0';
+	lumpinfo->longname[lumpinfo->namelength] = '\0';
+	lumpinfo->longnamelength = lumpinfo->namelength;
+	lumpinfo->hash.longname = lumpinfo->hash.name;
 
 	// Allocate the lump's full name.
-	lumpinfo->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
+	lumpinfo->fullname = Z_Malloc((lumpinfo->namelength + 1) * sizeof(char), PU_STATIC, NULL);
 	strcpy(lumpinfo->fullname, lumpname);
-	lumpinfo->fullname[8] = '\0';
+	lumpinfo->fullname[lumpinfo->namelength] = '\0';
+	lumpinfo->fullnamelength = lumpinfo->namelength;
+	lumpinfo->hash.fullname = lumpinfo->hash.name;
 
 	*numlumps = 1;
 	return lumpinfo;
@@ -443,17 +453,22 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
 			lump_p->compression = CM_NOCOMPRESSION;
 		memset(lump_p->name, 0x00, 9);
 		strncpy(lump_p->name, fileinfo->name, 8);
-		lump_p->hash = quickncasehash(lump_p->name, 8);
+		lump_p->namelength = strlen(lump_p->name);
+		lump_p->hash.name = W_HashLumpName(lump_p->name);
 
 		// Allocate the lump's long name.
 		lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
 		strncpy(lump_p->longname, fileinfo->name, 8);
 		lump_p->longname[8] = '\0';
+		lump_p->longnamelength = lump_p->namelength;
+		lump_p->hash.longname = lump_p->hash.name;
 
 		// Allocate the lump's full name.
 		lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
 		strncpy(lump_p->fullname, fileinfo->name, 8);
 		lump_p->fullname[8] = '\0';
+		lump_p->fullnamelength = lump_p->namelength;
+		lump_p->hash.fullname = lump_p->hash.name;
 	}
 	free(fileinfov);
 	*nlmp = numlumps;
@@ -619,13 +634,18 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 
 		memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
 		strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
-		lump_p->hash = quickncasehash(lump_p->name, 8);
+		lump_p->namelength = strlen(lump_p->name);
+		lump_p->hash.name = W_HashLumpName(lump_p->name);
 
 		lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
 		strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
+		lump_p->longnamelength = strlen(lump_p->longname);
+		lump_p->hash.longname = W_HashLumpName(lump_p->longname);
 
 		lump_p->fullname = Z_Calloc(zentry.namelen + 1, PU_STATIC, NULL);
 		strncpy(lump_p->fullname, fullname, zentry.namelen);
+		lump_p->fullnamelength = zentry.namelen;
+		lump_p->hash.fullname = W_HashLumpName(lump_p->fullname);
 
 		switch(zentry.compression)
 		{
@@ -1230,13 +1250,15 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
 	UINT16 i;
 	static char uname[8 + 1];
 	UINT32 hash;
+	size_t namelen;
 
 	if (!TestValidLump(wad,0))
 		return INT16_MAX;
 
 	strlcpy(uname, name, sizeof uname);
 	strupr(uname);
-	hash = quickncasehash(uname, 8);
+	namelen = strlen(uname);
+	hash = W_HashLumpName(uname);
 
 	//
 	// scan forward
@@ -1247,7 +1269,9 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
 	{
 		lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
 		for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
-			if (lump_p->hash == hash && !strncmp(lump_p->name, uname, sizeof(uname) - 1))
+			if (lump_p->namelength == namelen
+				&& lump_p->hash.name == hash
+				&& !strncmp(lump_p->name, uname, sizeof(uname) - 1))
 				return i;
 	}
 
@@ -1264,13 +1288,12 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
 UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump)
 {
 	UINT16 i;
-	static char uname[256 + 1];
 
 	if (!TestValidLump(wad,0))
 		return INT16_MAX;
 
-	strlcpy(uname, name, sizeof uname);
-	strupr(uname);
+	size_t namelen = strlen(name);
+	UINT32 hash = W_HashLumpName(name);
 
 	//
 	// scan forward
@@ -1281,7 +1304,9 @@ UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump)
 	{
 		lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
 		for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
-			if (!strcmp(lump_p->longname, uname))
+			if (lump_p->longnamelength == namelen
+				&& lump_p->hash.name == hash
+				&& !stricmp(lump_p->longname, name))
 				return i;
 	}
 
@@ -1490,49 +1515,6 @@ lumpnum_t W_CheckNumForLongName(const char *name)
 	}
 }
 
-// Look for valid map data through all added files in descendant order.
-// Get a map marker for WADs, and a standalone WAD file lump inside PK3s.
-// TODO: Make it search through cache first, maybe...?
-lumpnum_t W_CheckNumForMap(const char *name)
-{
-	UINT32 hash = quickncasehash(name, 8);
-	UINT16 lumpNum, end;
-	UINT32 i;
-	lumpinfo_t *p;
-	for (i = numwadfiles - 1; i < numwadfiles; i--)
-	{
-		if (wadfiles[i]->type == RET_WAD)
-		{
-			for (lumpNum = 0; lumpNum < wadfiles[i]->numlumps; lumpNum++)
-			{
-				p = wadfiles[i]->lumpinfo + lumpNum;
-				if (p->hash == hash && !strncmp(name, p->name, 8))
-					return (i<<16) + lumpNum;
-			}
-		}
-		else if (W_FileHasFolders(wadfiles[i]))
-		{
-			lumpNum = W_CheckNumForFolderStartPK3("maps/", i, 0);
-			if (lumpNum != INT16_MAX)
-				end = W_CheckNumForFolderEndPK3("maps/", i, lumpNum);
-			else
-				continue;
-			// Now look for the specified map.
-			for (; lumpNum < end; lumpNum++)
-			{
-				p = wadfiles[i]->lumpinfo + lumpNum;
-				if (p->hash == hash && !strnicmp(name, p->name, 8))
-				{
-					const char *extension = strrchr(p->fullname, '.');
-					if (!(extension && stricmp(extension, ".wad")))
-						return (i<<16) + lumpNum;
-				}
-			}
-		}
-	}
-	return LUMPERROR;
-}
-
 //
 // W_GetNumForName
 //
diff --git a/src/w_wad.h b/src/w_wad.h
index a5b5eee700b26817a7f95a36ab2498f21dad43fc..02868f92f8f475cc2b8baab4f8418137d7402c29 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -66,13 +66,25 @@ typedef struct
 {
 	unsigned long position; // filelump_t filepos
 	unsigned long disksize; // filelump_t size
+
 	char name[9];           // filelump_t name[] e.g. "LongEntr"
-	UINT32 hash;
 	char *longname;         //                   e.g. "LongEntryName"
 	char *fullname;         //                   e.g. "Folder/Subfolder/LongEntryName.extension"
 	char *diskpath;         // path to the file  e.g. "/usr/games/srb2/Addon/Folder/Subfolder/LongEntryName.extension"
+							// NOTE: This is NULL if the WAD type != RET_FOLDER
+
+	size_t namelength;      // length of name
+	size_t longnamelength;  // length of longname
+	size_t fullnamelength;  // length of fullname
+
 	size_t size;            // real (uncompressed) size
 	compmethod compression; // lump compression method
+
+	struct {
+		UINT32 name;        // hash of name
+		UINT32 longname;    // hash of longname
+		UINT32 fullname;    // hash of fullname
+	} hash;
 } lumpinfo_t;
 
 // =========================================================================
@@ -168,6 +180,8 @@ void W_InitMultipleFiles(addfilelist_t *list);
 INT32 W_IsPathToFolderValid(const char *path);
 char *W_GetFullFolderPath(const char *path);
 
+UINT32 W_HashLumpName(const char *name);
+
 const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
 const char *W_CheckNameForNum(lumpnum_t lumpnum);
 
@@ -186,7 +200,6 @@ const char *W_GetFilenameFromFullname(const char *path);
 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);
 
-lumpnum_t W_CheckNumForMap(const char *name);
 lumpnum_t W_CheckNumForName(const char *name);
 lumpnum_t W_CheckNumForLongName(const char *name);
 lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR