diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c
index fe0b65c5021c0a8ef7db1ae189ad37709f76d33d..3e207025c15179bac7429987305e7ac895c9280a 100644
--- a/src/hardware/hw_cache.c
+++ b/src/hardware/hw_cache.c
@@ -804,45 +804,18 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex)
 
 static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
 {
-	size_t size, pflatsize;
+	size_t size = W_LumpLength(flatlumpnum);
+	UINT16 pflatsize = R_GetFlatSize(size);
 
 	// setup the texture info
 	grMipmap->format = GL_TEXFMT_P_8;
 	grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
 
-	size = W_LumpLength(flatlumpnum);
-
-	switch (size)
-	{
-		case 4194304: // 2048x2048 lump
-			pflatsize = 2048;
-			break;
-		case 1048576: // 1024x1024 lump
-			pflatsize = 1024;
-			break;
-		case 262144:// 512x512 lump
-			pflatsize = 512;
-			break;
-		case 65536: // 256x256 lump
-			pflatsize = 256;
-			break;
-		case 16384: // 128x128 lump
-			pflatsize = 128;
-			break;
-		case 1024: // 32x32 lump
-			pflatsize = 32;
-			break;
-		default: // 64x64 lump
-			pflatsize = 64;
-			break;
-	}
-
-	grMipmap->width  = (UINT16)pflatsize;
-	grMipmap->height = (UINT16)pflatsize;
+	grMipmap->width = pflatsize;
+	grMipmap->height = pflatsize;
 
 	// the flat raw data needn't be converted with palettized textures
-	W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
-		PU_HWRCACHE, &grMipmap->data));
+	W_ReadLump(flatlumpnum, Z_Malloc(size, PU_HWRCACHE, &grMipmap->data));
 }
 
 static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c
index 691e3cd3f0c70d76b0a015f3f3ee36196361a436..ada2a6bf8dab732367b30557e4828fbcbf464e93 100644
--- a/src/hardware/hw_draw.c
+++ b/src/hardware/hw_draw.c
@@ -705,42 +705,10 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
 // --------------------------------------------------------------------------
 void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
 {
-	FOutVector  v[4];
-	double dflatsize;
-	INT32 flatflag;
+	FOutVector v[4];
 	const size_t len = W_LumpLength(flatlumpnum);
-
-	switch (len)
-	{
-		case 4194304: // 2048x2048 lump
-			dflatsize = 2048.0f;
-			flatflag = 2047;
-			break;
-		case 1048576: // 1024x1024 lump
-			dflatsize = 1024.0f;
-			flatflag = 1023;
-			break;
-		case 262144:// 512x512 lump
-			dflatsize = 512.0f;
-			flatflag = 511;
-			break;
-		case 65536: // 256x256 lump
-			dflatsize = 256.0f;
-			flatflag = 255;
-			break;
-		case 16384: // 128x128 lump
-			dflatsize = 128.0f;
-			flatflag = 127;
-			break;
-		case 1024: // 32x32 lump
-			dflatsize = 32.0f;
-			flatflag = 31;
-			break;
-		default: // 64x64 lump
-			dflatsize = 64.0f;
-			flatflag = 63;
-			break;
-	}
+	UINT16 flatflag = R_GetFlatSize(len) - 1;
+	double dflatsize = (double)(flatflag + 1);
 
 //  3--2
 //  | /|
@@ -754,7 +722,6 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
 
 	v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
 
-	// flat is 64x64 lod and texture offsets are [0.0, 1.0]
 	v[0].s = v[3].s = (float)((x & flatflag)/dflatsize);
 	v[2].s = v[1].s = (float)(v[0].s + w/dflatsize);
 	v[0].t = v[1].t = (float)((y & flatflag)/dflatsize);
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 4126820293e756417515f9890ca9fdabe570f4a5..040a64b5f8e748a71c7d3bc427014b16132951c1 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -360,30 +360,39 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta)
 // -----------------+
 static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap)
 {
-	polyvertex_t *  pv;
-	float           height; //constant y for all points on the convex flat polygon
-	FOutVector      *v3d;
-	INT32             nrPlaneVerts;   //verts original define of convex flat polygon
-	INT32             i;
-	float           flatxref,flatyref;
+	FSurfaceInfo Surf;
+	FOutVector *v3d;
+	polyvertex_t *pv;
+	pslope_t *slope = NULL;
+	INT32 shader = SHADER_DEFAULT;
+
+	size_t nrPlaneVerts;
+	INT32 i;
+
+	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;
-	INT32 flatflag = 63;
+	UINT16 flatflag = 63;
+
 	boolean texflat = false;
-	float scrollx = 0.0f, scrolly = 0.0f, anglef = 0.0f;
-	angle_t angle = 0;
-	FSurfaceInfo    Surf;
+
 	float tempxsow, tempytow;
-	pslope_t *slope = NULL;
+	float scrollx = 0.0f, scrolly = 0.0f;
+	angle_t angle = 0;
 
 	static FOutVector *planeVerts = NULL;
 	static UINT16 numAllocedPlaneVerts = 0;
 
-	INT32 shader = SHADER_DEFAULT;
-
 	// no convex poly were generated for this subsector
 	if (!xsub->planepoly)
 		return;
 
+	pv = xsub->planepoly->pts;
+	nrPlaneVerts = xsub->planepoly->numpts;
+
+	if (nrPlaneVerts < 3) // not even a triangle?
+		return;
+
 	// Get the slope pointer to simplify future code
 	if (FOFsector)
 	{
@@ -406,12 +415,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 
 	height = FIXED_TO_FLOAT(fixedheight);
 
-	pv  = xsub->planepoly->pts;
-	nrPlaneVerts = xsub->planepoly->numpts;
-
-	if (nrPlaneVerts < 3)   //not even a triangle ?
-		return;
-
 	// Allocate plane-vertex buffer if we need to
 	if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts)
 	{
@@ -426,31 +429,8 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 		if (levelflat->type == LEVELFLAT_FLAT)
 		{
 			size_t len = W_LumpLength(levelflat->u.flat.lumpnum);
-			switch (len)
-			{
-				case 4194304: // 2048x2048 lump
-					fflatwidth = fflatheight = 2048.0f;
-					break;
-				case 1048576: // 1024x1024 lump
-					fflatwidth = fflatheight = 1024.0f;
-					break;
-				case 262144:// 512x512 lump
-					fflatwidth = fflatheight = 512.0f;
-					break;
-				case 65536: // 256x256 lump
-					fflatwidth = fflatheight = 256.0f;
-					break;
-				case 16384: // 128x128 lump
-					fflatwidth = fflatheight = 128.0f;
-					break;
-				case 1024: // 32x32 lump
-					fflatwidth = fflatheight = 32.0f;
-					break;
-				default: // 64x64 lump
-					fflatwidth = fflatheight = 64.0f;
-					break;
-			}
-			flatflag = ((INT32)fflatwidth)-1;
+			flatflag = R_GetFlatSize(len) - 1;
+			fflatwidth = fflatheight = (float)(flatflag + 1);
 		}
 		else
 		{
@@ -550,7 +530,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 		}\
 }
 
-	for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++)
+	for (i = 0, v3d = planeVerts; i < (INT32)nrPlaneVerts; i++,v3d++,pv++)
 		SETUP3DVERT(v3d, pv->x, pv->y);
 
 	if (slope)
