diff --git a/src/r_draw.h b/src/r_draw.h
index d77bbedd306bb4cf101336daead31e23ab071c9b..5011d29d95984be0b253d946ad0faf94577b1bb1 100644
--- a/src/r_draw.h
+++ b/src/r_draw.h
@@ -150,42 +150,53 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void);
 void R_DrawFogColumn_8(void);
 void R_DrawColumnShadowed_8(void);
 
+#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
+
 void R_DrawSpan_8(void);
-void R_DrawSplat_8(void);
-void R_DrawFloorSprite_8(void);
 void R_DrawTranslucentSpan_8(void);
-void R_DrawTranslucentSplat_8(void);
-void R_DrawTranslucentFloorSprite_8(void);
 void R_DrawTiltedSpan_8(void);
 void R_DrawTiltedTranslucentSpan_8(void);
-#ifndef NOWATER
-void R_DrawTiltedTranslucentWaterSpan_8(void);
-#endif
+
+void R_DrawSplat_8(void);
+void R_DrawTranslucentSplat_8(void);
 void R_DrawTiltedSplat_8(void);
+
+void R_DrawFloorSprite_8(void);
+void R_DrawTranslucentFloorSprite_8(void);
+void R_DrawTiltedFloorSprite_8(void);
+void R_DrawTiltedTranslucentFloorSprite_8(void);
+
 void R_CalcTiltedLighting(fixed_t start, fixed_t end);
 extern INT32 tiltlighting[MAXVIDWIDTH];
+
 #ifndef NOWATER
 void R_DrawTranslucentWaterSpan_8(void);
+void R_DrawTiltedTranslucentWaterSpan_8(void);
+
 extern INT32 ds_bgofs;
 extern INT32 ds_waterofs;
 #endif
+
 void R_DrawFogSpan_8(void);
 
 // Lactozilla: Non-powers-of-two
 void R_DrawSpan_NPO2_8(void);
 void R_DrawTranslucentSpan_NPO2_8(void);
-void R_DrawFloorSprite_NPO2_8(void);
-void R_DrawSplat_NPO2_8(void);
-void R_DrawTranslucentSplat_NPO2_8(void);
-void R_DrawTranslucentFloorSprite_NPO2_8(void);
 void R_DrawTiltedSpan_NPO2_8(void);
 void R_DrawTiltedTranslucentSpan_NPO2_8(void);
-#ifndef NOWATER
-void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void);
-#endif
+
+void R_DrawSplat_NPO2_8(void);
+void R_DrawTranslucentSplat_NPO2_8(void);
 void R_DrawTiltedSplat_NPO2_8(void);
+
+void R_DrawFloorSprite_NPO2_8(void);
+void R_DrawTranslucentFloorSprite_NPO2_8(void);
+void R_DrawTiltedFloorSprite_NPO2_8(void);
+void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void);
+
 #ifndef NOWATER
 void R_DrawTranslucentWaterSpan_NPO2_8(void);
+void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void);
 #endif
 
 #ifdef USEASM
diff --git a/src/r_draw8.c b/src/r_draw8.c
index bc39e91a5f5d797cfff40af4df14796a37a93560..c28a25cbca40e4b4456c20a81741a10928120586 100644
--- a/src/r_draw8.c
+++ b/src/r_draw8.c
@@ -536,6 +536,9 @@ void R_DrawTranslatedColumn_8(void)
 // SPANS
 // ==========================================================================
 
+#define SPANSIZE 16
+#define INVSPAN 0.0625f
+
 /**	\brief The R_DrawSpan_8 function
 	Draws the actual span.
 */
@@ -643,8 +646,6 @@ void R_CalcTiltedLighting(fixed_t start, fixed_t end)
 	}
 }
 
-#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
-
 /**	\brief The R_DrawTiltedSpan_8 function
 	Draw slopes! Holy sheit!
 */
@@ -704,9 +705,6 @@ void R_DrawTiltedSpan_8(void)
 		vz += ds_svp->x;
 	} while (--width >= 0);
 #else
-#define SPANSIZE 16
-#define INVSPAN	0.0625f
-
 	startz = 1.f/iz;
 	startu = uz*startz;
 	startv = vz*startz;
@@ -839,9 +837,6 @@ void R_DrawTiltedTranslucentSpan_8(void)
 		vz += ds_svp->x;
 	} while (--width >= 0);
 #else
-#define SPANSIZE 16
-#define INVSPAN	0.0625f
-
 	startz = 1.f/iz;
 	startu = uz*startz;
 	startv = vz*startz;
@@ -977,9 +972,6 @@ void R_DrawTiltedTranslucentWaterSpan_8(void)
 		vz += ds_svp->x;
 	} while (--width >= 0);
 #else
-#define SPANSIZE 16
-#define INVSPAN	0.0625f
-
 	startz = 1.f/iz;
 	startu = uz*startz;
 	startv = vz*startz;
@@ -1116,9 +1108,6 @@ void R_DrawTiltedSplat_8(void)
 		vz += ds_svp->x;
 	} while (--width >= 0);
 #else
-#define SPANSIZE 16
-#define INVSPAN	0.0625f
-
 	startz = 1.f/iz;
 	startu = uz*startz;
 	startv = vz*startz;
@@ -1643,6 +1632,224 @@ void R_DrawTranslucentFloorSprite_8 (void)
 	}
 }
 
