diff --git a/src/p_saveg.c b/src/p_saveg.c
index 89447db80ae08d844d3259c0717f4916f7a380c5..c876713e4cca1c0856ea1b79ded396b189cac514 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -781,9 +781,10 @@ static void P_NetArchiveWorld(void)
 	UINT8 *put;
 
 	// reload the map just to see difference
-	mapsector_t *ms;
-	mapsidedef_t *msd;
-	maplinedef_t *mld;
+	virtres_t* virt = vres_GetMap(lastloadedmaplumpnum);
+	mapsector_t  *ms  = (mapsector_t*) vres_Find(virt, "SECTORS")->data;
+	mapsidedef_t *msd = (mapsidedef_t*) vres_Find(virt, "SIDEDEFS")->data;
+	maplinedef_t *mld = (maplinedef_t*) vres_Find(virt, "LINEDEFS")->data;
 	const sector_t *ss = sectors;
 	UINT8 diff, diff2, diff3;
 
@@ -793,26 +794,6 @@ static void P_NetArchiveWorld(void)
 	WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
 	put = save_p;
 
-	if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3
-	{ // HACK: Open wad file rather quickly so we can get the data from the relevant lumps
-		UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC);
-		filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs);
-#define retrieve_mapdata(d, f)\
-		d = Z_Malloc((f)->size, PU_CACHE, NULL); \
-		M_Memcpy(d, wadData + (f)->filepos, (f)->size)
-		retrieve_mapdata(ms, fileinfo + ML_SECTORS);
-		retrieve_mapdata(mld, fileinfo + ML_LINEDEFS);
-		retrieve_mapdata(msd, fileinfo + ML_SIDEDEFS);
-#undef retrieve_mapdata
-		Z_Free(wadData); // we're done with this now
-	}
-	else // phew it's just a WAD
-	{
-			ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE);
-			mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE);
-			msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE);
-	}
-
 	for (i = 0; i < numsectors; i++, ss++, ms++)
 	{
 		diff = diff2 = diff3 = 0;
@@ -1037,6 +1018,7 @@ static void P_NetArchiveWorld(void)
 	WRITEUINT16(put, 0xffff);
 	R_ClearTextureNumCache(false);
 
+	vres_Free(virt);
 	save_p = put;
 }
 
diff --git a/src/p_setup.c b/src/p_setup.c
index 3c45509eeb152ebefab7cb23c54b0ce748188c74..74d33f8f5eb1459f503f1c86a3ab0b4b2485b02a 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1950,7 +1950,7 @@ static boolean P_LoadBlockMap(lumpnum_t lumpnum)
 // because making both the WAD and PK3 loading code use
 // the same functions is trickier than it looks for blockmap
 // -- Monster Iestyn 09/01/18