@@ -2693,13 +2673,13 @@ 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;
-	INT32 flatflag = 63;
+	UINT16 flatflag = 63;
 
 	boolean texflat = false;
 
 	float scrollx = 0.0f, scrolly = 0.0f;
+	float tempxsow, tempytow, anglef = 0.0f;
 	angle_t angle = 0;
-	fixed_t tempxs, tempyt;
 
 	static FOutVector *planeVerts = NULL;
 	static UINT16 numAllocedPlaneVerts = 0;
@@ -2726,31 +2706,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
 		if (levelflat->type == LEVELFLAT_FLAT)
 		{
 			size_t len = W_LumpLength(levelflat->u.flat.lumpnum);
-			switch (len)
-			{
-				case 4194304: // 2048x2048 lump
-					fflatwidth = fflatheight = 2048.0f;
-					break;
-				case 1048576: // 1024x1024 lump
-					fflatwidth = fflatheight = 1024.0f;
-					break;
-				case 262144:// 512x512 lump
-					fflatwidth = fflatheight = 512.0f;
-					break;
-				case 65536: // 256x256 lump
-					fflatwidth = fflatheight = 256.0f;
-					break;
-				case 16384: // 128x128 lump
-					fflatwidth = fflatheight = 128.0f;
-					break;
-				case 1024: // 32x32 lump
-					fflatwidth = fflatheight = 32.0f;
-					break;
-				default: // 64x64 lump
-					fflatwidth = fflatheight = 64.0f;
-					break;
-			}
-			flatflag = ((INT32)fflatwidth)-1;
+			flatflag = R_GetFlatSize(len) - 1;
+			fflatwidth = fflatheight = (float)(flatflag + 1);
 		}
 		else
 		{
@@ -2813,20 +2770,13 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
 
 	if (angle) // Only needs to be done if there's an altered angle
 	{
-		angle = (InvAngle(angle))>>ANGLETOFINESHIFT;
+		tempxsow = flatxref;
+		tempytow = flatyref;
 
-		// This needs to be done so that it scrolls in a different direction after rotation like software
-		/*tempxs = FLOAT_TO_FIXED(scrollx);
-		tempyt = FLOAT_TO_FIXED(scrolly);
-		scrollx = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle))));
-		scrolly = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle))));*/
+		anglef = ANG2RAD(InvAngle(angle));
 
-		// This needs to be done so everything aligns after rotation
-		// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
-		tempxs = FLOAT_TO_FIXED(flatxref);
-		tempyt = FLOAT_TO_FIXED(flatyref);
-		flatxref = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle))));
-		flatyref = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle))));
+		flatxref = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));
+		flatyref = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));
 	}
 
 	for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++)