+/**	\brief The R_DrawTiltedFloorSprite_8 function
+	Draws a tilted floor sprite.
+*/
+void R_DrawTiltedFloorSprite_8(void)
+{
+	// x1, x2 = ds_x1, ds_x2
+	int width = ds_x2 - ds_x1;
+	double iz, uz, vz;
+	UINT32 u, v;
+	int i;
+
+	UINT16 *source;
+	UINT8 *colormap;
+	UINT8 *translation;
+	UINT8 *dest;
+	UINT16 val;
+
+	double startz, startu, startv;
+	double izstep, uzstep, vzstep;
+	double endz, endu, endv;
+	UINT32 stepu, stepv;
+
+	iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
+	uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
+	vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
+
+	dest = ylookup[ds_y] + columnofs[ds_x1];
+	source = (UINT16 *)ds_source;
+	colormap = ds_colormap;
+	translation = ds_translation;
+
+	startz = 1.f/iz;
+	startu = uz*startz;
+	startv = vz*startz;
+
+	izstep = ds_szp->x * SPANSIZE;
+	uzstep = ds_sup->x * SPANSIZE;
+	vzstep = ds_svp->x * SPANSIZE;
+	//x1 = 0;
+	width++;
+
+	while (width >= SPANSIZE)
+	{
+		iz += izstep;
+		uz += uzstep;
+		vz += vzstep;
+
+		endz = 1.f/iz;
+		endu = uz*endz;
+		endv = vz*endz;
+		stepu = (INT64)((endu - startu) * INVSPAN);
+		stepv = (INT64)((endv - startv) * INVSPAN);
+		u = (INT64)(startu) + viewx;
+		v = (INT64)(startv) + viewy;
+
+		for (i = SPANSIZE-1; i >= 0; i--)
+		{
+			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
+			if (val & 0xFF00)
+				*dest = colormap[translation[val & 0xFF]];
+			dest++;
+
+			u += stepu;
+			v += stepv;
+		}
+		startu = endu;
+		startv = endv;
+		width -= SPANSIZE;
+	}
+	if (width > 0)
+	{
+		if (width == 1)
+		{
+			u = (INT64)(startu);
+			v = (INT64)(startv);
+			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
+			if (val & 0xFF00)
+				*dest = colormap[translation[val & 0xFF]];
+		}
+		else
+		{
+			double left = width;
+			iz += ds_szp->x * left;
+			uz += ds_sup->x * left;
+			vz += ds_svp->x * left;
+
+			endz = 1.f/iz;
+			endu = uz*endz;
+			endv = vz*endz;
+			left = 1.f/left;
+			stepu = (INT64)((endu - startu) * left);
+			stepv = (INT64)((endv - startv) * left);
+			u = (INT64)(startu) + viewx;
+			v = (INT64)(startv) + viewy;
+
+			for (; width != 0; width--)
+			{
+				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
+				if (val & 0xFF00)
+					*dest = colormap[translation[val & 0xFF]];
+				dest++;
+
+				u += stepu;
+				v += stepv;
+			}
+		}
+	}
+}
+
+/**	\brief The R_DrawTiltedTranslucentFloorSprite_8 function
+	Draws a tilted, translucent, floor sprite.
+*/
+void R_DrawTiltedTranslucentFloorSprite_8(void)
+{
+	// x1, x2 = ds_x1, ds_x2
+	int width = ds_x2 - ds_x1;
+	double iz, uz, vz;
+	UINT32 u, v;
+	int i;
+
+	UINT16 *source;
+	UINT8 *colormap;
+	UINT8 *translation;
+	UINT8 *dest;
+	UINT16 val;
+
+	double startz, startu, startv;
+	double izstep, uzstep, vzstep;
+	double endz, endu, endv;
+	UINT32 stepu, stepv;
+
+	iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
+	uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
+	vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
+
+	dest = ylookup[ds_y] + columnofs[ds_x1];
+	source = (UINT16 *)ds_source;
+	colormap = ds_colormap;
+	translation = ds_translation;
+
+	startz = 1.f/iz;
+	startu = uz*startz;
+	startv = vz*startz;
+
+	izstep = ds_szp->x * SPANSIZE;
+	uzstep = ds_sup->x * SPANSIZE;
+	vzstep = ds_svp->x * SPANSIZE;
+	//x1 = 0;
+	width++;
+
+	while (width >= SPANSIZE)
+	{
+		iz += izstep;
+		uz += uzstep;
+		vz += vzstep;
+
+		endz = 1.f/iz;
+		endu = uz*endz;
+		endv = vz*endz;
+		stepu = (INT64)((endu - startu) * INVSPAN);
+		stepv = (INT64)((endv - startv) * INVSPAN);
+		u = (INT64)(startu) + viewx;
+		v = (INT64)(startv) + viewy;
+
+		for (i = SPANSIZE-1; i >= 0; i--)
+		{
+			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
+			if (val & 0xFF00)
+				*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
+			dest++;
+
+			u += stepu;
+			v += stepv;
+		}
+		startu = endu;
+		startv = endv;
+		width -= SPANSIZE;
+	}
+	if (width > 0)
+	{
+		if (width == 1)
+		{
+			u = (INT64)(startu);
+			v = (INT64)(startv);
+			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
+			if (val & 0xFF00)
+				*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
+		}
+		else
+		{
+			double left = width;
+			iz += ds_szp->x * left;
+			uz += ds_sup->x * left;
+			vz += ds_svp->x * left;
+
+			endz = 1.f/iz;
+			endu = uz*endz;
+			endv = vz*endz;
+			left = 1.f/left;
+			stepu = (INT64)((endu - startu) * left);
+			stepv = (INT64)((endv - startv) * left);
+			u = (INT64)(startu) + viewx;
+			v = (INT64)(startv) + viewy;
+
+			for (; width != 0; width--)
+			{
+				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
+				if (val & 0xFF00)
+					*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
+				dest++;
+
+				u += stepu;
+				v += stepv;
+			}
+		}
+	}
+}
+
 /**	\brief The R_DrawTranslucentSpan_8 function
 	Draws the actual span with translucency.
 */
diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c
index 087a8d30caf547501571347f9a02dc11f74fc89e..895869e2d86d95e2de19774e2bfe32637480ee55 100644
--- a/src/r_draw8_npo2.c
+++ b/src/r_draw8_npo2.c
@@ -15,6 +15,9 @@
 // SPANS
 // ==========================================================================
 
