diff --git a/src/f_finale.c b/src/f_finale.c
index 317a57f3d385efdaa1795788bbf96390588b9ddf..bbee48bdc2a52d69033c92f285f17c0338cca45b 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -3790,7 +3790,7 @@ void F_ContinueDrawer(void)
 								sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\
 								sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\
 								patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH);\
-								V_DrawFixedPatch((dx), (dy), FRACUNIT, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\
+								V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\
 							}
 
 	if (offsy < 0)
diff --git a/src/f_wipe.c b/src/f_wipe.c
index a83d104f24ed09696cdf10ea33885b64242e0191..a350e0f36c646169d31e373ebd6b46f4c49cc466 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -2,7 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1993-1996 by id Software, Inc.
 // Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 2013-2016 by Matthew "Inuyasha" Walsh.
+// Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh.
 // Copyright (C) 1999-2019 by Sonic Team Junior.
 //
 // This program is free software distributed under the
diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c
index c47833187b1af03f7308d3844fbcce51baa22bd0..ccffc8a4934785012b617cd8696dd88c35ad6116 100644
--- a/src/hardware/hw_cache.c
+++ b/src/hardware/hw_cache.c
@@ -122,11 +122,11 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
 			if (mipmap->colormap)
 				texel = mipmap->colormap[texel];
 
-			// transparent pixel
-			if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)
+			// If the mipmap is chromakeyed, check if the texel's color
+			// is equivalent to the chroma key's color index.
+			alpha = 0xff;
+			if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX))
 				alpha = 0x00;
-			else
-				alpha = 0xff;
 
 			// hope compiler will get this switch out of the loops (dreams...)
 			// gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?)
@@ -654,7 +654,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
 
 #ifndef NO_PNG_LUMPS
 		if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
-			realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false);
+			realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL);
 		else
 #endif
 #ifdef WALLFLATS
@@ -698,7 +698,7 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
 	// lump is a png so convert it
 	size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
 	if ((patch != NULL) && R_IsLumpPNG((const UINT8 *)patch, len))
-		patch = R_PNGToPatch((const UINT8 *)patch, len, NULL, true);
+		patch = R_PNGToPatch((const UINT8 *)patch, len, NULL);
 #endif
 
 	// don't do it twice (like a cache)
@@ -1324,23 +1324,6 @@ GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum)
 	return HWR_GetCachedGLPatchPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum));
 }
 
-#ifdef ROTSPRITE
-GLPatch_t *HWR_GetCachedGLRotSprite(aatree_t *hwrcache, UINT16 rollangle, patch_t *rawpatch)
-{
-	GLPatch_t *grpatch;
-
-	if (!(grpatch = M_AATreeGet(hwrcache, rollangle)))
-	{
-		grpatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL);
-		grpatch->rawpatch = rawpatch;
-		grpatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL);
-		M_AATreeSet(hwrcache, rollangle, grpatch);
-	}
-
-	return grpatch;
-}
-#endif
-
 // Need to do this because they aren't powers of 2
 static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 pblockheight,
 	lumpnum_t fademasklumpnum, UINT16 fmwidth, UINT16 fmheight)
diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h
index cf98e731739ce59016dd6347f531a1079c59f813..a2bf79817ac15f1b85740dfbe20bd121cd2e880d 100644
--- a/src/hardware/hw_glob.h
+++ b/src/hardware/hw_glob.h
@@ -113,9 +113,6 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum);
 void HWR_SetPalette(RGBA_t *palette);
 GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
 GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
-#ifdef ROTSPRITE
-GLPatch_t *HWR_GetCachedGLRotSprite(aatree_t *hwrcache, UINT16 rollangle, patch_t *rawpatch);
-#endif
 void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
 
 // --------
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 3800b6ad98ff9b89af7ee38a7c328a87abcbf580..3f0575dd909c60ec3d34b4b830fb70efebb8dcec 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -1108,7 +1108,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
 	{
 		sector_t *sector = spr->mobj->subsector->sector;
 		UINT8 lightlevel = 255;
-		extracolormap_t *colormap = sector->extra_colormap;
+		extracolormap_t *colormap = NULL;
 
 		if (sector->numlights)
 		{
@@ -1145,6 +1145,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
 		INT32 durs = spr->mobj->state->tics;
 		INT32 tics = spr->mobj->tics;
 		//mdlframe_t *next = NULL;
+		const boolean papersprite = (spr->mobj->frame & FF_PAPERSPRITE);
 		const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP));
 		spritedef_t *sprdef;
 		spriteframe_t *sprframe;