@@ -2847,10 +2797,11 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
 		// Need to rotate before translate
 		if (angle) // Only needs to be done if there's an altered angle
 		{
-			tempxs = FLOAT_TO_FIXED(v3d->s);
-			tempyt = FLOAT_TO_FIXED(v3d->t);
-			v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle))));
-			v3d->t = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle))));
+			tempxsow = v3d->s;
+			tempytow = v3d->t;
+
+			v3d->s = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));
+			v3d->t = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));
 		}
 
 		v3d->x = FIXED_TO_FLOAT(polysector->vertices[i]->x);
diff --git a/src/r_draw.c b/src/r_draw.c
index 85310328aa4892beecc810d33277b108ef6ae195..601fb4bb2545f518546ca9df02ad8b9e8ab42849 100644
--- a/src/r_draw.c
+++ b/src/r_draw.c
@@ -106,7 +106,7 @@ fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
 INT32 ds_waterofs, ds_bgofs;
 
 UINT16 ds_flatwidth, ds_flatheight;
-boolean ds_powersoftwo;
+boolean ds_powersoftwo, ds_solidcolor;
 
 UINT8 *ds_source; // points to the start of a flat
 UINT8 *ds_transmap; // one of the translucency tables
diff --git a/src/r_draw.h b/src/r_draw.h
index fa59a74ee9d2583497bd40b1d7e2f43c2cec342b..cb4e4482a894e1e9218295e5e0ec2fd3dfd50728 100644
--- a/src/r_draw.h
+++ b/src/r_draw.h
@@ -61,7 +61,7 @@ extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
 extern INT32 ds_waterofs, ds_bgofs;
 
 extern UINT16 ds_flatwidth, ds_flatheight;
-extern boolean ds_powersoftwo;
+extern boolean ds_powersoftwo, ds_solidcolor;
 
 extern UINT8 *ds_source;
 extern UINT8 *ds_transmap;
@@ -194,8 +194,8 @@ void R_DrawTranslucentFloorSprite_8(void);
 void R_DrawTiltedFloorSprite_8(void);
 void R_DrawTiltedTranslucentFloorSprite_8(void);
 
-void R_DrawTranslucentWaterSpan_8(void);
-void R_DrawTiltedTranslucentWaterSpan_8(void);
+void R_DrawWaterSpan_8(void);
+void R_DrawTiltedWaterSpan_8(void);
 
 void R_DrawFogSpan_8(void);
 void R_DrawTiltedFogSpan_8(void);
@@ -215,8 +215,15 @@ void R_DrawTranslucentFloorSprite_NPO2_8(void);
 void R_DrawTiltedFloorSprite_NPO2_8(void);
 void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void);
 
-void R_DrawTranslucentWaterSpan_NPO2_8(void);
-void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void);
+void R_DrawWaterSpan_NPO2_8(void);
+void R_DrawTiltedWaterSpan_NPO2_8(void);
+
+void R_DrawSolidColorSpan_8(void);
+void R_DrawTransSolidColorSpan_8(void);
+void R_DrawTiltedSolidColorSpan_8(void);
+void R_DrawTiltedTransSolidColorSpan_8(void);
+void R_DrawWaterSolidColorSpan_8(void);
+void R_DrawTiltedWaterSolidColorSpan_8(void);
 
 #ifdef USEASM
 void ASMCALL R_DrawColumn_8_ASM(void);
diff --git a/src/r_draw8.c b/src/r_draw8.c
index d644398ff41e20dc2f2af627b768e64bca6d0cd0..31abe70b8a2487df9c4bb3a1fd96c3967655e498 100644
--- a/src/r_draw8.c
+++ b/src/r_draw8.c
@@ -901,10 +901,10 @@ void R_DrawTiltedTranslucentSpan_8(void)
 #endif
 }
 
-/**	\brief The R_DrawTiltedTranslucentWaterSpan_8 function
+/**	\brief The R_DrawTiltedWaterSpan_8 function
 	Like DrawTiltedTranslucentSpan, but for water
 */
-void R_DrawTiltedTranslucentWaterSpan_8(void)
+void R_DrawTiltedWaterSpan_8(void)
 {
 	// x1, x2 = ds_x1, ds_x2
 	int width = ds_x2 - ds_x1;
@@ -1893,7 +1893,7 @@ void R_DrawTranslucentSpan_8 (void)
 	}
 }
 
-void R_DrawTranslucentWaterSpan_8(void)
+void R_DrawWaterSpan_8(void)
 {
 	UINT32 xposition;
 	UINT32 yposition;
@@ -2025,6 +2025,123 @@ void R_DrawTiltedFogSpan_8(void)
 	} while (--width >= 0);
 }
 