+#define SPANSIZE 16
+#define INVSPAN 0.0625f
+
 /**	\brief The R_DrawSpan_NPO2_8 function
 	Draws the actual span.
 */
@@ -61,8 +64,6 @@ void R_DrawSpan_NPO2_8 (void)
 	}
 }
 
-#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
-
 /**	\brief The R_DrawTiltedSpan_NPO2_8 function
 	Draw slopes! Holy sheit!
 */
@@ -137,9 +138,6 @@ void R_DrawTiltedSpan_NPO2_8(void)
 		vz += ds_svp->x;
 	} while (--width >= 0);
 #else
-#define SPANSIZE 16
-#define INVSPAN	0.0625f
-
 	startz = 1.f/iz;
 	startu = uz*startz;
 	startv = vz*startz;
@@ -332,9 +330,6 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
 		vz += ds_svp->x;
 	} while (--width >= 0);
 #else
-#define SPANSIZE 16
-#define INVSPAN	0.0625f
-
 	startz = 1.f/iz;
 	startu = uz*startz;
 	startv = vz*startz;
@@ -531,9 +526,6 @@ void R_DrawTiltedSplat_NPO2_8(void)
 		vz += ds_svp->x;
 	} while (--width >= 0);
 #else
-#define SPANSIZE 16
-#define INVSPAN	0.0625f
-
 	startz = 1.f/iz;
 	startu = uz*startz;
 	startv = vz*startz;
@@ -852,6 +844,306 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void)
 	}
 }
 
+/**	\brief The R_DrawTiltedFloorSprite_NPO2_8 function
+	Draws a tilted floor sprite.
+*/
+void R_DrawTiltedFloorSprite_NPO2_8(void)
+{
+	// x1, x2 = ds_x1, ds_x2
+	int width = ds_x2 - ds_x1;
+	double iz, uz, vz;
+	UINT32 u, v;
+	int i;
+
+	UINT16 *source;
+	UINT8 *colormap;
+	UINT8 *translation;
+	UINT8 *dest;
+	UINT16 val;
+
+	double startz, startu, startv;
+	double izstep, uzstep, vzstep;
+	double endz, endu, endv;
+	UINT32 stepu, stepv;
+
+	iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
+	uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
+	vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
+
+	dest = ylookup[ds_y] + columnofs[ds_x1];
+	source = (UINT16 *)ds_source;
+	colormap = ds_colormap;
+	translation = ds_translation;
+
+	startz = 1.f/iz;
+	startu = uz*startz;
+	startv = vz*startz;
+
+	izstep = ds_szp->x * SPANSIZE;
+	uzstep = ds_sup->x * SPANSIZE;
+	vzstep = ds_svp->x * SPANSIZE;
+	//x1 = 0;
+	width++;
+
+	while (width >= SPANSIZE)
+	{
+		iz += izstep;
+		uz += uzstep;
+		vz += vzstep;
+
+		endz = 1.f/iz;
+		endu = uz*endz;
+		endv = vz*endz;
+		stepu = (INT64)((endu - startu) * INVSPAN);
+		stepv = (INT64)((endv - startv) * INVSPAN);
+		u = (INT64)(startu) + viewx;
+		v = (INT64)(startv) + viewy;
+
+		for (i = SPANSIZE-1; i >= 0; i--)
+		{
+			// Lactozilla: Non-powers-of-two
+			fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
+			fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
+
+			// Carefully align all of my Friends.
+			if (x < 0)
+				x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
+			if (y < 0)
+				y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
+
+			x %= ds_flatwidth;
+			y %= ds_flatheight;
+
+			val = source[((y * ds_flatwidth) + x)];
+			if (val & 0xFF00)
+				*dest = colormap[translation[val & 0xFF]];
+			dest++;
+
+			u += stepu;
+			v += stepv;
+		}
+		startu = endu;
+		startv = endv;
+		width -= SPANSIZE;
+	}
+	if (width > 0)
+	{
+		if (width == 1)
+		{
+			u = (INT64)(startu);
+			v = (INT64)(startv);
+			// Lactozilla: Non-powers-of-two
+			{
+				fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
+				fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
+
+				// Carefully align all of my Friends.
+				if (x < 0)
+					x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
+				if (y < 0)
+					y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
+
+				x %= ds_flatwidth;
+				y %= ds_flatheight;
+
+				val = source[((y * ds_flatwidth) + x)];
+				if (val & 0xFF00)
+					*dest = colormap[translation[val & 0xFF]];
+			}
+		}
+		else
+		{
+			double left = width;
+			iz += ds_szp->x * left;
+			uz += ds_sup->x * left;
+			vz += ds_svp->x * left;
+
+			endz = 1.f/iz;
+			endu = uz*endz;
+			endv = vz*endz;
+			left = 1.f/left;
+			stepu = (INT64)((endu - startu) * left);
+			stepv = (INT64)((endv - startv) * left);
+			u = (INT64)(startu) + viewx;
+			v = (INT64)(startv) + viewy;
+
+			for (; width != 0; width--)
+			{
+				// Lactozilla: Non-powers-of-two
+				fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
+				fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
+
+				// Carefully align all of my Friends.
+				if (x < 0)
+					x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
+				if (y < 0)
+					y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
+
+				x %= ds_flatwidth;
+				y %= ds_flatheight;
+
+				val = source[((y * ds_flatwidth) + x)];
+				if (val & 0xFF00)
+					*dest = colormap[translation[val & 0xFF]];
+				dest++;
+
+				u += stepu;
+				v += stepv;
+			}
+		}
+	}
+}
+
+/**	\brief The R_DrawTiltedTranslucentFloorSprite_NPO2_8 function
+	Draws a tilted, translucent, floor sprite.
+*/
+void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
+{
+	// x1, x2 = ds_x1, ds_x2
+	int width = ds_x2 - ds_x1;
+	double iz, uz, vz;
+	UINT32 u, v;
+	int i;
+
+	UINT16 *source;
+	UINT8 *colormap;
+	UINT8 *translation;
+	UINT8 *dest;
+	UINT16 val;
+
+	double startz, startu, startv;
+	double izstep, uzstep, vzstep;
+	double endz, endu, endv;
+	UINT32 stepu, stepv;
+
+	iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
+	uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
+	vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
+
+	dest = ylookup[ds_y] + columnofs[ds_x1];
+	source = (UINT16 *)ds_source;
+	colormap = ds_colormap;
+	translation = ds_translation;
+
+	startz = 1.f/iz;
+	startu = uz*startz;
+	startv = vz*startz;
+
+	izstep = ds_szp->x * SPANSIZE;
+	uzstep = ds_sup->x * SPANSIZE;
+	vzstep = ds_svp->x * SPANSIZE;
+	//x1 = 0;
+	width++;
+
+	while (width >= SPANSIZE)
+	{
+		iz += izstep;
+		uz += uzstep;
+		vz += vzstep;
+
+		endz = 1.f/iz;
+		endu = uz*endz;
+		endv = vz*endz;
+		stepu = (INT64)((endu - startu) * INVSPAN);
+		stepv = (INT64)((endv - startv) * INVSPAN);
+		u = (INT64)(startu) + viewx;
+		v = (INT64)(startv) + viewy;
+
+		for (i = SPANSIZE-1; i >= 0; i--)
+		{
+			// Lactozilla: Non-powers-of-two
+			fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
+			fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
+
+			// Carefully align all of my Friends.
+			if (x < 0)
+				x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
+			if (y < 0)
+				y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
+
+			x %= ds_flatwidth;
+			y %= ds_flatheight;
+
+			val = source[((y * ds_flatwidth) + x)];
+			if (val & 0xFF00)
+				*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
+			dest++;
+
+			u += stepu;
+			v += stepv;
+		}
+		startu = endu;
+		startv = endv;
+		width -= SPANSIZE;
+	}
+	if (width > 0)
+	{
+		if (width == 1)
+		{
+			u = (INT64)(startu);
+			v = (INT64)(startv);
+			// Lactozilla: Non-powers-of-two
+			{
+				fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
+				fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
+
+				// Carefully align all of my Friends.
+				if (x < 0)
+					x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
+				if (y < 0)
+					y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
+
+				x %= ds_flatwidth;
+				y %= ds_flatheight;
+
+				val = source[((y * ds_flatwidth) + x)];
+				if (val & 0xFF00)
+					*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
+			}
+		}
+		else
+		{
+			double left = width;
+			iz += ds_szp->x * left;
+			uz += ds_sup->x * left;
+			vz += ds_svp->x * left;
+
+			endz = 1.f/iz;
+			endu = uz*endz;
+			endv = vz*endz;
+			left = 1.f/left;
+			stepu = (INT64)((endu - startu) * left);
+			stepv = (INT64)((endv - startv) * left);
+			u = (INT64)(startu) + viewx;
+			v = (INT64)(startv) + viewy;
+
+			for (; width != 0; width--)
+			{
+				// Lactozilla: Non-powers-of-two
+				fixed_t x = (((fixed_t)u-viewx) >> FRACBITS);
+				fixed_t y = (((fixed_t)v-viewy) >> FRACBITS);
+
+				// Carefully align all of my Friends.
+				if (x < 0)
+					x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
+				if (y < 0)
+					y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
+
+				x %= ds_flatwidth;
+				y %= ds_flatheight;
+
+				val = source[((y * ds_flatwidth) + x)];
+				if (val & 0xFF00)
+					*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
+				dest++;
+
+				u += stepu;
+				v += stepv;
+			}
+		}
+	}
+}
+
 /**	\brief The R_DrawTranslucentSpan_NPO2_8 function
 	Draws the actual span with translucency.
 */
