diff --git a/src/r_bsp.c b/src/r_bsp.c
index d4f7694335ebc5530ea1865e23947687fe615f1b..01d2be67194ccb6df196cdfb581f3c5e606cc087 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -487,6 +487,10 @@ static void R_AddLine(seg_t *line)
 #endif
 		backsector->ceilingpic == frontsector->ceilingpic
 		&& backsector->floorpic == frontsector->floorpic
+#ifdef ESLOPE
+		&& backsector->f_slope == frontsector->f_slope
+		&& backsector->c_slope == frontsector->c_slope
+#endif
 		&& backsector->lightlevel == frontsector->lightlevel
 		&& !curline->sidedef->midtexture
 		// Check offsets too!
@@ -862,7 +866,11 @@ static void R_Subsector(size_t num)
 		&& sectors[frontsector->heightsec].ceilingpic == skyflatnum)))
 	{
 		floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel,
-			frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL);
+			frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL
+#ifdef ESLOPE
+			, frontsector->f_slope
+#endif
+			);
 	}
 	else
 		floorplane = NULL;
@@ -877,7 +885,11 @@ static void R_Subsector(size_t num)
 	{
 		ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic,
 			ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle,
-			ceilingcolormap, NULL);
+			ceilingcolormap, NULL
+#ifdef ESLOPE
+			, frontsector->c_slope
+#endif
+			);
 	}
 	else
 		ceilingplane = NULL;
@@ -914,7 +926,11 @@ static void R_Subsector(size_t num)
 					viewz < *rover->bottomheight);
 				ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic,
 					*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs,
-					*rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover);
+					*rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover
+#ifdef ESLOPE
+					, NULL // will ffloors be slopable eventually?
+#endif
+					);
 
 				ffloor[numffloors].height = *rover->bottomheight;
 				ffloor[numffloors].ffloor = rover;
@@ -932,7 +948,11 @@ static void R_Subsector(size_t num)
 				light = R_GetPlaneLight(frontsector, *rover->topheight, viewz < *rover->topheight);
 				ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic,
 					*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle,
-					frontsector->lightlist[light].extra_colormap, rover);
+					frontsector->lightlist[light].extra_colormap, rover
+#ifdef ESLOPE
+					, NULL // will ffloors be slopable eventually?
+#endif
+					);
 				ffloor[numffloors].height = *rover->topheight;
 				ffloor[numffloors].ffloor = rover;
 				numffloors++;
@@ -985,7 +1005,11 @@ static void R_Subsector(size_t num)
 						polysec->lightlevel, xoff, yoff,
 						polysec->floorpic_angle-po->angle,
 						NULL,
-						NULL);
+						NULL
+#ifdef ESLOPE
+					, NULL // will ffloors be slopable eventually?
+#endif
+					);
 				//ffloor[numffloors].plane->polyobj = po;
 
 				ffloor[numffloors].height = polysec->floorheight;
@@ -1022,7 +1046,11 @@ static void R_Subsector(size_t num)
 				light = 0;
 				ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
 					polysec->lightlevel, xoff, yoff, polysec->ceilingpic_angle-po->angle,
-					NULL, NULL);
+					NULL, NULL
+#ifdef ESLOPE
+					, NULL // will ffloors be slopable eventually?
+#endif
+					);
 				//ffloor[numffloors].plane->polyobj = po;
 
 				ffloor[numffloors].polyobj = po;
diff --git a/src/r_draw.c b/src/r_draw.c
index cd219c15f624cf9726148ac6d42124f2f40eef99..f4886d262bee00494d5adfef70f8e18c4c3f6e8a 100644
--- a/src/r_draw.c
+++ b/src/r_draw.c
@@ -103,6 +103,12 @@ fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
 UINT8 *ds_source; // start of a 64*64 tile image
 UINT8 *ds_transmap; // one of the translucency tables
 