+/**	\brief The R_DrawSolidColorSpan_8 function
+	Draws a solid color span.
+*/
+void R_DrawSolidColorSpan_8(void)
+{
+	size_t count = (ds_x2 - ds_x1 + 1);
+
+	UINT8 source = ds_colormap[ds_source[0]];
+	UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1];
+
+	memset(dest, source, count);
+}
+
+/**	\brief The R_DrawTransSolidColorSpan_8 function
+	Draws a translucent solid color span.
+*/
+void R_DrawTransSolidColorSpan_8(void)
+{
+	size_t count = (ds_x2 - ds_x1 + 1);
+
+	UINT8 source = ds_colormap[ds_source[0]];
+	UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1];
+
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+
+	while (count-- && dest <= deststop)
+	{
+		*dest = *(ds_transmap + (source << 8) + *dest);
+		dest++;
+	}
+}
+
+/**	\brief The R_DrawTiltedSolidColorSpan_8 function
+	Draws a tilted solid color span.
+*/
+void R_DrawTiltedSolidColorSpan_8(void)
+{
+	int width = ds_x2 - ds_x1;
+
+	UINT8 source = ds_source[0];
+	UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1];
+
+	double iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
+
+	CALC_SLOPE_LIGHT
+
+	do
+	{
+		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+		*dest++ = colormap[source];
+	} while (--width >= 0);
+}
+
+/**	\brief The R_DrawTiltedTransSolidColorSpan_8 function
+	Draws a tilted and translucent solid color span.
+*/
+void R_DrawTiltedTransSolidColorSpan_8(void)
+{
+	int width = ds_x2 - ds_x1;
+
+	UINT8 source = ds_source[0];
+	UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1];
+
+	double iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
+
+	CALC_SLOPE_LIGHT
+
+	do
+	{
+		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+		*dest = *(ds_transmap + (colormap[source] << 8) + *dest);
+		dest++;
+	} while (--width >= 0);
+}
+
+/**	\brief The R_DrawWaterSolidColorSpan_8 function
+	Draws a water solid color span.
+*/
+void R_DrawWaterSolidColorSpan_8(void)
+{
+	UINT8 source = ds_source[0];
+	UINT8 *colormap = ds_colormap;
+	UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1];
+	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
+
+	size_t count = (ds_x2 - ds_x1 + 1);
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+
+	while (count-- && dest <= deststop)
+	{
+		*dest = colormap[*(ds_transmap + (source << 8) + *dsrc++)];
+		dest++;
+	}
+}
+
+/**	\brief The R_DrawTiltedWaterSolidColorSpan_8 function
+	Draws a tilted water solid color span.
+*/
+void R_DrawTiltedWaterSolidColorSpan_8(void)
+{
+	int width = ds_x2 - ds_x1;
+
+	UINT8 source = ds_source[0];
+	UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1];
+	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
+
+	double iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
+
+	CALC_SLOPE_LIGHT
+
+	do
+	{
+		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+		*dest++ = *(ds_transmap + (colormap[source] << 8) + *dsrc++);
+	} while (--width >= 0);
+}
+
 /**	\brief The R_DrawFogColumn_8 function
 	Fog wall.
 */
diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c
index f660108412ce0da1f36f4f65234267771a68d5c0..8b02fb90de973736af22cf459c16a2cb0d75b8c0 100644
--- a/src/r_draw8_npo2.c
+++ b/src/r_draw8_npo2.c
@@ -1319,7 +1319,7 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
 	}
 }
 
-void R_DrawTranslucentWaterSpan_NPO2_8(void)
+void R_DrawWaterSpan_NPO2_8(void)
 {
 	fixed_t xposition;
 	fixed_t yposition;
@@ -1382,10 +1382,10 @@ void R_DrawTranslucentWaterSpan_NPO2_8(void)
 	}
 }
 
-/**	\brief The R_DrawTiltedTranslucentWaterSpan_NPO2_8 function
+/**	\brief The R_DrawTiltedWaterSpan_NPO2_8 function
 	Like DrawTiltedTranslucentSpan_NPO2, but for water
 */
-void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void)
+void R_DrawTiltedWaterSpan_NPO2_8(void)
 {
 	// x1, x2 = ds_x1, ds_x2
 	int width = ds_x2 - ds_x1;
diff --git a/src/r_plane.c b/src/r_plane.c
index fe575a78392f6038bcc6d87c47b5bd91ca71d4e8..56cf869efb46166748ee9f4575765281b471423a 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -36,9 +36,6 @@
 // opening
 //
 
-// Quincunx antialiasing of flats!
-//#define QUINCUNX
-
 //SoM: 3/23/2000: Use Boom visplane hashing.
 
 visplane_t *visplanes[MAXVISPLANES];
@@ -789,6 +786,9 @@ d->z = (v1.x * v2.y) - (v1.y * v2.x)
 	ds_svp->z *= focallengthf;
 	ds_szp->z *= focallengthf;
 
+	if (ds_solidcolor)
+		return;
+
 	// Premultiply the texture vectors with the scale factors
 	if (ds_powersoftwo)
 		sfmult *= (1 << nflatshiftup);
@@ -858,7 +858,7 @@ void R_DrawSinglePlane(visplane_t *pl)
 	ffloor_t *rover;
 	boolean fog = false;
 	INT32 spanfunctype = BASEDRAWFUNC;
-	void (*mapfunc)(INT32, INT32, INT32) = R_MapPlane;
+	void (*mapfunc)(INT32, INT32, INT32);
 
 	if (!(pl->minx <= pl->maxx))
 		return;
@@ -871,7 +871,6 @@ void R_DrawSinglePlane(visplane_t *pl)
 	}
 
 	planeripple.active = false;
-	spanfunc = spanfuncs[BASEDRAWFUNC];
 
 	if (pl->polyobj)
 	{
@@ -941,7 +940,7 @@ void R_DrawSinglePlane(visplane_t *pl)
 			}
 			else light = (pl->lightlevel >> LIGHTSEGSHIFT);
 