@@ -1361,14 +1362,12 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
 
 		sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK];
 
-		if (sprframe->rotate)
+		if (sprframe->rotate || papersprite)
 		{
 			fixed_t anglef = AngleFixed(spr->mobj->angle);
 
 			if (spr->mobj->player)
 				anglef = AngleFixed(spr->mobj->player->drawangle);
-			else
-				anglef = AngleFixed(spr->mobj->angle);
 
 			p.angley = FIXED_TO_FLOAT(anglef);
 		}
diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index 97b3b98be576753f7b815ce3e49d7c3f825e319e..327dbd3df2ac6e64a446c15e16cfe331c07fe981 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -2273,14 +2273,30 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
 
 EXPORT INT32  HWRAPI(GetTextureUsed) (void)
 {
-	FTextureInfo*   tmp = gr_cachehead;
-	INT32             res = 0;
+	FTextureInfo *tmp = gr_cachehead;
+	INT32 res = 0;
 
 	while (tmp)
 	{
-		res += tmp->height*tmp->width*(screen_depth/8);
+		// Figure out the correct bytes-per-pixel for this texture
+		// I don't know which one the game actually _uses_ but this
+		// follows format2bpp in hw_cache.c
+		int bpp = 1;
+		int format = tmp->grInfo.format;
+		if (format == GR_RGBA)
+			bpp = 4;
+		else if (format == GR_TEXFMT_RGB_565
+			|| format == GR_TEXFMT_ARGB_1555
+			|| format == GR_TEXFMT_ARGB_4444
+			|| format == GR_TEXFMT_ALPHA_INTENSITY_88
+			|| format == GR_TEXFMT_AP_88)
+			bpp = 2;
+
+		// Add it up!
+		res += tmp->height*tmp->width*bpp;
 		tmp = tmp->nextmipmap;
 	}
+
 	return res;
 }
 
diff --git a/src/m_anigif.c b/src/m_anigif.c
index f761db143b0cb016ee0395e9f045c8cdeb49d444..32fc2746da54caa831cda304053c73a2519b55db 100644
--- a/src/m_anigif.c
+++ b/src/m_anigif.c
@@ -1,6 +1,6 @@
 // SONIC ROBO BLAST 2
 //-----------------------------------------------------------------------------
-// Copyright (C) 2013-2016 by Matthew "Inuyasha" Walsh.
+// Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh.
 // Copyright (C) 2013      by "Ninji".
 // Copyright (C) 2013-2019 by Sonic Team Junior.
 //
diff --git a/src/m_anigif.h b/src/m_anigif.h
index 592d2cf19a8d2f1aceb8f26336e272fdbbfa5c87..9bdf2cc7f22701c6a2a35eff4580ba299379a565 100644
--- a/src/m_anigif.h
+++ b/src/m_anigif.h
@@ -1,6 +1,6 @@
 // SONIC ROBO BLAST 2
 //-----------------------------------------------------------------------------
-// Copyright (C) 2013-2016 by Matthew "Inuyasha" Walsh.
+// Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh.
 // Copyright (C) 2013-2019 by Sonic Team Junior.
 //
 // This program is free software distributed under the
diff --git a/src/m_cond.c b/src/m_cond.c
index 1e761fdb4a5134d0f8102e02083725a673b26c0e..08f3fe03874294e83dd71fc750a5670f69e0eb54 100644
--- a/src/m_cond.c
+++ b/src/m_cond.c
@@ -1,6 +1,6 @@
 // SONIC ROBO BLAST 2
 //-----------------------------------------------------------------------------