+#ifdef ESLOPE
+pslope_t *ds_slope; // Current slope being used
+v3float_t ds_su, ds_sv, ds_sz; // Vectors for... stuff?
+float focallengthf;
+#endif
+
 /**	\brief Variable flat sizes
 */
 
diff --git a/src/r_draw.h b/src/r_draw.h
index 061a271b15be4d466d108b2b313f9e389a738792..17988753693ed9f18b9c0cc716a58ff83da6795c 100644
--- a/src/r_draw.h
+++ b/src/r_draw.h
@@ -60,6 +60,12 @@ extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
 extern UINT8 *ds_source; // start of a 64*64 tile image
 extern UINT8 *ds_transmap;
 
+#ifdef ESLOPE
+pslope_t *ds_slope; // Current slope being used
+v3float_t ds_su, ds_sv, ds_sz; // Vectors for... stuff?
+float focallengthf;
+#endif
+
 // Variable flat sizes
 extern UINT32 nflatxshift;
 extern UINT32 nflatyshift;
@@ -141,6 +147,9 @@ void ASMCALL R_DrawSpan_8_MMX(void);
 void R_DrawTranslatedColumn_8(void);
 void R_DrawTranslatedTranslucentColumn_8(void);
 void R_DrawSpan_8(void);
+#ifdef ESLOPE
+void R_DrawTiltedSpan_8(void);
+#endif
 void R_DrawSplat_8(void);
 void R_DrawTranslucentSplat_8(void);
 void R_DrawTranslucentSpan_8(void);
diff --git a/src/r_draw8.c b/src/r_draw8.c
index e0264ba921a1b2ee3ec7824ba86ffe17a5a86db9..6a240c34988f3f42f002717a05d17563214565c3 100644
--- a/src/r_draw8.c
+++ b/src/r_draw8.c
@@ -526,6 +526,49 @@ void R_DrawSpan_8 (void)
 	}
 }
 
+#ifdef ESLOPE
+/**	\brief The R_DrawTiltedSpan_8 function
+	Draw slopes! Holy sheit!
+*/
+void R_DrawTiltedSpan_8(void)
+{
+	// x1, x2 = ds_x1, ds_x2
+	int width = ds_x2 - ds_x1;
+	double iz, uz, vz;
+	BYTE *fb;
+	DWORD u, v;
+	int i;
+
+	UINT8 *source;
+	UINT8 *colormap;
+	UINT8 *dest;
+
+	iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx);
+
+	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
+	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
+
+	dest = ylookup[ds_y] + columnofs[ds_x1];
+	source = ds_source;
+	colormap = ds_colormap;
+
+	// The "perfect" reference version of this routine. Pretty slow.
+	// Use it only to see how things are supposed to look.
+	i = 0;
+	do
+	{
+		double z = 1.f/iz;
+		u = (INT64)(uz*z) + viewx;
+		v = (INT64)(vz*z) + viewy;
+		*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
+		dest++;
+		iz += ds_sz.x;
+		uz += ds_su.x;
+		vz += ds_sv.x;
+	} while (--width >= 0);
+}
+#endif // ESLOPE
+
 /**	\brief The R_DrawSplat_8 function
 	Just like R_DrawSpan_8, but skips transparent pixels.
 */
diff --git a/src/r_main.c b/src/r_main.c
index 1edcb815b5f5dbded625c5474bb5213a16f635bc..127801598703014296efae0a08170b1adc329f15 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -527,6 +527,8 @@ static void R_InitTextureMapping(void)
 	focallength = FixedDiv(centerxfrac,
 		FINETANGENT(FINEANGLES/4+/*cv_fov.value*/ FIELDOFVIEW/2));
 