-			if (pl->ffloor->fofflags & FOF_RIPPLE)
+			if (pl->ffloor->fofflags & FOF_RIPPLE && !fog)
 			{
 				planeripple.active = true;
 
@@ -963,17 +962,21 @@ void R_DrawSinglePlane(visplane_t *pl)
 										 vid.width, bottom-top,
 										 vid.width, vid.width);
 				}
-				else if (fog)
-					planeripple.active = false;
 			}
 		}
 		else
 			light = (pl->lightlevel >> LIGHTSEGSHIFT);
 	}
 
-	currentplane = pl;
+	ds_powersoftwo = ds_solidcolor = false;
 
-	if (!fog)
+	if (fog)
+	{
+		// Since all fog planes do is apply a colormap, it's not required
+		// to know any information about their textures.
+		mapfunc = R_MapFogPlane;
+	}
+	else
 	{
 		levelflat_t *levelflat = &levelflats[pl->picnum];
 
@@ -984,28 +987,50 @@ void R_DrawSinglePlane(visplane_t *pl)
 				return;
 			case LEVELFLAT_FLAT:
 				ds_source = (UINT8 *)R_GetFlat(levelflat->u.flat.lumpnum);
-				R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum));
-				// Raw flats always have dimensions that are powers-of-two numbers.
-				ds_powersoftwo = true;
+				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;
-				// Check if this texture or patch has power-of-two dimensions.
-				if (R_CheckPowersOfTwo())
-					R_CheckFlatLength(ds_flatwidth * ds_flatheight);
+				else if (R_CheckSolidColorFlat())
+					ds_solidcolor = true;
+				else if (R_CheckPowersOfTwo())
+				{
+					R_SetFlatVars(ds_flatwidth * ds_flatheight);
+					ds_powersoftwo = true;
+				}
 		}
 
-		if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later
-			&& viewangle != pl->viewangle+pl->plangle)
+		// Don't mess with angle on slopes! We'll handle this ourselves later
+		if (!pl->slope && viewangle != pl->viewangle+pl->plangle)
 		{
 			memset(cachedheight, 0, sizeof (cachedheight));
 			viewangle = pl->viewangle+pl->plangle;
 		}
+
+		mapfunc = R_MapPlane;
+
+		if (ds_solidcolor)
+		{
+			switch (spanfunctype)
+			{
+				case SPANDRAWFUNC_WATER:
+					spanfunctype = SPANDRAWFUNC_WATERSOLID;
+					break;
+				case SPANDRAWFUNC_TRANS:
+					spanfunctype = SPANDRAWFUNC_TRANSSOLID;
+					break;
+				default:
+					spanfunctype = SPANDRAWFUNC_SOLID;
+					break;
+			}
+		}
 	}
-	else
-		mapfunc = R_MapFogPlane;
 
 	xoffs = pl->xoffs;
 	yoffs = pl->yoffs;
@@ -1024,7 +1049,7 @@ void R_DrawSinglePlane(visplane_t *pl)
 		{
 			mapfunc = R_MapTiltedPlane;
 
-			if (!pl->plangle)
+			if (!pl->plangle && !ds_solidcolor)
 			{
 				if (ds_powersoftwo)
 					R_AdjustSlopeCoordinates(&pl->slope->o);
@@ -1060,6 +1085,15 @@ void R_DrawSinglePlane(visplane_t *pl)
 			case SPANDRAWFUNC_SPLAT:
 				spanfunctype = SPANDRAWFUNC_TILTEDSPLAT;
 				break;
+			case SPANDRAWFUNC_SOLID:
+				spanfunctype = SPANDRAWFUNC_TILTEDSOLID;
+				break;
+			case SPANDRAWFUNC_TRANSSOLID:
+				spanfunctype = SPANDRAWFUNC_TILTEDTRANSSOLID;
+				break;
+			case SPANDRAWFUNC_WATERSOLID:
+				spanfunctype = SPANDRAWFUNC_TILTEDWATERSOLID;
+				break;
 			case SPANDRAWFUNC_FOG:
 				spanfunctype = SPANDRAWFUNC_TILTEDFOG;
 				break;
@@ -1076,7 +1110,7 @@ void R_DrawSinglePlane(visplane_t *pl)
 		planezlight = zlight[light];
 	}
 
-	// Use the correct span drawer depending on the powers-of-twoness
+	// Set the span drawer
 	if (!ds_powersoftwo)
 	{
 		if (spanfuncs_npo2[spanfunctype])
@@ -1093,81 +1127,11 @@ void R_DrawSinglePlane(visplane_t *pl)
 	pl->bottom[pl->maxx+1] = 0x0000;
 	pl->bottom[pl->minx-1] = 0x0000;
 
+	currentplane = pl;
 	stop = pl->maxx + 1;
 
 	for (x = pl->minx; x <= stop; x++)
 		R_MakeSpans(mapfunc, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]);
-
-/*
-QUINCUNX anti-aliasing technique (sort of)
-
-Normally, Quincunx antialiasing staggers pixels
-in a 5-die pattern like so:
-
-o   o
-  o
-o   o
-
-To simulate this, we offset the plane by
-FRACUNIT/4 in each direction, and draw
-at 50% translucency. The result is
-a 'smoothing' of the texture while
-using the palette colors.
-*/
-#ifdef QUINCUNX
-	if (spanfunc == spanfuncs[BASEDRAWFUNC])
-	{
-		INT32 i;
-		ds_transmap = R_GetTranslucencyTable(tr_trans50);
-		spanfunc = spanfuncs[SPANDRAWFUNC_TRANS];
-		for (i=0; i<4; i++)
-		{
-			xoffs = pl->xoffs;
-			yoffs = pl->yoffs;
-
-			switch(i)
-			{
-				case 0:
-					xoffs -= FRACUNIT/4;
-					yoffs -= FRACUNIT/4;
-					break;
-				case 1:
-					xoffs -= FRACUNIT/4;
-					yoffs += FRACUNIT/4;
-					break;
-				case 2:
-					xoffs += FRACUNIT/4;
-					yoffs -= FRACUNIT/4;
-					break;
-				case 3:
-					xoffs += FRACUNIT/4;
-					yoffs += FRACUNIT/4;
-					break;
-			}
-			planeheight = abs(pl->height - pl->viewz);
-
-			if (light >= LIGHTLEVELS)
-				light = LIGHTLEVELS-1;
-
-			if (light < 0)
-				light = 0;
-
-			planezlight = zlight[light];
-
-			// set the maximum value for unsigned
-			pl->top[pl->maxx+1] = 0xffff;
-			pl->top[pl->minx-1] = 0xffff;
-			pl->bottom[pl->maxx+1] = 0x0000;
-			pl->bottom[pl->minx-1] = 0x0000;
-
-			stop = pl->maxx + 1;
-
-			for (x = pl->minx; x <= stop; x++)
-				R_MakeSpans(mapfunc, x, pl->top[x-1], pl->bottom[x-1],
-					pl->top[x], pl->bottom[x]);
-		}
-	}
-#endif
 }
 
 void R_PlaneBounds(visplane_t *plane)