-// Copyright (C) 2012-2016 by Matthew "Inuyasha" Walsh.
+// Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh.
 // Copyright (C) 2012-2019 by Sonic Team Junior.
 //
 // This program is free software distributed under the
diff --git a/src/m_cond.h b/src/m_cond.h
index 3ea77145d4651f4081b088431ad505144ddff222..f4f017787c7611d71802049243fb9725ee4baf70 100644
--- a/src/m_cond.h
+++ b/src/m_cond.h
@@ -1,6 +1,6 @@
 // SONIC ROBO BLAST 2
 //-----------------------------------------------------------------------------
-// Copyright (C) 2012-2016 by Matthew "Inuyasha" Walsh.
+// Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh.
 // Copyright (C) 2012-2019 by Sonic Team Junior.
 //
 // This program is free software distributed under the
diff --git a/src/m_menu.c b/src/m_menu.c
index bf7325fc51557258e25156ace06481514aa48868..1dcd4ef0f767a0776a7c64dc5ef20eadbaa24c86 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -2,7 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1993-1996 by id Software, Inc.
 // Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 2011-2016 by Matthew "Inuyasha" Walsh.
+// Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh.
 // Copyright (C) 1999-2019 by Sonic Team Junior.
 //
 // This program is free software distributed under the
diff --git a/src/m_menu.h b/src/m_menu.h
index 78586b11df47f8565a7af6431bb2ed5361b2d583..a563a18dcf4e08e909831a765609bea8ac1f7bc0 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -2,7 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1993-1996 by id Software, Inc.
 // Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 2011-2016 by Matthew "Inuyasha" Walsh.
+// Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh.
 // Copyright (C) 1999-2019 by Sonic Team Junior.
 //
 // This program is free software distributed under the
diff --git a/src/m_random.c b/src/m_random.c
index 8a7b62b196ce8f944c66adf59232138692dbd0c1..8fd0e1e4e011d21566611db643763063bc28c668 100644
--- a/src/m_random.c
+++ b/src/m_random.c
@@ -2,7 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1993-1996 by id Software, Inc.
 // Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 2012-2016 by Matthew "Inuyasha" Walsh.
+// Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh.
 // Copyright (C) 1999-2019 by Sonic Team Junior.
 //
 // This program is free software distributed under the
diff --git a/src/m_random.h b/src/m_random.h
index fb14249bca4266cc42b4f8e4fa3db8c82b9d14f6..5efd3e02ca9cf96f2cd86574c9eca5d788cbc444 100644
--- a/src/m_random.h
+++ b/src/m_random.h
@@ -2,7 +2,7 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1993-1996 by id Software, Inc.
 // Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 2012-2016 by Matthew "Inuyasha" Walsh.
+// Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh.
 // Copyright (C) 1999-2019 by Sonic Team Junior.
 //
 // This program is free software distributed under the
diff --git a/src/r_data.c b/src/r_data.c
index 986b65deaca333a80d059d72f7875fd6c575116b..d35777664645d99a7d557dc222a52793b3213c31 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -571,7 +571,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);
+			realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL);
 		else
 #endif
 #ifdef WALLFLATS
diff --git a/src/r_defs.h b/src/r_defs.h
index c7c198d662e2713db2ce93716f40dfd68bc3a8d8..176f33c4f9a22adf72e2bf414ae7df79b428a695 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -729,9 +729,6 @@ typedef struct
 {
 	patch_t *patch[8][ROTANGLES];
 	boolean cached[8];
-#ifdef HWRENDER
-	aatree_t *hardware_patch[8];
-#endif/*HWRENDER*/
 } rotsprite_t;
 #endif/*ROTSPRITE*/
 
diff --git a/src/r_patch.c b/src/r_patch.c
index fbb64e3621a266f3febab774f4c66b52a4a60615..13414aae40960f12b9d849335362d97a39e1f83b 100644
--- a/src/r_patch.c
+++ b/src/r_patch.c
@@ -2,8 +2,8 @@
 //-----------------------------------------------------------------------------
 // Copyright (C) 1993-1996 by id Software, Inc.
 // Copyright (C) 2005-2009 by Andrey "entryway" Budko.