@@ -1016,9 +1308,6 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void)
 		vz += ds_svp->x;
 	} while (--width >= 0);
 #else
-#define SPANSIZE 16
-#define INVSPAN	0.0625f
-
 	startz = 1.f/iz;
 	startu = uz*startz;
 	startv = vz*startz;
diff --git a/src/r_plane.c b/src/r_plane.c
index 797919a9fb9e0636ef9453e71b652862f8459575..096d1dbd6ec8951b3765f30f11d44f6a1d4579b6 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -645,46 +645,48 @@ static void R_DrawSkyPlane(visplane_t *pl)
 	}
 }
 
-static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge)
+// Potentially override other stuff for now cus we're mean. :< But draw a slope plane!
+// I copied ZDoom's code and adapted it to SRB2... -Red
+void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge)
 {
-	// Potentially override other stuff for now cus we're mean. :< But draw a slope plane!
-	// I copied ZDoom's code and adapted it to SRB2... -Red
 	floatv3_t p, m, n;
 	float ang;
 	float vx, vy, vz;
+	float xscale = FIXED_TO_FLOAT(planexscale);
+	float yscale = FIXED_TO_FLOAT(planeyscale);
 	// compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly
 	// use this as a temp var to store P_GetSlopeZAt's return value each time
 	fixed_t temp;
 
-	vx = FIXED_TO_FLOAT(pl->viewx+xoffs);
-	vy = FIXED_TO_FLOAT(pl->viewy-yoffs);
-	vz = FIXED_TO_FLOAT(pl->viewz);
+	vx = FIXED_TO_FLOAT(planeviewx+planexoffset);
+	vy = FIXED_TO_FLOAT(planeviewy-planeyoffset);
+	vz = FIXED_TO_FLOAT(planeviewz);
 
-	temp = P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy);
+	temp = P_GetSlopeZAt(slope, planeviewx, planeviewy);
 	zeroheight = FIXED_TO_FLOAT(temp);
 
 	// p is the texture origin in view space
 	// Don't add in the offsets at this stage, because doing so can result in
 	// errors if the flat is rotated.