diff --git a/src/r_plane.h b/src/r_plane.h
index 09648feadc938bdb66e9d03403a401c543a50c96..ea793fce20c4a4bf921a90e6fc89c0509ebe6d05 100644
--- a/src/r_plane.h
+++ b/src/r_plane.h
@@ -84,9 +84,6 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
 void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
 void R_PlaneBounds(visplane_t *plane);
 
-void R_CheckFlatLength(size_t size);
-boolean R_CheckPowersOfTwo(void);
-
 // Draws a single visplane.
 void R_DrawSinglePlane(visplane_t *pl);
 
diff --git a/src/r_splats.c b/src/r_splats.c
index 92d12d784fbd5fe3a2f3189e15dde86a8bc22d63..a58cfe5365c3c2b08f986906d6a69659cb47da63 100644
--- a/src/r_splats.c
+++ b/src/r_splats.c
@@ -390,9 +390,13 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
 	ds_source = (UINT8 *)pSplat->pic;
 	ds_flatwidth = pSplat->width;
 	ds_flatheight = pSplat->height;
+	ds_powersoftwo = false;
 
 	if (R_CheckPowersOfTwo())
-		R_CheckFlatLength(ds_flatwidth * ds_flatheight);
+	{
+		R_SetFlatVars(ds_flatwidth * ds_flatheight);
+		ds_powersoftwo = true;
+	}
 
 	if (pSplat->slope)
 	{
diff --git a/src/r_textures.c b/src/r_textures.c
index 03f8f53a50a9e80f7df130a425a1331801deb876..98c2788a24316bc5eb5250263a415dba5b3bd97b 100644
--- a/src/r_textures.c
+++ b/src/r_textures.c
@@ -620,88 +620,99 @@ void *R_GetLevelFlat(levelflat_t *levelflat)
 }
 
 //
-// R_CheckPowersOfTwo
-//
-// Sets ds_powersoftwo true if the flat's dimensions are powers of two, and returns that.
+// Checks if the current flat's dimensions are powers of two
 //
 boolean R_CheckPowersOfTwo(void)
 {
-	boolean wpow2 = (!(ds_flatwidth & (ds_flatwidth - 1)));
-	boolean hpow2 = (!(ds_flatheight & (ds_flatheight - 1)));
-
-	// Initially, the flat isn't powers-of-two-sized.
-	ds_powersoftwo = false;
+	boolean wpow2 = !(ds_flatwidth & (ds_flatwidth - 1));
+	boolean hpow2 = !(ds_flatheight & (ds_flatheight - 1));
 
-	// But if the width and height are powers of two,
-	// and are EQUAL, then it's okay :]
-	if ((ds_flatwidth == ds_flatheight) && (wpow2 && hpow2))
-		ds_powersoftwo = true;
+	if (ds_flatwidth > 2048 || ds_flatheight > 2048)
+		return false;
 
-	// Just return ds_powersoftwo.
-	return ds_powersoftwo;
+	return ds_flatwidth == ds_flatheight && wpow2 && hpow2;
 }
 
 //