-// Copyright (C) 2018-2019 by Jaime "Lactozilla" Passos.
-// Copyright (C) 2019      by Sonic Team Junior.
+// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos.
+// Copyright (C) 2019-2020 by Sonic Team Junior.
 //
 // This program is free software distributed under the
 // terms of the GNU General Public License, version 2.
@@ -199,11 +199,15 @@ void R_PatchToFlat(patch_t *patch, UINT8 *flat)
 }
 
 //
-// R_PatchToFlat_16bpp
+// R_PatchToMaskedFlat
 //
-// Convert a patch to a 16-bit flat.
+// Convert a patch to a masked flat.
+// Now, what is a "masked" flat anyway?
+// It means the flat uses two bytes to store image data.
+// The upper byte is used to store the transparent pixel,
+// and the lower byte stores a palette index.
 //
-void R_PatchToFlat_16bpp(patch_t *patch, UINT16 *raw, boolean flip)
+void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip)
 {
 	fixed_t col, ofs;
 	column_t *column;
@@ -248,6 +252,9 @@ patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffse
 	UINT8 *colpointers, *startofspan;
 	size_t size = 0;
 
+	if (!raw)
+		return NULL;
+
 	// Write image size and offset
 	WRITEINT16(imgptr, width);
 	WRITEINT16(imgptr, height);
@@ -347,16 +354,18 @@ patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffse
 }
 
 //
-// R_FlatToPatch_16bpp
+// R_MaskedFlatToPatch
 //
-// Convert a 16-bit flat to a patch.
+// Convert a masked flat to a patch.
+// Explanation of "masked" flats in R_PatchToMaskedFlat.
 //
-patch_t *R_FlatToPatch_16bpp(UINT16 *raw, UINT16 width, UINT16 height, size_t *size)
+patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize)
 {
 	UINT32 x, y;
 	UINT8 *img;
 	UINT8 *imgptr = imgbuf;
 	UINT8 *colpointers, *startofspan;
+	size_t size = 0;
 
 	if (!raw)
 		return NULL;
@@ -364,9 +373,8 @@ patch_t *R_FlatToPatch_16bpp(UINT16 *raw, UINT16 width, UINT16 height, size_t *s
 	// Write image size and offset
 	WRITEINT16(imgptr, width);
 	WRITEINT16(imgptr, height);
-	// no offsets
-	WRITEINT16(imgptr, 0);
-	WRITEINT16(imgptr, 0);
+	WRITEINT16(imgptr, leftoffset);
+	WRITEINT16(imgptr, topoffset);
 
 	// Leave placeholder to column pointers
 	colpointers = imgptr;
@@ -450,9 +458,12 @@ patch_t *R_FlatToPatch_16bpp(UINT16 *raw, UINT16 width, UINT16 height, size_t *s
 		WRITEUINT8(imgptr, 0xFF);
 	}
 
-	*size = imgptr-imgbuf;
-	img = Z_Malloc(*size, PU_STATIC, NULL);
-	memcpy(img, imgbuf, *size);
+	size = imgptr-imgbuf;
+	img = Z_Malloc(size, PU_STATIC, NULL);
+	memcpy(img, imgbuf, size);
+
+	if (destsize != NULL)
+		*destsize = size;
 	return (patch_t *)img;
 }
 
@@ -675,6 +686,41 @@ static UINT8 *PNG_RawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topo
 	return flat;
 }
 
+// Convert a PNG with transparency to a raw image.
+static UINT16 *PNG_MaskedRawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size)
+{
+	UINT16 *flat;
+	png_uint_32 x, y;
+	png_bytep *row_pointers = PNG_Read(png, w, h, topoffset, leftoffset, size);
+	png_uint_32 width = *w, height = *h;
+	size_t flatsize, i;
+
+	if (!row_pointers)
+		I_Error("PNG_MaskedRawConvert: conversion failed");
+
+	// Convert the image to 16bpp
+	flatsize = (width * height);
+	flat = Z_Malloc(flatsize * sizeof(UINT16), PU_LEVEL, NULL);
+
+	// can't memset here
+	for (i = 0; i < flatsize; i++)
+		flat[i] = 0xFF00;
+
+	for (y = 0; y < height; y++)
+	{
+		png_bytep row = row_pointers[y];
+		for (x = 0; x < width; x++)
+		{
+			png_bytep px = &(row[x * 4]);
+			if ((UINT8)px[3])
+				flat[((y * width) + x)] = NearestColor((UINT8)px[0], (UINT8)px[1], (UINT8)px[2]);
+		}
+	}
+	free(row_pointers);
+
+	return flat;
+}
+
 //
 // R_PNGToFlat
 //