+	focallengthf = FIXED_TO_FLOAT(focallength);
+
 	for (i = 0; i < FINEANGLES/2; i++)
 	{
 		if (FINETANGENT(i) > FRACUNIT*2)
diff --git a/src/r_plane.c b/src/r_plane.c
index dcff25c1304fd45deba11b9845cdaa40f23c7658..44b65ad106c168fea119b82cfdb5013e812f148a 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -423,7 +423,11 @@ static visplane_t *new_visplane(unsigned hash)
 //
 visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 	fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap,
-	ffloor_t *pfloor)
+	ffloor_t *pfloor
+#ifdef ESLOPE
+			, pslope_t *slope
+#endif
+			)
 {
 	visplane_t *check;
 	unsigned hash;
@@ -462,7 +466,11 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 			&& xoff == check->xoffs && yoff == check->yoffs
 			&& planecolormap == check->extra_colormap
 			&& !pfloor && !check->ffloor && check->viewz == viewz
-			&& check->viewangle == viewangle)
+			&& check->viewangle == viewangle
+#ifdef ESLOPE
+			&& check->slope == slope
+#endif
+			)
 		{
 			return check;
 		}
@@ -485,6 +493,9 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 #ifdef POLYOBJECTS_PLANES
 	check->polyobj = NULL;
 #endif
+#ifdef ESLOPE
+	check->slope = slope;
+#endif
 
 	memset(check->top, 0xff, sizeof (check->top));
 	memset(check->bottom, 0x00, sizeof (check->bottom));
@@ -551,6 +562,9 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
 		new_pl->plangle = pl->plangle;
 #ifdef POLYOBJECTS_PLANES
 		new_pl->polyobj = pl->polyobj;
+#endif
+#ifdef ESLOPE
+		new_pl->slope = pl->slope;
 #endif
 		pl = new_pl;
 		pl->minx = start;
@@ -905,6 +919,78 @@ void R_DrawSinglePlane(visplane_t *pl)
 			break;
 	}
 
+#ifdef ESLOPE
+	if (pl->slope) {
+		// 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
+		static const float ifloatpow2[16] =
+		{
+			// ifloatpow2[i] = 1 / (1 << i)
+			64.f, 32.f, 16.f, 8.f, 4.f, 2.f, 1.f, 0.5f,
+			0.25f, 0.125f, 0.0625f, 0.03125f, 0.015625f, 0.0078125f,
+			0.00390625f, 0.001953125f
+			/*, 0.0009765625f, 0.00048828125f, 0.000244140625f,
+			1.220703125e-4f, 6.103515625e-5, 3.0517578125e-5*/
+		};
+		double lxscale, lyscale;
+		double xscale, yscale;
+		v3float_t p, m, n;
+		angle_t ang;
+		double zeroheight;
+
+		double vx = FIXED_TO_FLOAT(viewx);
+		double vy = FIXED_TO_FLOAT(viewy);
+		double vz = FIXED_TO_FLOAT(viewz);
+
+		zeroheight = FIXED_TO_FLOAT(P_GetZAt(pl->slope, viewx, viewy));
+
+		// 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 = (ANGLE_270 - viewangle)>>ANGLETOFINESHIFT;
+		p.x = vx * FIXED_TO_FLOAT(FINECOSINE(ang)) - vy * FIXED_TO_FLOAT(FINESINE(ang));
+		p.z = vx * FIXED_TO_FLOAT(FINESINE(ang)) + vy * FIXED_TO_FLOAT(FINECOSINE(ang));
+		p.y = FIXED_TO_FLOAT(P_GetZAt(pl->slope, 0, 0)) - vz;
+
+		// m is the v direction vector in view space
+		ang = (ANGLE_180 - viewangle - pl->plangle) >> ANGLETOFINESHIFT;
+		m.x = FIXED_TO_FLOAT(FINECOSINE(ang));
+		m.z = FIXED_TO_FLOAT(FINESINE(ang));
+
+		// n is the u direction vector in view space
+		ang += ANGLE_90>>ANGLETOFINESHIFT;
+		ang &= FINEMASK;
+		n.x = -FIXED_TO_FLOAT(FINECOSINE(ang));
+		n.z = -FIXED_TO_FLOAT(FINESINE(ang));
+
+		ang = pl->plangle>>ANGLETOFINESHIFT;
+		m.y = FIXED_TO_FLOAT(P_GetZAt(pl->slope, viewx + FINESINE(ang), viewy + FINECOSINE(ang))) - zeroheight;
+		ang += ANGLE_90>>ANGLETOFINESHIFT;
+		ang &= FINEMASK;
+		n.y = FIXED_TO_FLOAT(P_GetZAt(pl->slope, viewx + FINESINE(ang), viewy + FINECOSINE(ang))) - zeroheight;
+
+		M_CrossProduct3f(&ds_su, &p, &m);
+		M_CrossProduct3f(&ds_sv, &p, &n);
+		M_CrossProduct3f(&ds_sz, &m, &n);
+
+		ds_su.z *= focallengthf;
+		ds_sv.z *= focallengthf;
+		ds_sz.z *= focallengthf;
+
+		// Premultiply the texture vectors with the scale factors
+#define SFMULT 65536.f*(1<<nflatshiftup)
+		ds_su.x *= SFMULT;
+		ds_su.y *= SFMULT;
+		ds_su.z *= SFMULT;
+		ds_sv.x *= SFMULT;
+		ds_sv.y *= SFMULT;
+		ds_sv.z *= SFMULT;
+#undef SFMULT
+
+		spanfunc = R_DrawTiltedSpan_8;
+	}
+#endif // ESLOPE
+
 	xoffs = pl->xoffs;
 	yoffs = pl->yoffs;
 	planeheight = abs(pl->height - pl->viewz);