-static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname)
+static boolean P_LoadRawBlockMap(UINT8 *data, size_t count)
 {
 #if 0
 	(void)data;
@@ -1958,12 +1958,6 @@ static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname
 	(void)lumpname;
 	return false;
 #else
-	// Check if the lump is named "BLOCKMAP"
-	if (!lumpname || memcmp(lumpname, "BLOCKMAP", 8) != 0)
-	{
-		CONS_Printf("No blockmap lump found for pk3!\n");
-		return false;
-	}
 
 	if (!count || count >= 0x20000)
 		return false;
@@ -2120,16 +2114,8 @@ static void P_LoadReject(lumpnum_t lumpnum)
 
 // PK3 version
 // -- Monster Iestyn 09/01/18
-static void P_LoadRawReject(UINT8 *data, size_t count, const char *lumpname)
+static void P_LoadRawReject(UINT8 *data, size_t count)
 {
-	// Check if the lump is named "REJECT"
-	if (!lumpname || memcmp(lumpname, "REJECT\0\0", 8) != 0)
-	{
-		rejectmatrix = NULL;
-		CONS_Debug(DBG_SETUP, "P_LoadRawReject: No valid REJECT lump found\n");
-		return;
-	}
-
 	if (!count) // zero length, someone probably used ZDBSP
 	{
 		rejectmatrix = NULL;
@@ -2892,90 +2878,42 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	P_MakeMapMD5(lastloadedmaplumpnum, &mapmd5);
 
-	// HACK ALERT: Cache the WAD, get the map data into the tables, free memory.
-	// As it is implemented right now, we're assuming an uncompressed WAD.
-	// (As in, a normal PWAD, not ZWAD or anything. The lump itself can be compressed.)
-	// We're not accounting for extra lumps and scrambled lump positions. Any additional data will cause an error.
-	if (W_IsLumpWad(lastloadedmaplumpnum))
-	{
-		// Remember that we're assuming that the WAD will have a specific set of lumps in a specific order.
-		UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC);
-		//filelump_t *fileinfo = wadData + ((wadinfo_t *)wadData)->infotableofs;
-		filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs);
-		UINT32 numlumps = ((wadinfo_t *)wadData)->numlumps;
-
-		if (numlumps < ML_REJECT) // at least 9 lumps should be in the wad for a map to be loaded
-		{
-			I_Error("Bad WAD file for map %s!\n", maplumpname);
-		}
+	if (lastloadedmaplumpnum)
+	{
+		virtres_t* virt = vres_GetMap(lastloadedmaplumpnum);
+		virtlump_t* virtthings   = vres_Find(virt, "THINGS");
+		virtlump_t* virtvertexes = vres_Find(virt, "VERTEXES");
+		virtlump_t* virtsectors  = vres_Find(virt, "SECTORS");
+		virtlump_t* virtsidedefs = vres_Find(virt, "SIDEDEFS");
+		virtlump_t* virtlinedefs = vres_Find(virt, "LINEDEFS");
+
+		virtlump_t* virtssectors = vres_Find(virt, "SSECTORS");
+		virtlump_t* virtsegs     = vres_Find(virt, "SEGS");
+		virtlump_t* virtnodes    = vres_Find(virt, "NODES");
+
+		virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP");
+		virtlump_t* virtreject   = vres_Find(virt, "REJECT");
+
+		P_LoadRawVertexes(virtvertexes->data, virtvertexes->size);
+		P_LoadRawSectors(virtsectors->data, virtsectors->size);
+		P_LoadRawSideDefs(virtsidedefs->size);
+		P_LoadRawLineDefs(virtlinedefs->data, virtlinedefs->size);
+		P_LoadRawSideDefs2(virtsidedefs->data);
+		P_LoadRawSubsectors(virtssectors->data, virtssectors->size);
+		P_LoadRawNodes(virtnodes->data, virtnodes->size);
+		P_LoadRawSegs(virtsegs->data, virtsegs->size);
+
+		if (virtreject)
+			P_LoadRawReject(virtreject->data, virtreject->size);
+		else
+			rejectmatrix = NULL;
 
-		if (numlumps > ML_BLOCKMAP) // enough room for a BLOCKMAP lump at least
-		{
-			loadedbm = P_LoadRawBlockMap(
-							wadData + (fileinfo + ML_BLOCKMAP)->filepos,
-							(fileinfo + ML_BLOCKMAP)->size,
-							(fileinfo + ML_BLOCKMAP)->name);
-		}
-		P_LoadRawVertexes(wadData + (fileinfo + ML_VERTEXES)->filepos, (fileinfo + ML_VERTEXES)->size);
-		P_LoadRawSectors(wadData + (fileinfo + ML_SECTORS)->filepos, (fileinfo + ML_SECTORS)->size);
-		P_LoadRawSideDefs((fileinfo + ML_SIDEDEFS)->size);
-		P_LoadRawLineDefs(wadData + (fileinfo + ML_LINEDEFS)->filepos, (fileinfo + ML_LINEDEFS)->size);
-		P_LoadRawSideDefs2(wadData + (fileinfo + ML_SIDEDEFS)->filepos);
-		P_LoadRawSubsectors(wadData + (fileinfo + ML_SSECTORS)->filepos, (fileinfo + ML_SSECTORS)->size);
-		P_LoadRawNodes(wadData + (fileinfo + ML_NODES)->filepos, (fileinfo + ML_NODES)->size);
-		P_LoadRawSegs(wadData + (fileinfo + ML_SEGS)->filepos, (fileinfo + ML_SEGS)->size);
-		if (numlumps > ML_REJECT) // enough room for a REJECT lump at least
-		{
-			P_LoadRawReject(
-					wadData + (fileinfo + ML_REJECT)->filepos,
-					(fileinfo + ML_REJECT)->size,
-					(fileinfo + ML_REJECT)->name);
-		}
+		if (!(virtblockmap && P_LoadRawBlockMap(virtblockmap->data, virtblockmap->size)))
+			P_CreateBlockMap();
 
-		// Important: take care of the ordering of the next functions.
-		if (!loadedbm)
-			P_CreateBlockMap(); // Graue 02-29-2004
 		P_LoadLineDefs2();
 		P_GroupLines();
-		numdmstarts = numredctfstarts = numbluectfstarts = 0;
 
-		// reset the player starts
-		for (i = 0; i < MAXPLAYERS; i++)
-			playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL;
-
-		for (i = 0; i < MAX_DM_STARTS; i++)
-			deathmatchstarts[i] = NULL;
-
-		for (i = 0; i < 2; i++)
-			skyboxmo[i] = NULL;
-
-		for (i = 0; i < 16; i++)
-			skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL;
-
-		P_MapStart();
-
-		P_PrepareRawThings(wadData + (fileinfo + ML_THINGS)->filepos, (fileinfo + ML_THINGS)->size);
-		Z_Free(wadData);
-	}
-	else
-	{
-		// Important: take care of the ordering of the next functions.
-		loadedbm = P_LoadBlockMap(lastloadedmaplumpnum + ML_BLOCKMAP);
-		P_LoadVertexes(lastloadedmaplumpnum + ML_VERTEXES);
-		P_LoadSectors(lastloadedmaplumpnum + ML_SECTORS);
-		P_LoadSideDefs(lastloadedmaplumpnum + ML_SIDEDEFS);
-		P_LoadLineDefs(lastloadedmaplumpnum + ML_LINEDEFS);
-		P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS);
-		P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS);
-		P_LoadNodes(lastloadedmaplumpnum + ML_NODES);
-		P_LoadSegs(lastloadedmaplumpnum + ML_SEGS);
-		P_LoadReject(lastloadedmaplumpnum + ML_REJECT);
-
-		// Important: take care of the ordering of the next functions.
-		if (!loadedbm)
-			P_CreateBlockMap(); // Graue 02-29-2004
-		P_LoadLineDefs2();
-		P_GroupLines();
 		numdmstarts = numredctfstarts = numbluectfstarts = 0;
 
 		// reset the player starts
@@ -2993,7 +2931,9 @@ boolean P_SetupLevel(boolean skipprecip)
 
 		P_MapStart();
 
-		P_PrepareThings(lastloadedmaplumpnum + ML_THINGS);
+		P_PrepareRawThings(virtthings->data, virtthings->size);
+
+		vres_Free(virt);
 	}
 
 	// init gravity, tag lists,