@@ -690,16 +736,16 @@ UINT8 *R_PNGToFlat(UINT16 *width, UINT16 *height, UINT8 *png, size_t size)
 //
 // Convert a PNG to a patch.
 //
-patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency)
+patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize)
 {
 	UINT16 width, height;
 	INT16 topoffset = 0, leftoffset = 0;
-	UINT8 *raw = PNG_RawConvert(png, &width, &height, &topoffset, &leftoffset, size);
+	UINT16 *raw = PNG_MaskedRawConvert(png, &width, &height, &topoffset, &leftoffset, size);
 
 	if (!raw)
 		I_Error("R_PNGToPatch: conversion failed");
 
-	return R_FlatToPatch(raw, width, height, leftoffset, topoffset, destsize, transparency);
+	return R_MaskedFlatToPatch(raw, width, height, leftoffset, topoffset, destsize);
 }
 
 //
@@ -1150,7 +1196,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
 	INT32 angle;
 	patch_t *patch;
 	patch_t *newpatch;
-	UINT16 *rawdst;
+	UINT16 *rawsrc, *rawdst;
 	size_t size;
 	INT32 bflip = (flip != 0x00);
 
@@ -1196,6 +1242,17 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
 			leftoffset = width - leftoffset;
 		}
 
+		// Draw the sprite to a temporary buffer.
+		size = (width*height);
+		rawsrc = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL);
+
+		// can't memset here
+		for (i = 0; i < size; i++)
+			rawsrc[i] = 0xFF00;
+
+		R_PatchToMaskedFlat(patch, rawsrc, bflip);
+
+		// Don't cache angle = 0
 		for (angle = 1; angle < ROTANGLES; angle++)
 		{
 			INT32 newwidth, newheight;
@@ -1287,7 +1344,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
 			}
 
 			// make patch
-			newpatch = R_FlatToPatch_16bpp(rawdst, newwidth, newheight, &size);
+			newpatch = R_MaskedFlatToPatch(rawdst, newwidth, newheight, 0, 0, &size);
 			{
 				newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px);
 				newpatch->topoffset = (newpatch->height / 2) + (patch->topoffset - py);
@@ -1303,9 +1360,11 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
 #ifdef HWRENDER
 			if (rendermode == render_opengl)
 			{
-				GLPatch_t *grPatch = HWR_GetCachedGLRotSprite(sprframe->rotsprite.hardware_patch[rot], angle, newpatch);
-				HWR_MakePatch(newpatch, grPatch, grPatch->mipmap, false);
+				GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL);
+				grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL);
+				grPatch->rawpatch = newpatch;
 				sprframe->rotsprite.patch[rot][angle] = (patch_t *)grPatch;
+				HWR_MakePatch(newpatch, grPatch, grPatch->mipmap, false);
 			}
 			else
 #endif // HWRENDER
diff --git a/src/r_patch.h b/src/r_patch.h
index 2961448a0bc10d1401ae5bf39e8dc06f6664a30f..e743a7d097c057f2b9d3892a72f2b96622c2b176 100644
--- a/src/r_patch.h
+++ b/src/r_patch.h
@@ -41,9 +41,9 @@ typedef struct
 boolean R_CheckIfPatch(lumpnum_t lump);
 void R_TextureToFlat(size_t tex, UINT8 *flat);
 void R_PatchToFlat(patch_t *patch, UINT8 *flat);