-	ang = ANG2RAD(ANGLE_270 - pl->viewangle);
+	ang = ANG2RAD(ANGLE_270 - planeviewangle);
 	p.x = vx * cos(ang) - vy * sin(ang);
 	p.z = vx * sin(ang) + vy * cos(ang);
-	temp = P_GetSlopeZAt(pl->slope, -xoffs, yoffs);
+	temp = P_GetSlopeZAt(slope, -planexoffset, planeyoffset);
 	p.y = FIXED_TO_FLOAT(temp) - vz;
 
 	// m is the v direction vector in view space
-	ang = ANG2RAD(ANGLE_180 - (pl->viewangle + pl->plangle));
-	m.x = cos(ang);
-	m.z = sin(ang);
+	ang = ANG2RAD(ANGLE_180 - (planeviewangle + planeangle));
+	m.x = yscale * cos(ang);
+	m.z = yscale * sin(ang);
 
 	// n is the u direction vector in view space
-	n.x = sin(ang);
-	n.z = -cos(ang);
+	n.x = xscale * sin(ang);
+	n.z = -xscale * cos(ang);
 
-	ang = ANG2RAD(pl->plangle);
-	temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(sin(ang)), pl->viewy + FLOAT_TO_FIXED(cos(ang)));
+	ang = ANG2RAD(planeangle);
+	temp = P_GetSlopeZAt(slope, planeviewx + yscale * FLOAT_TO_FIXED(sin(ang)), planeviewy + yscale * FLOAT_TO_FIXED(cos(ang)));
 	m.y = FIXED_TO_FLOAT(temp) - zeroheight;
-	temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang)));
+	temp = P_GetSlopeZAt(slope, planeviewx + xscale * FLOAT_TO_FIXED(cos(ang)), planeviewy - xscale * FLOAT_TO_FIXED(sin(ang)));
 	n.y = FIXED_TO_FLOAT(temp) - zeroheight;
 
 	if (ds_powersoftwo)
@@ -700,42 +702,50 @@ static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge)
 
 	// Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using.
 #define CROSS(d, v1, v2) \
-d.x = (v1.y * v2.z) - (v1.z * v2.y);\
-d.y = (v1.z * v2.x) - (v1.x * v2.z);\
-d.z = (v1.x * v2.y) - (v1.y * v2.x)
-	CROSS(ds_su[i], p, m);
-	CROSS(ds_sv[i], p, n);
-	CROSS(ds_sz[i], m, n);
+d->x = (v1.y * v2.z) - (v1.z * v2.y);\
+d->y = (v1.z * v2.x) - (v1.x * v2.z);\
+d->z = (v1.x * v2.y) - (v1.y * v2.x)
+		CROSS(ds_sup, p, m);
+		CROSS(ds_svp, p, n);
+		CROSS(ds_szp, m, n);
 #undef CROSS
 
-	ds_su[i].z *= focallengthf;
-	ds_sv[i].z *= focallengthf;
-	ds_sz[i].z *= focallengthf;
+	ds_sup->z *= focallengthf;
+	ds_svp->z *= focallengthf;
+	ds_szp->z *= focallengthf;
 
 	// Premultiply the texture vectors with the scale factors
 #define SFMULT 65536.f
 	if (ds_powersoftwo)
 	{
-		ds_su[i].x *= (SFMULT * (1<<nflatshiftup));
-		ds_su[i].y *= (SFMULT * (1<<nflatshiftup));
-		ds_su[i].z *= (SFMULT * (1<<nflatshiftup));
-		ds_sv[i].x *= (SFMULT * (1<<nflatshiftup));
-		ds_sv[i].y *= (SFMULT * (1<<nflatshiftup));
-		ds_sv[i].z *= (SFMULT * (1<<nflatshiftup));
+		ds_sup->x *= (SFMULT * (1<<nflatshiftup));
+		ds_sup->y *= (SFMULT * (1<<nflatshiftup));
+		ds_sup->z *= (SFMULT * (1<<nflatshiftup));
+		ds_svp->x *= (SFMULT * (1<<nflatshiftup));
+		ds_svp->y *= (SFMULT * (1<<nflatshiftup));
+		ds_svp->z *= (SFMULT * (1<<nflatshiftup));
 	}
 	else
 	{
 		// Lactozilla: I'm essentially multiplying the vectors by FRACUNIT...
-		ds_su[i].x *= SFMULT;
-		ds_su[i].y *= SFMULT;
-		ds_su[i].z *= SFMULT;
-		ds_sv[i].x *= SFMULT;
-		ds_sv[i].y *= SFMULT;
-		ds_sv[i].z *= SFMULT;
+		ds_sup->x *= SFMULT;
+		ds_sup->y *= SFMULT;
+		ds_sup->z *= SFMULT;
+		ds_svp->x *= SFMULT;
+		ds_svp->y *= SFMULT;
+		ds_svp->z *= SFMULT;
 	}
 #undef SFMULT
 }
 
+static void R_SlopePlaneVectors(visplane_t *pl, INT32 i, float fudge)
+{
+	ds_sup = &ds_su[i];
+	ds_svp = &ds_sv[i];
+	ds_szp = &ds_sz[i];
+	R_CalculateSlopeVectors(pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoffs, yoffs, pl->viewangle, pl->plangle, fudge);
+}
+
 void R_DrawSinglePlane(visplane_t *pl)
 {
 	levelflat_t *levelflat;
@@ -992,7 +1002,7 @@ void R_DrawSinglePlane(visplane_t *pl)
 				R_PlaneRipple(pl, i, plheight);
 				xoffs = rxoffs + ripple_xfrac;
 				yoffs = ryoffs + ripple_yfrac;
-				R_SlopeVectors(pl, i, fudgecanyon);
+				R_SlopePlaneVectors(pl, i, fudgecanyon);
 			}
 
 			xoffs = rxoffs;