-// R_CheckFlatLength
+// Checks if the current flat's dimensions are 1x1
+//
+boolean R_CheckSolidColorFlat(void)
+{
+	return ds_flatwidth == 1 && ds_flatheight == 1;
+}
+
 //
-// Determine the flat's dimensions from its lump length.
+// Returns the flat size corresponding to the length of a lump
 //
-void R_CheckFlatLength(size_t size)
+UINT16 R_GetFlatSize(size_t length)
 {
-	switch (size)
+	switch (length)
 	{
 		case 4194304: // 2048x2048 lump
-			nflatmask = 0x3FF800;
-			nflatxshift = 21;
-			nflatyshift = 10;
-			nflatshiftup = 5;
-			ds_flatwidth = ds_flatheight = 2048;
-			break;
+			return 2048;
 		case 1048576: // 1024x1024 lump
-			nflatmask = 0xFFC00;
-			nflatxshift = 22;
-			nflatyshift = 12;
-			nflatshiftup = 6;
-			ds_flatwidth = ds_flatheight = 1024;
-			break;
+			return 1024;
 		case 262144:// 512x512 lump
-			nflatmask = 0x3FE00;
-			nflatxshift = 23;
-			nflatyshift = 14;
-			nflatshiftup = 7;
-			ds_flatwidth = ds_flatheight = 512;
-			break;
+			return 512;
 		case 65536: // 256x256 lump
-			nflatmask = 0xFF00;
-			nflatxshift = 24;
-			nflatyshift = 16;
-			nflatshiftup = 8;
-			ds_flatwidth = ds_flatheight = 256;
-			break;
+			return 256;
 		case 16384: // 128x128 lump
-			nflatmask = 0x3F80;
-			nflatxshift = 25;
-			nflatyshift = 18;
-			nflatshiftup = 9;
-			ds_flatwidth = ds_flatheight = 128;
-			break;
+			return 128;
 		case 1024: // 32x32 lump
-			nflatmask = 0x3E0;
-			nflatxshift = 27;
-			nflatyshift = 22;
-			nflatshiftup = 11;
-			ds_flatwidth = ds_flatheight = 32;
-			break;
+			return 32;
+		case 256: // 16x16 lump
+			return 16;
+		case 64: // 8x8 lump
+			return 8;
+		case 16: // 4x4 lump
+			return 4;
+		case 4: // 2x2 lump
+			return 2;
+		case 1: // 1x1 lump
+			return 1;
 		default: // 64x64 lump
-			nflatmask = 0xFC0;
-			nflatxshift = 26;
-			nflatyshift = 20;
-			nflatshiftup = 10;
-			ds_flatwidth = ds_flatheight = 64;
-			break;
+			return 64;
+	}
+}
+
+//
+// Determines a flat's width bits from its size
+//
+UINT8 R_GetFlatBits(INT32 size)
+{
+	switch (size)
+	{
+		case 2048: return 11;
+		case 1024: return 10;
+		case 512:  return 9;
+		case 256:  return 8;
+		case 128:  return 7;
+		case 32:   return 5;
+		case 16:   return 4;
+		case 8:    return 3;
+		case 4:    return 2;
+		case 2:    return 1;
+		case 1:    return 0;
+		default:   return 6; // 64x64
 	}
 }
 
+void R_SetFlatVars(size_t length)
+{
+	UINT16 size = R_GetFlatSize(length);
+	UINT8 bits = R_GetFlatBits(size);
+
+	ds_flatwidth = ds_flatheight = size;
+
+	if (bits == 0)
+		return;
+
+	nflatshiftup = 16 - bits;
+	nflatxshift = 16 + nflatshiftup;
+	nflatyshift = nflatxshift - bits;
+	nflatmask = (size - 1) * size;
+}
+
 //
 // Empty the texture cache (used for load wad at runtime)
 //
@@ -748,7 +759,7 @@ Rloadflats (INT32 i, INT32 w)
 			UINT16 wadnum = (UINT16)w;
 			lumpnum_t lumpnum = texstart + j;
 			size_t lumplength;
-			size_t flatsize = 0;
+			size_t flatsize;
 
 			if (W_FileHasFolders(wadfiles[w]))
 			{
@@ -758,31 +769,7 @@ Rloadflats (INT32 i, INT32 w)
 
 			W_ReadLumpHeaderPwad(wadnum, lumpnum, header, sizeof header, 0);
 			lumplength = W_LumpLengthPwad(wadnum, lumpnum);
-
-			switch (lumplength)
-			{
-				case 4194304: // 2048x2048 lump
-					flatsize = 2048;
-					break;
-				case 1048576: // 1024x1024 lump
-					flatsize = 1024;
-					break;
-				case 262144:// 512x512 lump
-					flatsize = 512;
-					break;
-				case 65536: // 256x256 lump
-					flatsize = 256;
-					break;
-				case 16384: // 128x128 lump
-					flatsize = 128;
-					break;
-				case 1024: // 32x32 lump
-					flatsize = 32;
-					break;
-				default: // 64x64 lump
-					flatsize = 64;
-					break;
-			}
+			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);
diff --git a/src/r_textures.h b/src/r_textures.h
index 9aa11ad4d9da7fce8b85b961d24b1f2109d3429d..b9b48da8c398e3cc8cda150ec1dd55786504bbb5 100644
--- a/src/r_textures.h
+++ b/src/r_textures.h
@@ -93,7 +93,11 @@ UINT8 *R_GetColumn(fixed_t tex, INT32 col);
 void *R_GetFlat(lumpnum_t flatnum);
 
 boolean R_CheckPowersOfTwo(void);