-void R_PatchToFlat_16bpp(patch_t *patch, UINT16 *raw, boolean flip);
+void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip);
 patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency);
-patch_t *R_FlatToPatch_16bpp(UINT16 *raw, UINT16 width, UINT16 height, size_t *size);
+patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize);
 
 // Portable Network Graphics
 boolean R_IsLumpPNG(const UINT8 *d, size_t s);
@@ -51,7 +51,7 @@ boolean R_IsLumpPNG(const UINT8 *d, size_t s);
 
 #ifndef NO_PNG_LUMPS
 UINT8 *R_PNGToFlat(UINT16 *width, UINT16 *height, UINT8 *png, size_t size);
-patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency);
+patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize);
 boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size);
 #endif
 
diff --git a/src/r_things.c b/src/r_things.c
index 927d199a54b361bc836ec4e9bc15e886010bf1d0..8458d983570ccde2efef319330a130a94388c5e0 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -125,9 +125,6 @@ static void R_InstallSpriteLump(UINT16 wad,            // graphics patch
 		sprtemp[frame].rotsprite.cached[r] = false;
 		for (ang = 0; ang < ROTANGLES; ang++)
 			sprtemp[frame].rotsprite.patch[r][ang] = NULL;
-#ifdef HWRENDER
-		sprtemp[frame].rotsprite.hardware_patch[r] = M_AATreeAlloc(AATREE_ZUSER);
-#endif/*HWRENDER*/
 	}
 #endif/*ROTSPRITE*/
 
@@ -284,7 +281,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
 				// lump is a png so convert it
 				if (R_IsLumpPNG((UINT8 *)png, len))
 				{
-					png = R_PNGToPatch((UINT8 *)png, len, NULL, true);
+					png = R_PNGToPatch((UINT8 *)png, len, NULL);
 					M_Memcpy(&patch, png, sizeof(INT16)*4);
 				}
 				Z_Free(png);
diff --git a/src/w_wad.c b/src/w_wad.c
index 1aa2814264935ac92aa3c11d425142fe5795836a..dc400987f23a4aaabe98ae66d46dd874d2c54556 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -1465,6 +1465,21 @@ boolean W_IsPatchCached(lumpnum_t lumpnum, void *ptr)
 	return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr);
 }
 
+void W_FlushCachedPatches(void)
+{
+	if (needpatchflush)
+	{
+		Z_FreeTag(PU_CACHE);
+		Z_FreeTag(PU_PATCH);
+		Z_FreeTag(PU_HUDGFX);
+		Z_FreeTag(PU_HWRPATCHINFO);
+		Z_FreeTag(PU_HWRMODELTEXTURE);
+		Z_FreeTag(PU_HWRCACHE);
+		Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRPATCHINFO_UNLOCKED);
+	}
+	needpatchflush = false;
+}
+
 // ==========================================================================
 // W_CacheLumpName
 // ==========================================================================
@@ -1488,22 +1503,6 @@ void *W_CacheLumpName(const char *name, INT32 tag)
 // Cache a patch into heap memory, convert the patch format as necessary
 //
 
-void W_FlushCachedPatches(void)
-{
-	if (needpatchflush)
-	{
-		Z_FreeTag(PU_CACHE);
-		Z_FreeTag(PU_PATCH);
-		Z_FreeTag(PU_HUDGFX);
-		Z_FreeTag(PU_HWRPATCHINFO);
-		Z_FreeTag(PU_HWRMODELTEXTURE);
-		Z_FreeTag(PU_HWRCACHE);
-		Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRPATCHINFO_UNLOCKED);
-	}
-	needpatchflush = false;
-}
-
-// Software-only compile cache the data without conversion
 void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
 {
 #ifdef HWRENDER
@@ -1541,7 +1540,7 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
 			if (R_IsLumpPNG((UINT8 *)lumpdata, len))
 			{
 				size_t newlen;
-				srcdata = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen, true);
+				srcdata = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen);
 				ptr = Z_Realloc(ptr, newlen, tag, &lumpcache[lump]);
 				M_Memcpy(ptr, srcdata, newlen);
 				Z_Free(srcdata);