@@ -1000,7 +1010,7 @@ void R_DrawSinglePlane(visplane_t *pl)
 		}
 		else
 #endif
-			R_SlopeVectors(pl, 0, fudgecanyon);
+			R_SlopePlaneVectors(pl, 0, fudgecanyon);
 
 #ifndef NOWATER
 		if (itswater && (spanfunctype == SPANDRAWFUNC_WATER))
diff --git a/src/r_plane.h b/src/r_plane.h
index 15f7f07f308830fd217ca6af05f516bf8d0b55b8..e6dffb4da6561ff5a4ccf0049c3bb004209cde63 100644
--- a/src/r_plane.h
+++ b/src/r_plane.h
@@ -84,11 +84,15 @@ 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);
 
-// Draws a single visplane.
-void R_DrawSinglePlane(visplane_t *pl);
 void R_CheckFlatLength(size_t size);
 boolean R_CheckPowersOfTwo(void);
 
+// Draws a single visplane.
+void R_DrawSinglePlane(visplane_t *pl);
+
+// Calculates the slope vectors needed for tilted span drawing.
+void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge);
+
 typedef struct planemgr_s
 {
 	visplane_t *plane;
diff --git a/src/r_splats.c b/src/r_splats.c
index fa4d9eef8f4e591c6e37564fcf652a31ec540d6e..541221841ac97ea17250aa0ae756728e3419acc9 100644
--- a/src/r_splats.c
+++ b/src/r_splats.c
@@ -14,6 +14,7 @@
 #include "r_main.h"
 #include "r_splats.h"
 #include "r_bsp.h"
+#include "p_slopes.h"
 #include "w_wad.h"
 #include "z_zone.h"
 
@@ -143,10 +144,10 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
 // fill the polygon with linear interpolation, call span drawer for each
 // scan line
 // --------------------------------------------------------------------------
-void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis)
+void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis)
 {
 	// rasterizing
-	INT32 miny = viewheight + 1, maxy = 0, y, x1, ry1, x2, y2, i;
+	INT32 miny = viewheight + 1, maxy = 0, y, x1, ry1, x2, y2, i, xclip;
 	fixed_t offsetx = 0, offsety = 0;
 	fixed_t step;
 
@@ -217,19 +218,47 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis)
 	// do segment d -> left side of texture
 	RASTERPARAMS(0,3,pSplat->width-1,0,0,1);
 
-	ds_source = pSplat->pic;
+	ds_source = (UINT8 *)pSplat->pic;
 	ds_flatwidth = pSplat->width;
 	ds_flatheight = pSplat->height;
 
 	if (R_CheckPowersOfTwo())
 		R_CheckFlatLength(ds_flatwidth * ds_flatheight);
 
+	// Lactozilla: I don't know what I'm doing
+	if (pSplat->tilted)
+	{
+		R_CalculateSlopeVectors(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, viewangle, pSplat->angle, 1.0f);
+		spanfunctype = SPANDRAWFUNC_TILTEDSPRITE;
+	}
+	else
+	{
+		if (pSplat->angle)
+		{
+			// Add the view offset, rotated by the plane angle.
+			fixed_t a = -pSplat->verts[0].x + viewx;
+			fixed_t b = -pSplat->verts[0].y + viewy;
+			angle = (pSplat->angle >> ANGLETOFINESHIFT);
+			offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle));
+			offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle));
+		}
+		else
+		{
+			offsetx = viewx - pSplat->verts[0].x;
+			offsety = pSplat->verts[0].y - viewy;
+		}
+	}
+
 	ds_transmap = NULL;
 
 	if (vis->transmap)
 	{
 		ds_transmap = vis->transmap;
-		spanfunctype = SPANDRAWFUNC_TRANSSPRITE;
+
+		if (pSplat->tilted)
+			spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE;
+		else
+			spanfunctype = SPANDRAWFUNC_TRANSSPRITE;
 	}
 
 	if (ds_powersoftwo)
@@ -237,7 +266,7 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis)
 	else
 		spanfunc = spanfuncs_npo2[spanfunctype];
 
-	if (pSplat->angle)
+	if (pSplat->angle && !pSplat->tilted)
 	{
 		memset(cachedheight, 0, sizeof(cachedheight));
 		angle = (viewangle + pSplat->angle - ANGLE_90) >> ANGLETOFINESHIFT;
@@ -252,7 +281,6 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis)
 	}
 
 	planeheight = abs(pSplat->z - viewz);
-
 	if (maxy >= vid.height)
 		maxy = vid.height-1;
 
@@ -276,33 +304,6 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis)
 		if (x2 >= vid.width)
 			x2 = vid.width - 1;
 
-		angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT;
-		planecos = FINECOSINE(angle);
-		planesin = FINESINE(angle);
-
-		if (planeheight != cachedheight[y])
-		{
-			cachedheight[y] = planeheight;
-			distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]);
-			xstep = cachedxstep[y] = FixedMul(distance, basexscale);
-			ystep = cachedystep[y] = FixedMul(distance, baseyscale);
-			// don't divide by zero
-			if ((span = abs(centery-y)))
-			{
-				xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span;
-				ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span;
-			}
-		}
-		else
-		{
-			distance = cacheddistance[y];
-			xstep = cachedxstep[y];
-			ystep = cachedystep[y];
-		}
-
-		ds_xstep = FixedDiv(xstep, pSplat->xscale);
-		ds_ystep = FixedDiv(ystep, pSplat->yscale);
-
 		ds_colormap = vis->colormap;
 		ds_translation = R_GetSpriteTranslation(vis);
 		if (ds_translation == NULL)
@@ -316,53 +317,61 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis)
 				ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps];
 		}
 