diff --git a/src/r_plane.h b/src/r_plane.h
index f3a7f573fe90c0201f944430953327f29c999e17..b2346636b3094b4bc2e49694b9c884a27fcf89cd 100644
--- a/src/r_plane.h
+++ b/src/r_plane.h
@@ -61,6 +61,9 @@ typedef struct visplane_s
 #ifdef POLYOBJECTS_PLANES
 	polyobj_t *polyobj;
 #endif
+#ifdef ESLOPE
+	pslope_t *slope;
+#endif
 } visplane_t;
 
 extern visplane_t *floorplane;
@@ -91,7 +94,11 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2);
 void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2);
 void R_DrawPlanes(void);
 visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
-	extracolormap_t *planecolormap, ffloor_t *ffloor);
+	extracolormap_t *planecolormap, ffloor_t *ffloor
+#ifdef ESLOPE
+	, pslope_t *slope
+#endif
+	);
 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);
diff --git a/src/r_segs.c b/src/r_segs.c
index d582f13fe31d80192708a476b03b10e64a73f579..2cb04b25e310b3cfa1fb1c45b6e5d50de56ce8d2 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -1757,6 +1757,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		if (worldlow != worldbottom
 #ifdef ESLOPE
 			|| worldlowslope != worldbottomslope
+			|| backsector->f_slope != frontsector->f_slope
 #endif
 		    || backsector->floorpic != frontsector->floorpic
 		    || backsector->lightlevel != frontsector->lightlevel
@@ -1782,6 +1783,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		if (worldhigh != worldtop
 #ifdef ESLOPE
 			|| worldhighslope != worldtopslope
+			|| backsector->c_slope != frontsector->c_slope
 #endif
 		    || backsector->ceilingpic != frontsector->ceilingpic
 		    || backsector->lightlevel != frontsector->lightlevel
@@ -2092,13 +2094,21 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	//  and doesn't need to be marked.
 	if (frontsector->heightsec == -1)
 	{
-		if (frontsector->floorheight >= viewz)
+		if ((
+#ifdef ESLOPE
+			frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) :
+#endif
+			frontsector->floorheight) >= viewz)
 		{
 			// above view plane
 			markfloor = false;
 		}
 
-		if (frontsector->ceilingheight <= viewz &&
+		if ((
+#ifdef ESLOPE
+			frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) :
+#endif
+			frontsector->ceilingheight) <= viewz &&
 		    frontsector->ceilingpic != skyflatnum)
 		{
 			// below view plane