-void R_CheckFlatLength(size_t size);
+boolean R_CheckSolidColorFlat(void);
+
+UINT16 R_GetFlatSize(size_t length);
+UINT8 R_GetFlatBits(INT32 size);
+void R_SetFlatVars(size_t length);
 
 // Returns the texture number for the texture name.
 INT32 R_TextureNumForName(const char *name);
diff --git a/src/screen.c b/src/screen.c
index bcb7600a22d23329342bb4d683ae7bcaeabc3ed0..e984f9ee5617d992c3e0d1bc33eed23f21928950 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -141,8 +141,14 @@ void SCR_SetDrawFuncs(void)
 		spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8;
 		spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8;
 		spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_8;
-		spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8;
-		spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_8;
+		spanfuncs[SPANDRAWFUNC_WATER] = R_DrawWaterSpan_8;
+		spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedWaterSpan_8;
+		spanfuncs[SPANDRAWFUNC_SOLID] = R_DrawSolidColorSpan_8;
+		spanfuncs[SPANDRAWFUNC_TRANSSOLID] = R_DrawTransSolidColorSpan_8;
+		spanfuncs[SPANDRAWFUNC_TILTEDSOLID] = R_DrawTiltedSolidColorSpan_8;
+		spanfuncs[SPANDRAWFUNC_TILTEDTRANSSOLID] = R_DrawTiltedTransSolidColorSpan_8;
+		spanfuncs[SPANDRAWFUNC_WATERSOLID] = R_DrawWaterSolidColorSpan_8;
+		spanfuncs[SPANDRAWFUNC_TILTEDWATERSOLID] = R_DrawTiltedWaterSolidColorSpan_8;
 		spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8;
 		spanfuncs[SPANDRAWFUNC_TILTEDFOG] = R_DrawTiltedFogSpan_8;
 
@@ -158,8 +164,8 @@ void SCR_SetDrawFuncs(void)
 		spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8;
 		spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8;
 		spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8;
-		spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8;
-		spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8;
+		spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawWaterSpan_NPO2_8;
+		spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedWaterSpan_NPO2_8;
 
 #ifdef RUSEASM
 		if (R_ASM)
diff --git a/src/screen.h b/src/screen.h
index 50444ec4a33cd401d6a93925128ae638ccba8a8d..add048b25ad39c7ea6a16ca9795adc82c09e5708 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -155,6 +155,13 @@ enum
 	SPANDRAWFUNC_WATER,
 	SPANDRAWFUNC_TILTEDWATER,
 
+	SPANDRAWFUNC_SOLID,
+	SPANDRAWFUNC_TRANSSOLID,
+	SPANDRAWFUNC_TILTEDSOLID,
+	SPANDRAWFUNC_TILTEDTRANSSOLID,
+	SPANDRAWFUNC_WATERSOLID,
+	SPANDRAWFUNC_TILTEDWATERSOLID,
+
 	SPANDRAWFUNC_FOG,
 	SPANDRAWFUNC_TILTEDFOG,
 
diff --git a/src/v_video.c b/src/v_video.c
index 4f6ee7355c3de36360faff13cff2557c1715bbce..84d7978cb889213940ca3bbb290af5e6d03a8323 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -1748,7 +1748,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
 	fixed_t dx, dy, xfrac, yfrac;
 	const UINT8 *src, *deststop;
 	UINT8 *flat, *dest;
-	size_t size, lflatsize, flatshift;
+	size_t lflatsize, flatshift;
 
 #ifdef HWRENDER
 	if (rendermode == render_opengl)
@@ -1758,39 +1758,8 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
 	}
 #endif
 
-	size = W_LumpLength(flatnum);
-
-	switch (size)
-	{
-		case 4194304: // 2048x2048 lump
-			lflatsize = 2048;
-			flatshift = 10;
-			break;
-		case 1048576: // 1024x1024 lump
-			lflatsize = 1024;
-			flatshift = 9;
-			break;
-		case 262144:// 512x512 lump
-			lflatsize = 512;
-			flatshift = 8;
-			break;
-		case 65536: // 256x256 lump
-			lflatsize = 256;
-			flatshift = 7;
-			break;
-		case 16384: // 128x128 lump
-			lflatsize = 128;
-			flatshift = 7;
-			break;
-		case 1024: // 32x32 lump
-			lflatsize = 32;
-			flatshift = 5;
-			break;
-		default: // 64x64 lump
-			lflatsize = 64;
-			flatshift = 6;
-			break;
-	}
+	lflatsize = R_GetFlatSize(W_LumpLength(flatnum));
+	flatshift = R_GetFlatBits(lflatsize);
 
 	flat = W_CacheLumpNum(flatnum, PU_CACHE);