-		if (pSplat->angle)
+		R_ClipVisSprite(vis, x1-1, x2+1, drawsegs, NULL);
+		memset(ds_splatclip, 0, sizeof(ds_splatclip));
+
+		if (x2 >= x1 && x1 < viewwidth && x1 >= 0)
 		{
-			// Add the view offset, rotated by the plane angle.
-			fixed_t a = -pSplat->verts[0].x + viewx;
-			fixed_t b = -pSplat->verts[0].y + viewy;
-			angle = (pSplat->angle >> ANGLETOFINESHIFT);
-			offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle));
-			offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle));
+			for (xclip = x1; xclip <= x2; xclip++)
+			{
+				if (y >= mfloorclip[xclip])
+					ds_splatclip[xclip] = 1;
+			}
 		}
-		else
+
+		while (ds_splatclip[x1])
+			x1++;
+		i = x2;
+		while (i > x1)
 		{
-			offsetx = viewx - pSplat->verts[0].x;
-			offsety = pSplat->verts[0].y - viewy;
+			if (ds_splatclip[i])
+				x2 = i-1;
+			i--;
 		}
 
-		if (vis != NULL)
+		if (!pSplat->tilted)
 		{
-			INT32 xclip;
-
-			mfloorclip = vis->clipbot;
-			mceilingclip = vis->cliptop;
-
-			R_ClipVisSprite(vis, x1-1, x2+1, drawsegs, NULL);
-			memset(ds_splatclip, 0, sizeof(ds_splatclip));
+			angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT;
+			planecos = FINECOSINE(angle);
+			planesin = FINESINE(angle);
 
-			if (x2 >= x1 && x1 < viewwidth && x1 >= 0)
+			if (planeheight != cachedheight[y])
 			{
-				for (xclip = x1; xclip <= x2; xclip++)
+				cachedheight[y] = planeheight;
+				distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]);
+				xstep = cachedxstep[y] = FixedMul(distance, basexscale);
+				ystep = cachedystep[y] = FixedMul(distance, baseyscale);
+
+				// don't divide by zero
+				if ((span = abs(centery-y)))
 				{
-					if (y >= mfloorclip[xclip])
-						ds_splatclip[xclip] = 1;
+					xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span;
+					ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span;
 				}
 			}
-
-			while (ds_splatclip[x1])
-				x1++;
-			i = x2;
-			while (i > x1)
+			else
 			{
-				if (ds_splatclip[i])
-					x2 = i-1;
-				i--;
+				distance = cacheddistance[y];
+				xstep = cachedxstep[y];
+				ystep = cachedystep[y];
 			}
-		}
 
-		ds_xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale);
-		ds_yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale);
+			ds_xstep = FixedDiv(xstep, pSplat->xscale);
+			ds_ystep = FixedDiv(ystep, pSplat->yscale);
+
+			ds_xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale);
+			ds_yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale);
+		}
 
 		if (x2 >= x1)
 		{
@@ -376,7 +385,7 @@ void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis)
 		rastertab[y].maxx = INT32_MIN;
 	}
 
-	if (pSplat->angle)
+	if (pSplat->angle && !pSplat->tilted)
 	{
 		memset(cachedheight, 0, sizeof(cachedheight));
 		angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT;
diff --git a/src/r_splats.h b/src/r_splats.h
index 9c01084cf1750b4fea0141f9837156f20b4cedac..b0707e95bb75dd811bcfdd39a39ef7304ea57db3 100644
--- a/src/r_splats.h
+++ b/src/r_splats.h
@@ -31,17 +31,19 @@ extern struct rastery_s *prastertab; // for ASM code
 #ifdef FLOORSPLATS
 typedef struct floorsplat_s
 {
-	UINT8 *pic;
+	UINT16 *pic;
 	INT32 width, height;
 	fixed_t scale, xscale, yscale;
 	angle_t angle;
+	boolean tilted; // Uses the tilted drawer
+	pslope_t slope;
 
-	vertex_t verts[4]; // (x,y) as viewed from above on map
+	vector3_t verts[4]; // (x,y,z) as viewed from above on map
 	fixed_t x, y, z; // position
 	mobj_t *mobj; // Mobj it is tied to
 } floorsplat_t;
 
-void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis);
+void R_RenderFloorSplat(floorsplat_t *pSplat, vector2_t *verts, vissprite_t *vis);
 extern UINT8 ds_splatclip[MAXVIDWIDTH];
 #endif
 
diff --git a/src/r_things.c b/src/r_things.c
index d60228e36a6a47888f14c0d5e45463d667ad80f6..99fa2c7c5a4099248866e0b32056c1fb1afc2cf7 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1415,7 +1415,7 @@ static void R_ProjectSprite(mobj_t *thing)
 	fixed_t tx, tz;
 	fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!!
 	fixed_t sortscale, sortsplat = 0;
-	fixed_t sort_x = 0, sort_y = 0;
+	fixed_t sort_x = 0, sort_y = 0, sort_z;
 
 	INT32 x1, x2;
 
@@ -1764,10 +1764,10 @@ static void R_ProjectSprite(mobj_t *thing)
 	// Adjust the sort scale if needed
 	if (splat)
 	{
-		tz = (patch->height - patch->topoffset) * FRACUNIT;
+		sort_z = (patch->height - patch->topoffset) * FRACUNIT;
 		ang = (viewangle >> ANGLETOFINESHIFT);
-		sort_x = FixedMul(FixedMul(FixedMul(spritexscale, this_scale), tz), FINECOSINE(ang));
-		sort_y = FixedMul(FixedMul(FixedMul(spriteyscale, this_scale), tz), FINESINE(ang));
+		sort_x = FixedMul(FixedMul(FixedMul(spritexscale, this_scale), sort_z), FINECOSINE(ang));
+		sort_y = FixedMul(FixedMul(FixedMul(spriteyscale, this_scale), sort_z), FINESINE(ang));
 	}
 
 	if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY)
@@ -1797,8 +1797,8 @@ static void R_ProjectSprite(mobj_t *thing)
 	{
 		tr_x = (thing->x + sort_x) - viewx;
 		tr_y = (thing->y + sort_y) - viewy;
-		tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
-		sortscale = FixedDiv(projectiony, tz);
+		sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
+		sortscale = FixedDiv(projectiony, sort_z);
 	}
 
 	// Calculate the splat's sortscale
@@ -1806,8 +1806,8 @@ static void R_ProjectSprite(mobj_t *thing)
 	{
 		tr_x = (thing->x - sort_x) - viewx;
 		tr_y = (thing->y - sort_y) - viewy;
-		tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
-		sortsplat = FixedDiv(projectiony, tz);
+		sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
+		sortsplat = FixedDiv(projectiony, sort_z);
 	}
 
 	// PORTAL SPRITE CLIPPING
@@ -2796,8 +2796,8 @@ static void R_DrawVisSplat(vissprite_t *spr)
 #ifdef FLOORSPLATS
 	floorsplat_t splat;
 	fixed_t tr_x, tr_y, rot_x, rot_y, rot_z;
-	vertex_t *v3d;
-	vertex_t v2d[4];
+	vector3_t *v3d;
+	vector2_t v2d[4];
 	fixed_t x, y;
 	fixed_t w, h;
 	angle_t splatangle, angle;
@@ -2809,6 +2809,7 @@ static void R_DrawVisSplat(vissprite_t *spr)
 	boolean vflip = (spr->cut & SC_VFLIP);
 	UINT8 flipflags = 0;
 	vector2_t rotated[4];
+	pslope_t *slope = NULL;
 	INT32 i;
 
 	if (hflip)
@@ -2826,6 +2827,9 @@ static void R_DrawVisSplat(vissprite_t *spr)
 	splat.height = spr->patch->height;
 	splat.scale = spr->mobj->scale;
 
+	if (spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES)
+		splat.scale = FixedMul(splat.scale, ((skin_t *)spr->mobj->skin)->highresscale);
+
 	if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD)
 		splatangle = spr->mobj->angle;
 	else
@@ -2859,6 +2863,7 @@ static void R_DrawVisSplat(vissprite_t *spr)
 	splat.x = x;
 	splat.y = y;
 	splat.z = spr->mobj->z;
+	splat.tilted = false;
 
 	// Set positions
 
@@ -2889,14 +2894,53 @@ static void R_DrawVisSplat(vissprite_t *spr)
 		rotated[i].y = FixedMul(splat.verts[i].x, sa) + FixedMul(splat.verts[i].y, ca);
 	}
 
+	if (spr->renderflags & RF_SLOPESPLAT)
+	{
+		slope = spr->mobj->standingslope;
+		splat.tilted = (slope != NULL);
+	}
+
+	if (splat.tilted)
+	{
+		// Lactozilla: Just copy the entire slope LMFAOOOO
+		pslope_t *s = &splat.slope;
+
+		s->o.x = slope->o.x;
+		s->o.y = slope->o.y;
+		s->o.z = slope->o.z;
+
+		s->d.x = slope->d.x;
+		s->d.y = slope->d.y;
+
+		s->normal.x = slope->normal.x;
+		s->normal.y = slope->normal.y;
+		s->normal.z = slope->normal.z;
+
+		s->zdelta = slope->zdelta;
+		s->zangle = slope->zangle;
+		s->xydirection = slope->xydirection;
+
+		s->next = NULL;
+		s->flags = 0;
+	}
+
 	// Translate
 	for (i = 0; i < 4; i++)
 	{
-		splat.verts[i].x = rotated[i].x + x;
-		splat.verts[i].y = rotated[i].y + y;
-	}
+		tr_x = rotated[i].x + x;
+		tr_y = rotated[i].y + y;
 
-	rot_z = splat.z - viewz;
+		if (slope)
+		{
+			rot_z = P_GetSlopeZAt(slope, tr_x, tr_y);
+			splat.verts[i].z = rot_z;
+		}
+		else
+			splat.verts[i].z = splat.z;
+
+		splat.verts[i].x = tr_x;
+		splat.verts[i].y = tr_y;
+	}
 
 	for (i = 0; i < 4; i++)
 	{
@@ -2909,6 +2953,7 @@ static void R_DrawVisSplat(vissprite_t *spr)
 		// rotation around vertical y axis
 		rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
 		rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
+		rot_z = v3d->z - viewz;
 
 		if (!rot_y || rot_y < FixedDiv(4*FRACUNIT, splat.scale))
 			return;
diff --git a/src/screen.c b/src/screen.c
index f5d182f3488b4ebb821242084b75ea652a349531..8b6c05b6a75da3b5b6ac21b60e0e78304d921b8c 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -126,6 +126,8 @@ void SCR_SetDrawFuncs(void)
 		spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8;
 		spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8;
 		spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8;
+		spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8;
+		spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_8;
 		spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8;
 #ifndef NOWATER
 		spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8;
@@ -144,6 +146,8 @@ void SCR_SetDrawFuncs(void)
 		spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8;
 		spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8;
 		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_FOG] = NULL; // Not needed
 #ifndef NOWATER
 		spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8;
diff --git a/src/screen.h b/src/screen.h
index 021c644ba9792be0fc82365b638872ccb3d87dcd..b139bd3b4b26af375df61454874d80e590696d08 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -144,6 +144,8 @@ enum
 	SPANDRAWFUNC_TRANSSPLAT,
 	SPANDRAWFUNC_SPRITE,
 	SPANDRAWFUNC_TRANSSPRITE,
+	SPANDRAWFUNC_TILTEDSPRITE,
+	SPANDRAWFUNC_TILTEDTRANSSPRITE,
 	SPANDRAWFUNC_FOG,
 #ifndef NOWATER
 	SPANDRAWFUNC_WATER,