diff --git a/src/p_setup.c b/src/p_setup.c
index c29cc907e830e54bef7945e223ae0c5ee4b69802..42a6438a0f46996927ce5ec723bf51a06b6ff072 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -416,7 +416,9 @@ fixed_t P_SegLength(seg_t *seg)
 	return FixedHypot(dx, dy)<<1;
 }
 
+#ifdef HWRENDER
 /** Computes the length of a seg as a float.
+  * This is needed for OpenGL.
   *
   * \param seg Seg to compute length for.
   * \return Length as a float.
@@ -431,6 +433,7 @@ static inline float P_SegLengthFloat(seg_t *seg)
 
 	return (float)hypot(dx, dy);
 }
+#endif
 
 /** Loads the SEGS resource from a level.
   *
@@ -457,10 +460,10 @@ static void P_LoadRawSegs(UINT8 *data, size_t i)
 		li->v2 = &vertexes[SHORT(ml->v2)];
 
 		li->length = P_SegLength(li);
-		li->flength = P_SegLengthFloat(li);
 #ifdef HWRENDER
 		if (rendermode == render_opengl)
 		{
+			li->flength = P_SegLengthFloat(li);
 			//Hurdler: 04/12/2000: for now, only used in hardware mode
 			li->lightmaps = NULL; // list of static lightmap for this seg
 		}
diff --git a/src/r_bsp.c b/src/r_bsp.c
index b6dbfd76a62813d346cccec52b5eeeac64e461e5..51d9bd3fddad73389f6756305a9fe469c76beb69 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -410,7 +410,7 @@ static void R_AddLine(seg_t *line)
 		return;
 
 	// Global angle needed by segcalc.
-	rw.angle1 = angle1;
+	rw_angle1 = angle1;
 	angle1 -= viewangle;
 	angle2 -= viewangle;
 
diff --git a/src/r_defs.h b/src/r_defs.h
index cfc55ef187eebdfbf3862be28fa78825a3c9632d..2791ac8b069edf9d4e2579704fa948998fd328d9 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -582,12 +582,11 @@ typedef struct seg_s
 	sector_t *backsector;
 
 	fixed_t length;	// precalculated seg length
-	float flength; // ditto but float
-
 #ifdef HWRENDER
 	// new pointers so that AdjustSegs doesn't mess with v1/v2
 	void *pv1; // polyvertex_t
 	void *pv2; // polyvertex_t
+	float flength; // length of the seg, used by hardware renderer
 
 	lightmap_t *lightmaps; // for static lightmap
 #endif
diff --git a/src/r_main.c b/src/r_main.c
index 8ef47d21d994ea0ce81c249ce3ee2582cae2dc65..a5f4bc1184e45a00d4c5c6c407ce3a38241117b3 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -366,7 +366,7 @@ angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1)
 // R_ScaleFromGlobalAngle
 // Returns the texture mapping scale for the current line (horizontal span)
 //  at the given angle.
-// rw.distance must be calculated first.
+// rw_distance must be calculated first.
 //
 // killough 5/2/98: reformatted, cleaned up
 //
@@ -374,8 +374,8 @@ angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1)
 fixed_t R_ScaleFromGlobalAngle(angle_t visangle)
 {
 	angle_t anglea = ANGLE_90 + (visangle-viewangle);
-	angle_t angleb = ANGLE_90 + (visangle-rw.normalangle);
-	fixed_t den = FixedMul(rw.distance, FINESINE(anglea>>ANGLETOFINESHIFT));
+	angle_t angleb = ANGLE_90 + (visangle-rw_normalangle);
+	fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT));
 	// proff 11/06/98: Changed for high-res
 	fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT));
 
diff --git a/src/r_segs.c b/src/r_segs.c
index 750b32522d183dbd185bdfe104a194485f81b109..2c8aadec88b7286fd5c5e08d1571a5a30a90108f 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -37,21 +37,25 @@ static boolean maskedtexture;
 static INT32 toptexture, bottomtexture, midtexture;
 static INT32 numthicksides, numbackffloors;
 
-static boolean bothceilingssky;
-static boolean bothfloorssky;
-
-#ifdef ESLOPE
-static vertex_t segleft, segright;
-static fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide;
-#endif
+angle_t rw_normalangle;
+// angle to line origin
+angle_t rw_angle1;
+fixed_t rw_distance;
 
 //
 // regular wall
 //
-renderwall_t rw;
+static INT32 rw_x, rw_stopx;
+static angle_t rw_centerangle;
+static fixed_t rw_offset;
+static fixed_t rw_offset2; // for splats
+static fixed_t rw_scale, rw_scalestep;
+static fixed_t rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid;
 static INT32 worldtop, worldbottom, worldhigh, worldlow;
 #ifdef ESLOPE
 static INT32 worldtopslope, worldbottomslope, worldhighslope, worldlowslope; // worldtop/bottom at end of slope
+static fixed_t rw_toptextureslide, rw_midtextureslide, rw_bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes
+static fixed_t rw_midtextureback, rw_midtexturebackslide; // Values for masked midtexture height calculation
 #endif
 static fixed_t pixhigh, pixlow, pixhighstep, pixlowstep;
 static fixed_t topfrac, topstep;
@@ -63,1874 +67,1640 @@ static INT16 *maskedtexturecol;
 static fixed_t *maskedtextureheight = NULL;
 #endif
 
-// R_ExpandPlaneY
-//
-// A simple function to modify a vsplane's top and bottom for a particular column
-// Sort of like R_ExpandPlane in r_plane.c, except this is vertical expansion
-static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bottom)
-{
-	// Expand the plane, don't shrink it!
-	// note: top and bottom default to 0xFFFF and 0x0000 respectively, which is totally compatible with this
-	if (pl->top[x] > top)       pl->top[x] = top;
-	if (pl->bottom[x] < bottom) pl->bottom[x] = bottom;
-}
-
-//
-// R_RenderSegLoop
-// Draws zero, one, or two textures (and possibly a masked
-//  texture) for walls.
-// Can draw or mark the starting pixel of floor and ceiling
-//  textures.
-// CALLED: CORE LOOPING ROUTINE.
-//
-#define HEIGHTBITS              12
-#define HEIGHTUNIT              (1<<HEIGHTBITS)
-
+// ==========================================================================
+// R_Splats Wall Splats Drawer
+// ==========================================================================
 
-//profile stuff ---------------------------------------------------------
-//#define TIMING
-#ifdef TIMING
-#include "p5prof.h"
-INT64 mycount;
-INT64 mytotal = 0;
-UINT32 nombre = 100000;
-//static   char runtest[10][80];
-#endif
-//profile stuff ---------------------------------------------------------
+#ifdef WALLSPLATS
+static INT16 last_ceilingclip[MAXVIDWIDTH];
+static INT16 last_floorclip[MAXVIDWIDTH];
 
-static void R_RenderSegLoop (void)
+static void R_DrawSplatColumn(column_t *column)
 {
-	angle_t angle;
-	size_t  pindex = 0;
-	INT32     yl;
-	INT32     yh;
-
-	INT32     mid;
-	fixed_t texturecolumn = 0;
-#ifdef ESLOPE
-	fixed_t oldtexturecolumn = -1;
-#endif
-	INT32     top;
-	INT32     bottom;
-	INT32     i;
+	INT32 topscreen, bottomscreen;
+	fixed_t basetexturemid;
+	INT32 topdelta, prevdelta = -1;
 
-	// Set the shadowed column drawer for light lists.
-	if (dc_numlights)
-		colfunc = colfuncs[COLDRAWFUNC_SHADOWED];
+	basetexturemid = dc_texturemid;
 
-	for (; rw.x < rw.stopx; rw.x++)
+	for (; column->topdelta != 0xff ;)
 	{
-		// mark floor / ceiling areas
-		yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
-
-		top = ceilingclip[rw.x]+1;
+		// calculate unclipped screen coordinates for post
+		topdelta = column->topdelta;
+		if (topdelta <= prevdelta)
+			topdelta += prevdelta;
+		prevdelta = topdelta;
+		topscreen = sprtopscreen + spryscale*topdelta;
+		bottomscreen = topscreen + spryscale*column->length;
 
-		// no space above wall?
-		if (yl < top)
-			yl = top;
+		dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
+		dc_yh = (bottomscreen-1)>>FRACBITS;
 
-		if (markceiling)
+		if (dc_yh >= last_floorclip[dc_x])
+			dc_yh = last_floorclip[dc_x] - 1;
+		if (dc_yl <= last_ceilingclip[dc_x])
+			dc_yl = last_ceilingclip[dc_x] + 1;
+		if (dc_yl <= dc_yh && dl_yh < vid.height && yh > 0)
 		{
-#if 0
-			bottom = yl-1;
-
-			if (bottom >= floorclip[rw.x])
-				bottom = floorclip[rw.x]-1;
-
-			if (top <= bottom)
-#else
-			bottom = yl > floorclip[rw.x] ? floorclip[rw.x] : yl;
+			dc_source = (UINT8 *)column + 3;
+			dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
 
-			if (top <= --bottom && ceilingplane)
-#endif
-				R_ExpandPlaneY(ceilingplane, rw.x, top, bottom);
+			// Drawn by R_DrawColumn.
+			colfunc();
 		}
+		column = (column_t *)((UINT8 *)column + column->length + 4);
+	}
 
+	dc_texturemid = basetexturemid;
+}
 
-		yh = bottomfrac>>HEIGHTBITS;
-
-		bottom = floorclip[rw.x]-1;
-
-		if (yh > bottom)
-			yh = bottom;
-
-		if (markfloor)
-		{
-			top = yh < ceilingclip[rw.x] ? ceilingclip[rw.x] : yh;
-
-			if (++top <= bottom && floorplane)
-				R_ExpandPlaneY(floorplane, rw.x, top, bottom);
-		}
+static void R_DrawWallSplats(void)
+{
+	wallsplat_t *splat;
+	seg_t *seg;
+	angle_t angle, angle1, angle2;
+	INT32 x1, x2;
+	size_t pindex;
+	column_t *col;
+	patch_t *patch;
+	fixed_t texturecolumn;
 
-		if (numffloors)
-		{
-			firstseg->frontscale[rw.x] = frontscale[rw.x];
-			top = ceilingclip[rw.x]+1; // PRBoom
-			bottom = floorclip[rw.x]-1; // PRBoom
+	splat = (wallsplat_t *)linedef->splats;
 
-			for (i = 0; i < numffloors; i++)
-			{
-#ifdef POLYOBJECTS_PLANES
-				if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
-					continue;
-#endif
+	I_Assert(splat != NULL);
 
-				if (ffloor[i].height < viewz)
-				{
-					INT32 top_w = (ffloor[i].f_frac >> HEIGHTBITS) + 1;
-					INT32 bottom_w = ffloor[i].f_clip[rw.x];
+	seg = ds_p->curline;
 
-					if (top_w < top)
-						top_w = top;
+	// draw all splats from the line that touches the range of the seg
+	for (; splat; splat = splat->next)
+	{
+		angle1 = R_PointToAngle(splat->v1.x, splat->v1.y);
+		angle2 = R_PointToAngle(splat->v2.x, splat->v2.y);
+		angle1 = (angle1 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT;
+		angle2 = (angle2 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT;
+		// out of the viewangletox lut
+		/// \todo clip it to the screen
+		if (angle1 > FINEANGLES/2 || angle2 > FINEANGLES/2)
+			continue;
+		x1 = viewangletox[angle1];
+		x2 = viewangletox[angle2];
 
-					if (bottom_w > bottom)
-						bottom_w = bottom;
+		if (x1 >= x2)
+			continue; // does not cross a pixel
 
-#ifdef POLYOBJECTS_PLANES
-					// Polyobject-specific hack to fix plane leaking -Red
-					if (ffloor[i].polyobj && top_w >= bottom_w) {
-						ffloor[i].plane->top[rw.x] = 0xFFFF;
-						ffloor[i].plane->bottom[rw.x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
-					} else
-#endif
+		// splat is not in this seg range
+		if (x2 < ds_p->x1 || x1 > ds_p->x2)
+			continue;
 
-					if (top_w <= bottom_w)
-					{
-						ffloor[i].plane->top[rw.x] = (INT16)top_w;
-						ffloor[i].plane->bottom[rw.x] = (INT16)bottom_w;
-					}
-				}
-				else if (ffloor[i].height > viewz)
-				{
-					INT32 top_w = ffloor[i].c_clip[rw.x] + 1;
-					INT32 bottom_w = (ffloor[i].f_frac >> HEIGHTBITS);
+		if (x1 < ds_p->x1)
+			x1 = ds_p->x1;
+		if (x2 > ds_p->x2)
+			x2 = ds_p->x2;
+		if (x2 <= x1)
+			continue;
 
-					if (top_w < top)
-						top_w = top;
+		// calculate incremental stepping values for texture edges
+		rw_scalestep = ds_p->scalestep;
+		spryscale = ds_p->scale1 + (x1 - ds_p->x1)*rw_scalestep;
+		mfloorclip = floorclip;
+		mceilingclip = ceilingclip;
 
-					if (bottom_w > bottom)
-						bottom_w = bottom;
+		patch = W_CachePatchNum(splat->patch, PU_PATCH);
 
-#ifdef POLYOBJECTS_PLANES
-					// Polyobject-specific hack to fix plane leaking -Red
-					if (ffloor[i].polyobj && top_w >= bottom_w) {
-						ffloor[i].plane->top[rw.x] = 0xFFFF;
-						ffloor[i].plane->bottom[rw.x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
-					} else
-#endif
+		dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz;
+		if (splat->yoffset)
+			dc_texturemid += *splat->yoffset;
 
-					if (top_w <= bottom_w)
-					{
-						ffloor[i].plane->top[rw.x] = (INT16)top_w;
-						ffloor[i].plane->bottom[rw.x] = (INT16)bottom_w;
-					}
-				}
-			}
-		}
+		sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
 
-		// Calculate lighting.
-		// Done for light lists anyway to avoid doing it for every light.
-		if (segtextured || dc_numlights)
+		// set drawing mode
+		switch (splat->flags & SPLATDRAWMODE_MASK)
 		{
-			pindex = FixedMul(rw.scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
-			if (pindex >= MAXLIGHTSCALE)
-				pindex = MAXLIGHTSCALE-1;
-		}
-
-		//SoM: Calculate offsets for Thick fake floors.
-		// calculate texture offset
-		angle = (rw.centerangle + xtoviewangle[rw.x])>>ANGLETOFINESHIFT;
-		texturecolumn = rw.offset-FixedMul(FINETANGENT(angle),rw.distance);
+			case SPLATDRAWMODE_OPAQUE:
+				colfunc = colfuncs[BASEDRAWFUNC];
+				break;
+			case SPLATDRAWMODE_TRANS:
+				if (!cv_translucency.value)
+					colfunc = colfuncs[BASEDRAWFUNC];
+				else
+				{
+					dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT);
+					colfunc = colfuncs[COLDRAWFUNC_FUZZY];
+				}
 
-#ifdef ESLOPE
-		if (oldtexturecolumn != -1) {
-			rw.bottomtexturemid += FixedMul(rw.bottomtextureslide,  oldtexturecolumn-texturecolumn);
-			rw.midtexturemid    += FixedMul(rw.midtextureslide,     oldtexturecolumn-texturecolumn);
-			rw.toptexturemid    += FixedMul(rw.toptextureslide,     oldtexturecolumn-texturecolumn);
-			rw.midtextureback   += FixedMul(rw.midtexturebackslide, oldtexturecolumn-texturecolumn);
+				break;
+			case SPLATDRAWMODE_SHADE:
+				colfunc = colfuncs[COLDRAWFUNC_SHADE];
+				break;
 		}
-		oldtexturecolumn = texturecolumn;
-#endif
 
-		texturecolumn >>= FRACBITS;
+		dc_texheight = 0;
 
-		// texturecolumn and lighting are independent of wall tiers
-		if (segtextured)
+		// draw the columns
+		for (dc_x = x1; dc_x <= x2; dc_x++, spryscale += rw_scalestep)
 		{
+			pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
+			if (pindex >= MAXLIGHTSCALE)
+				pindex = MAXLIGHTSCALE - 1;
 			dc_colormap = walllights[pindex];
-			dc_x = rw.x;
-			dc_iscale = 0xffffffffu / (unsigned)rw.scale;
 
 			if (frontsector->extra_colormap)
 				dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
-		}
-
-		if (dc_numlights)
-		{
-			lighttable_t **xwalllights;
-			for (i = 0; i < dc_numlights; i++)
-			{
-				INT32 lightnum;
-				lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT);
 
-				if (dc_lightlist[i].extra_colormap)
-					;
-				else if (curline->v1->y == curline->v2->y)
-					lightnum--;
-				else if (curline->v1->x == curline->v2->x)
-					lightnum++;
+			sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
+			dc_iscale = 0xffffffffu / (unsigned)spryscale;
 
-				if (lightnum < 0)
-					xwalllights = scalelight[0];
-				else if (lightnum >= LIGHTLEVELS)
-					xwalllights = scalelight[LIGHTLEVELS-1];
-				else
-					xwalllights = scalelight[lightnum];
+			// find column of patch, from perspective
+			angle = (rw_centerangle + xtoviewangle[dc_x])>>ANGLETOFINESHIFT;
+				texturecolumn = rw_offset2 - splat->offset
+					- FixedMul(FINETANGENT(angle), rw_distance);
 
-				if (dc_lightlist[i].extra_colormap)
-					dc_lightlist[i].rcolormap = dc_lightlist[i].extra_colormap->colormap + (xwalllights[pindex] - colormaps);
-				else
-					dc_lightlist[i].rcolormap = xwalllights[pindex];
-			}
+			// FIXME!
+			texturecolumn >>= FRACBITS;
+			if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
+				continue;
+
+			// draw the texture
+			col = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
+			R_DrawSplatColumn(col);
 		}
+	} // next splat
 
-		frontscale[rw.x] = rw.scale;
+	colfunc = colfuncs[BASEDRAWFUNC];
+}
 
-		// draw the wall tiers
-		if (midtexture)
-		{
-			// single sided line
-			if (yl <= yh && yh >= 0 && yl < viewheight)
-			{
-				dc_yl = yl;
-				dc_yh = yh;
-				dc_texturemid = rw.midtexturemid;
-				dc_source = R_GetColumn(midtexture,texturecolumn);
-				dc_texheight = textureheight[midtexture]>>FRACBITS;
+#endif //WALLSPLATS
 
-				//profile stuff ---------------------------------------------------------
-#ifdef TIMING
-				ProfZeroTimer();
-#endif
-				colfunc();
-#ifdef TIMING
-				RDMSR(0x10,&mycount);
-				mytotal += mycount;      //64bit add
+// ==========================================================================
+// R_RenderMaskedSegRange
+// ==========================================================================
 
-				if (nombre--==0)
-					I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1),
-						(INT32)mytotal);
-#endif
-				//profile stuff ---------------------------------------------------------
+// If we have a multi-patch texture on a 2sided wall (rare) then we draw
+//  it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this
+//  way we don't have to store extra post_t info with each column for
+//  multi-patch textures. They are not normally needed as multi-patch
+//  textures don't have holes in it. At least not for now.
+static INT32 column2s_length; // column->length : for multi-patch on 2sided wall = texture->height
 
-				// dont draw anything more for this column, since
-				// a midtexture blocks the view
-				ceilingclip[rw.x] = (INT16)viewheight;
-				floorclip[rw.x] = -1;
-			}
-			else
-			{
-				// note: don't use min/max macros, since casting from INT32 to INT16 is involved here
-				if (markceiling)
-					ceilingclip[rw.x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
-				if (markfloor)
-					floorclip[rw.x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
-			}
-		}
-		else
-		{
-			// two sided line
-			if (toptexture)
-			{
-				// top wall
-				mid = pixhigh>>HEIGHTBITS;
-				pixhigh += pixhighstep;
+static void R_Render2sidedMultiPatchColumn(column_t *column)
+{
+	INT32 topscreen, bottomscreen;
 
-				if (mid >= floorclip[rw.x])
-					mid = floorclip[rw.x]-1;
+	topscreen = sprtopscreen; // + spryscale*column->topdelta;  topdelta is 0 for the wall
+	bottomscreen = topscreen + spryscale * column2s_length;
 
-				if (mid >= yl) // back ceiling lower than front ceiling ?
-				{
-					if (yl >= viewheight) // entirely off bottom of screen
-						ceilingclip[rw.x] = (INT16)viewheight;
-					else if (mid >= 0) // safe to draw top texture
-					{
-						dc_yl = yl;
-						dc_yh = mid;
-						dc_texturemid = rw.toptexturemid;
-						dc_source = R_GetColumn(toptexture,texturecolumn);
-						dc_texheight = textureheight[toptexture]>>FRACBITS;
-						colfunc();
-						ceilingclip[rw.x] = (INT16)mid;
-					}
-					else // entirely off top of screen
-						ceilingclip[rw.x] = -1;
-				}
-				else
-					ceilingclip[rw.x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
-			}
-			else if (markceiling) // no top wall
-				ceilingclip[rw.x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
+	dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
+	dc_yh = (bottomscreen-1)>>FRACBITS;
 
-			if (bottomtexture)
-			{
-				// bottom wall
-				mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
-				pixlow += pixlowstep;
+	if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
+	{
+		dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
+		dc_yh = (windowbottom - 1)>>FRACBITS;
+	}
 
-				// no space above wall?
-				if (mid <= ceilingclip[rw.x])
-					mid = ceilingclip[rw.x]+1;
+	if (dc_yh >= mfloorclip[dc_x])
+		dc_yh =  mfloorclip[dc_x] - 1;
+	if (dc_yl <= mceilingclip[dc_x])
+		dc_yl =  mceilingclip[dc_x] + 1;
 
-				if (mid <= yh) // back floor higher than front floor ?
-				{
-					if (yh < 0) // entirely off top of screen
-						floorclip[rw.x] = -1;
-					else if (mid < viewheight) // safe to draw bottom texture
-					{
-						dc_yl = mid;
-						dc_yh = yh;
-						dc_texturemid = rw.bottomtexturemid;
-						dc_source = R_GetColumn(bottomtexture,
-							texturecolumn);
-						dc_texheight = textureheight[bottomtexture]>>FRACBITS;
-						colfunc();
-						floorclip[rw.x] = (INT16)mid;
-					}
-					else  // entirely off bottom of screen
-						floorclip[rw.x] = (INT16)viewheight;
-				}
-				else
-					floorclip[rw.x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
-			}
-			else if (markfloor) // no bottom wall
-				floorclip[rw.x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
-		}
+	if (dc_yl >= vid.height || dc_yh < 0)
+		return;
 
-		if (maskedtexture || numthicksides)
-		{
-			// save texturecol
-			//  for backdrawing of masked mid texture
-			maskedtexturecol[rw.x] = (INT16)texturecolumn;
+	if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
+	{
+		dc_source = (UINT8 *)column + 3;
+
+		if (colfunc == colfuncs[BASEDRAWFUNC])
+			(colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])();
+		else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
+			(colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])();
+		else
+			colfunc();
+	}
+}
+
+// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value
+// uses column2s_length for texture->height as above
+static void R_DrawFlippedMaskedSegColumn(column_t *column)
+{
+	R_DrawFlippedMaskedColumn(column, column2s_length);
+}
 
+void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
+{
+	size_t pindex;
+	column_t *col;
+	INT32 lightnum, texnum, i;
+	fixed_t height, realbot;
+	lightlist_t *light;
+	r_lightlist_t *rlight;
+	void (*colfunc_2s)(column_t *);
+	line_t *ldef;
+	sector_t *front, *back;
+	INT32 times, repeats;
+	INT64 overflow_test;
 #ifdef ESLOPE
-			if (maskedtextureheight != NULL) {
-				maskedtextureheight[rw.x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ?
-											max(rw.midtexturemid, rw.midtextureback) :
-											min(rw.midtexturemid, rw.midtextureback));
-			}
+	INT32 range;
 #endif
-		}
 
-		if (dc_numlights)
-		{
-			for (i = 0; i < dc_numlights; i++)
-			{
-				dc_lightlist[i].height += dc_lightlist[i].heightstep;
-				if (dc_lightlist[i].flags & FF_CUTSOLIDS)
-					dc_lightlist[i].botheight += dc_lightlist[i].botheightstep;
-			}
-		}
+	// Calculate light table.
+	// Use different light tables
+	//   for horizontal / vertical / diagonal. Diagonal?
+	// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
+	curline = ds->curline;
+	frontsector = curline->frontsector;
+	backsector = curline->backsector;
+	texnum = R_GetTextureNum(curline->sidedef->midtexture);
+	windowbottom = windowtop = sprbotscreen = INT32_MAX;
 
-		for (i = 0; i < numffloors; i++)
-			ffloor[i].f_frac += ffloor[i].f_step;
+	// hack translucent linedef types (900-909 for transtables 1-9)
+	ldef = curline->linedef;
+	switch (ldef->special)
+	{
+		case 900:
+		case 901:
+		case 902:
+		case 903:
+		case 904:
+		case 905:
+		case 906:
+		case 907:
+		case 908:
+			dc_transmap = transtables + ((ldef->special-900)<<FF_TRANSSHIFT);
+			colfunc = colfuncs[COLDRAWFUNC_FUZZY];
+			break;
+		case 909:
+			colfunc = colfuncs[COLDRAWFUNC_FOG];
+			windowtop = frontsector->ceilingheight;
+			windowbottom = frontsector->floorheight;
+			break;
+		default:
+			colfunc = colfuncs[BASEDRAWFUNC];
+			break;
+	}
 
-		for (i = 0; i < numbackffloors; i++)
-		{
-			ffloor[i].f_clip[rw.x] = ffloor[i].c_clip[rw.x] = (INT16)((ffloor[i].b_frac >> HEIGHTBITS) & 0xFFFF);
-			ffloor[i].b_frac += ffloor[i].b_step;
-		}
+	if (curline->polyseg && curline->polyseg->translucency > 0)
+	{
+		if (curline->polyseg->translucency >= NUMTRANSMAPS)
+			return;
 
-		rw.scale += rw.scalestep;
-		topfrac += topstep;
-		bottomfrac += bottomstep;
+		dc_transmap = transtables + ((curline->polyseg->translucency-1)<<FF_TRANSSHIFT);
+		colfunc = colfuncs[COLDRAWFUNC_FUZZY];
 	}
-}
 
-// Macro for slope bullshit
-#define SLOPEPARAMS(slope, end1, end2, normalheight) \
-	if (slope) { \
-		end1 = P_GetZAt(slope, segleft.x, segleft.y); \
-		end2 = P_GetZAt(slope, segright.x, segright.y); \
-	} else \
-		end1 = end2 = normalheight;
+#ifdef ESLOPE
+	range = max(ds->x2-ds->x1, 1);
+#endif
+	rw_scalestep = ds->scalestep;
+	spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
 
-//
-// R_CalculateSegDistance
-// Calculate the distance from a seg.
-// Uses precalculated seg length.
-//
-static void R_CalculateSegDistance(seg_t *seg, INT64 x2, INT64 y2, boolean longboi)
-{
-#ifdef SOFTWARE_USE_FLOATS
-	float v1x = FIXED_TO_FLOAT(seg->v1->x);
-	float v1y = FIXED_TO_FLOAT(seg->v1->y);
-	float v2x = FIXED_TO_FLOAT(seg->v2->x);
-	float v2y = FIXED_TO_FLOAT(seg->v2->y);
-	float dx, dy, vdx, vdy;
-	float distance = 0.0f;
-
-	// The seg is vertical.
-	if (!seg->linedef->dy)
-		distance = fabsf(y2 - v1y);
-	// The seg is horizontal.
-	else if (!seg->linedef->dx)
-		distance = fabsf(x2 - v1x);
-	// Uses precalculated seg->flength
-	else if (longboi)
+	// Texture must be cached before setting colfunc_2s,
+	// otherwise texture[texnum]->holes may be false when it shouldn't be
+	R_CheckTextureCache(texnum);
+	// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
+	// are not stored per-column with post info in SRB2
+	if (textures[texnum]->holes)
 	{
-		dx = v2x-v1x;
-		dy = v2y-v1y;
-		vdx = x2-v1x;
-		vdy = y2-v1y;
-		distance = ((dy*vdx)-(dx*vdy))/(seg->flength);
+		if (textures[texnum]->flip & 2) // vertically flipped?
+		{
+			colfunc_2s = R_DrawFlippedMaskedSegColumn;
+			column2s_length = textures[texnum]->height;
+		}
+		else
+			colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
 	}
-	// Linguica's fix converted to floating-point math
 	else
 	{
-		fixed_t x, y;
-		float a, c, ac;
-
-		v1x -= FIXED_TO_FLOAT(viewx);
-		v1y -= FIXED_TO_FLOAT(viewy);
-		v2x -= FIXED_TO_FLOAT(viewx);
-		v2y -= FIXED_TO_FLOAT(viewy);
-		dx = v2x - v1x;
-		dy = v2y - v1y;
-
-		a = (v1x*v2y) - (v1y*v2x);
-		c = (dx*dx) + (dy*dy);
-		ac = (a/c);
-
-		x = FLOAT_TO_FIXED(ac*(-dy));
-		y = FLOAT_TO_FIXED(ac*dx);
-
-		rw.distance = R_PointToDist(viewx + x, viewy + y);
-		return;
+		colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info)
+		column2s_length = textures[texnum]->height;
 	}
 
-	rw.distance = FLOAT_TO_FIXED(distance);
-#else
-	(void)longboi;
-	if (!seg->linedef->dy)
-		rw.distance = (fixed_t)(llabs(y2 - seg->v1->y));
-	else if (!seg->linedef->dx)
-		rw.distance = (fixed_t)(llabs(x2 - seg->v1->x));
-	else
+	// Setup lighting based on the presence/lack-of 3D floors.
+	dc_numlights = 0;
+	if (frontsector->numlights)
 	{
-		INT64 dx = (seg->v2->x)-(seg->v1->x);
-		INT64 dy = (seg->v2->y)-(seg->v1->y);
-		INT64 vdx = x2-(seg->v1->x);
-		INT64 vdy = y2-(seg->v1->y);
-		rw.distance = (fixed_t)(((dy*vdx)-(dx*vdy))/(seg->length));
-	}
+		dc_numlights = frontsector->numlights;
+		if (dc_numlights >= dc_maxlights)
+		{
+			dc_maxlights = dc_numlights;
+			dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL);
+		}
+
+		for (i = 0; i < dc_numlights; i++)
+		{
+#ifdef ESLOPE
+			fixed_t leftheight, rightheight;
 #endif
-}
+			light = &frontsector->lightlist[i];
+			rlight = &dc_lightlist[i];
+#ifdef ESLOPE
+			if (light->slope) {
+				leftheight = P_GetZAt(light->slope, ds->leftpos.x, ds->leftpos.y);
+				rightheight = P_GetZAt(light->slope, ds->rightpos.x, ds->rightpos.y);
+			} else
+				leftheight = rightheight = light->height;
 
-//
-// R_CalculateWallScale
-// Calculate scale at both ends and step.
-//
-static INT32 R_CalculateWallScale(INT32 start, INT32 stop)
-{
-	INT32 range = 1;
+			leftheight -= viewz;
+			rightheight -= viewz;
+
+			rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1);
+			rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2);
+			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
+			//if (x1 > ds->x1)
+				//rlight->height -= (x1 - ds->x1)*rlight->heightstep;
+#else
+			rlight->height = (centeryfrac) - FixedMul((light->height - viewz), spryscale);
+			rlight->heightstep = -FixedMul(rw_scalestep, (light->height - viewz));
+#endif
+			rlight->startheight = rlight->height; // keep starting value here to reset for each repeat
+			rlight->lightlevel = *light->lightlevel;
+			rlight->extra_colormap = *light->extra_colormap;
+			rlight->flags = light->flags;
 
-	ds_p->scale1 = rw.scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]);
+			if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
+				lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
+			else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
+				lightnum = LIGHTLEVELS - 1;
+			else
+				lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
 
-	if (stop > start)
-	{
-		ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]);
-		range = stop-start;
+			if (rlight->extra_colormap && rlight->extra_colormap->fog)
+				;
+			else if (curline->v1->y == curline->v2->y)
+				lightnum--;
+			else if (curline->v1->x == curline->v2->x)
+				lightnum++;
+
+			rlight->lightnum = lightnum;
+		}
 	}
 	else
 	{
-		// UNUSED: try to fix the stretched line bug
-#if 0
-		if (rw.distance < FRACUNIT/2)
+		if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
 		{
-			fixed_t         tr_x,tr_y;
-			fixed_t         gxt,gyt;
-			CONS_Debug(DBG_RENDER, "TRYING TO FIX THE STRETCHED ETC\n");
+			if (frontsector->extra_colormap && frontsector->extra_colormap->fog)
+				lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
+			else
+				lightnum = LIGHTLEVELS - 1;
+		}
+		else
+			lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
 
-			tr_x = curline->v1->x - viewx;
-			tr_y = curline->v1->y - viewy;
+		if (colfunc == colfuncs[COLDRAWFUNC_FOG]
+			|| (frontsector->extra_colormap && frontsector->extra_colormap->fog))
+			;
+		else if (curline->v1->y == curline->v2->y)
+			lightnum--;
+		else if (curline->v1->x == curline->v2->x)
+			lightnum++;
 
-			gxt = FixedMul(tr_x, viewcos);
-			gyt = -FixedMul(tr_y, viewsin);
-			ds_p->scale1 = FixedDiv(projection, gxt - gyt);
-		}
-#endif
-		ds_p->scale2 = ds_p->scale1;
+		if (lightnum < 0)
+			walllights = scalelight[0];
+		else if (lightnum >= LIGHTLEVELS)
+			walllights = scalelight[LIGHTLEVELS - 1];
+		else
+			walllights = scalelight[lightnum];
 	}
 
-	ds_p->scalestep = rw.scalestep = (ds_p->scale2 - rw.scale) / (range);
+	maskedtexturecol = ds->maskedtexturecol;
 
-	return range;
-}
+	mfloorclip = ds->sprbottomclip;
+	mceilingclip = ds->sprtopclip;
 
-//
-// R_WorldTopAndBottom
-// Calculate texture boundaries
-// and decide if floor or ceiling marks are needed.
-//
-static void R_WorldTopAndBottom(INT32 start, INT32 stop)
-{
-#ifdef ESLOPE
-	// Figure out map coordinates of where start and end are mapping to on seg, so we can clip right for slope bullshit
-	if (frontsector->hasslope || (backsector && backsector->hasslope)) // Commenting this out for FOFslop. -Red
-	{
-		angle_t temp;
+	if (frontsector->heightsec != -1)
+		front = &sectors[frontsector->heightsec];
+	else
+		front = frontsector;
 
-		// left
-		temp = xtoviewangle[start]+viewangle;
+	if (backsector->heightsec != -1)
+		back = &sectors[backsector->heightsec];
+	else
+		back = backsector;
 
-		{
-			// Both lines can be written in slope-intercept form, so figure out line intersection
-			float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector...
-			///TODO: convert to FPU
+	if (ds->curline->sidedef->repeatcnt)
+		repeats = 1 + ds->curline->sidedef->repeatcnt;
+	else if (ldef->flags & ML_EFFECT5)
+	{
+		fixed_t high, low;
 
-			a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y);
-			b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x);
-			c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y);
+		if (front->ceilingheight > back->ceilingheight)
+			high = back->ceilingheight;
+		else
+			high = front->ceilingheight;
 
-			a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT));
-			b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT));
-			c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy);
+		if (front->floorheight > back->floorheight)
+			low = front->floorheight;
+		else
+			low = back->floorheight;
 
-			det = a1*b2 - a2*b1;
+		repeats = (high - low)/textureheight[texnum];
+		if ((high-low)%textureheight[texnum])
+			repeats++; // tile an extra time to fill the gap -- Monster Iestyn
+	}
+	else
+		repeats = 1;
 
-			ds_p->leftpos.x = segleft.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det);
-			ds_p->leftpos.y = segleft.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det);
+	for (times = 0; times < repeats; times++)
+	{
+		if (times > 0)
+		{
+			rw_scalestep = ds->scalestep;
+			spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
+			if (dc_numlights)
+			{ // reset all lights to their starting heights
+				for (i = 0; i < dc_numlights; i++)
+				{
+					rlight = &dc_lightlist[i];
+					rlight->height = rlight->startheight;
+				}
+			}
 		}
 
-		// right
-		temp = xtoviewangle[stop]+viewangle;
-
+#ifndef ESLOPE
+		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
 		{
-			// Both lines can be written in slope-intercept form, so figure out line intersection
-			float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector...
-			///TODO: convert to FPU
-
-			a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y);
-			b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x);
-			c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y);
-
-			a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT));
-			b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT));
-			c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy);
-
-			det = a1*b2 - a2*b1;
-
-			ds_p->rightpos.x = segright.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det);
-			ds_p->rightpos.y = segright.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det);
+			dc_texturemid = front->floorheight > back->floorheight
+				? front->floorheight : back->floorheight;
+			dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
 		}
-	}
+		else
+		{
+			dc_texturemid = front->ceilingheight < back->ceilingheight
+				? front->ceilingheight : back->ceilingheight;
+			dc_texturemid = dc_texturemid - viewz;
+		}
+		dc_texturemid += curline->sidedef->rowoffset;
 
-	SLOPEPARAMS(frontsector->c_slope, worldtop,    worldtopslope,    frontsector->ceilingheight)
-	SLOPEPARAMS(frontsector->f_slope, worldbottom, worldbottomslope, frontsector->floorheight)
-	// subtract viewz from these to turn them into
-	// positions relative to the camera's z position
-	worldtop -= viewz;
-	worldtopslope -= viewz;
-	worldbottom -= viewz;
-	worldbottomslope -= viewz;
-#else
-	worldtop = frontsector->ceilingheight - viewz;
-	worldbottom = frontsector->floorheight - viewz;
+		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
+			dc_texturemid += (textureheight[texnum])*times;
+		else
+			dc_texturemid -= (textureheight[texnum])*times;
 #endif
-}
 
-//
-// R_SegTextured
-// Calculate rw.offset.
-// Only needed for textured lines.
-//
-static void R_SegTextured(fixed_t hyp, boolean longboi)
-{
-	INT32 lightnum;
-	fixed_t sineval;
-	angle_t offsetangle = rw.normalangle-rw.angle1;
+		dc_texheight = textureheight[texnum]>>FRACBITS;
 
-	if (offsetangle > ANGLE_180)
-		offsetangle = -(signed)offsetangle;
-	if (offsetangle > ANGLE_90)
-		offsetangle = ANGLE_90;
+		// draw the columns
+		for (dc_x = x1; dc_x <= x2; dc_x++)
+		{
+#ifdef ESLOPE
+			dc_texturemid = ds->maskedtextureheight[dc_x];
 
-	sineval = FINESINE(offsetangle>>ANGLETOFINESHIFT);
-	rw.offset = FixedMul(hyp, sineval);
+			if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3))
+				dc_texturemid += (textureheight[texnum])*times + textureheight[texnum];
+			else
+				dc_texturemid -= (textureheight[texnum])*times;
+#endif
+			// calculate lighting
+			if (maskedtexturecol[dc_x] != INT16_MAX)
+			{
+				// Check for overflows first
+				overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS);
+				if (overflow_test < 0) overflow_test = -overflow_test;
+				if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL)
+				{
+					// Eh, no, go away, don't waste our time
+					if (dc_numlights)
+					{
+						for (i = 0; i < dc_numlights; i++)
+						{
+							rlight = &dc_lightlist[i];
+							rlight->height += rlight->heightstep;
+						}
+					}
+					spryscale += rw_scalestep;
+					continue;
+				}
 
-	// big room fix
-	if (longboi)
-	{
-		INT64 dx = (curline->v2->x)-(curline->v1->x);
-		INT64 dy = (curline->v2->y)-(curline->v1->y);
-		INT64 vdx = viewx-(curline->v1->x);
-		INT64 vdy = viewy-(curline->v1->y);
-		rw.offset = ((dx*vdx-dy*vdy))/(curline->length);
-	}
+				if (dc_numlights)
+				{
+					lighttable_t **xwalllights;
 
-	if (rw.normalangle-rw.angle1 < ANGLE_180)
-		rw.offset = -rw.offset;
+					sprbotscreen = INT32_MAX;
+					sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale));
 
-	/// don't use texture offset for splats
-	rw.offset2 = rw.offset + curline->offset;
-	rw.offset += sidedef->textureoffset + curline->offset;
-	rw.centerangle = ANGLE_90 + viewangle - rw.normalangle;
+					realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen;
+					dc_iscale = 0xffffffffu / (unsigned)spryscale;
 
-	// calculate light table
-	//  use different light tables
-	//  for horizontal / vertical / diagonal
-	// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
-	lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
+					// draw the texture
+					col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
 
-	if (curline->v1->y == curline->v2->y)
-		lightnum--;
-	else if (curline->v1->x == curline->v2->x)
-		lightnum++;
+					for (i = 0; i < dc_numlights; i++)
+					{
+						rlight = &dc_lightlist[i];
 
-	if (lightnum < 0)
-		walllights = scalelight[0];
-	else if (lightnum >= LIGHTLEVELS)
-		walllights = scalelight[LIGHTLEVELS - 1];
-	else
-		walllights = scalelight[lightnum];
-}
+						if ((rlight->flags & FF_NOSHADE))
+							continue;
 
-//
-// R_CheckMaskedTextures
-// Midtexture stuff, presumably.
-//
-static void R_CheckMaskedTextures(void)
-{
-	INT32 i = 0;
-	// allocate space for masked texture tables
-	if (frontsector && backsector && frontsector->tag != backsector->tag && (backsector->ffloors || frontsector->ffloors))
-	{
-		ffloor_t *rover;
-		ffloor_t *r2;
-		fixed_t   lowcut, highcut;
-#ifdef ESLOPE
-		fixed_t lowcutslope, highcutslope;
+						if (rlight->lightnum < 0)
+							xwalllights = scalelight[0];
+						else if (rlight->lightnum >= LIGHTLEVELS)
+							xwalllights = scalelight[LIGHTLEVELS-1];
+						else
+							xwalllights = scalelight[rlight->lightnum];
 
-		// Used for height comparisons and etc across FOFs and slopes
-		fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2;
-#endif
+						pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
 
-		//markceiling = markfloor = true;
-		maskedtexture = true;
+						if (pindex >= MAXLIGHTSCALE)
+							pindex = MAXLIGHTSCALE - 1;
 
-		ds_p->thicksidecol = maskedtexturecol = lastopening - rw.x;
-		lastopening += rw.stopx - rw.x;
+						if (rlight->extra_colormap)
+							rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
+						else
+							rlight->rcolormap = xwalllights[pindex];
 
-		lowcut = max(worldbottom, worldlow) + viewz;
-		highcut = min(worldtop, worldhigh) + viewz;
-#ifdef ESLOPE
-		lowcutslope = max(worldbottomslope, worldlowslope) + viewz;
-		highcutslope = min(worldtopslope, worldhighslope) + viewz;
-#endif
-
-		if (frontsector->ffloors && backsector->ffloors)
-		{
-			i = 0;
-			for (rover = backsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next)
-			{
-				if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS))
-					continue;
-				if (rover->flags & FF_INVERTSIDES)
-					continue;
-
-				if (rover->norender == leveltime)
-					continue;
-
-#ifdef ESLOPE
-				SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight)
-				SLOPEPARAMS(*rover->b_slope, low1,  lowslope1,  *rover->bottomheight)
-
-				if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
-					continue;
-#else
-				if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
-					continue;
-#endif
-
-				for (r2 = frontsector->ffloors; r2; r2 = r2->next)
-				{
-					if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
-						continue;
-
-					if (r2->norender == leveltime)
-						continue;
+						height = rlight->height;
+						rlight->height += rlight->heightstep;
 
-					if (rover->flags & FF_EXTRA)
-					{
-						if (!(r2->flags & FF_CUTEXTRA))
+						if (height <= windowtop)
+						{
+							dc_colormap = rlight->rcolormap;
 							continue;
+						}
+
+						windowbottom = height;
+						if (windowbottom >= realbot)
+						{
+							windowbottom = realbot;
+							colfunc_2s(col);
+							for (i++; i < dc_numlights; i++)
+							{
+								rlight = &dc_lightlist[i];
+								rlight->height += rlight->heightstep;
+							}
 
-						if (r2->flags & FF_EXTRA && (r2->flags & (FF_TRANSLUCENT|FF_FOG)) != (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
-							continue;
-					}
-					else
-					{
-						if (!(r2->flags & FF_CUTSOLIDS))
 							continue;
+						}
+						colfunc_2s(col);
+						windowtop = windowbottom + 1;
+						dc_colormap = rlight->rcolormap;
 					}
+					windowbottom = realbot;
+					if (windowtop < windowbottom)
+						colfunc_2s(col);
 
-#ifdef ESLOPE
-					SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight)
-					SLOPEPARAMS(*r2->b_slope, low2,  lowslope2,  *r2->bottomheight)
-
-					if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope))
-						continue;
-					if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2))
-						continue;
-#else
-					if (*r2->topheight < lowcut || *r2->bottomheight > highcut)
-						continue;
-					if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
-						continue;
-#endif
-
-					break;
-				}
-				if (r2)
+					spryscale += rw_scalestep;
 					continue;
+				}
 
-				ds_p->thicksides[i] = rover;
-				i++;
-			}
+				// calculate lighting
+				pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
 
-			for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next)
-			{
-				if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS))
-					continue;
-				if (!(rover->flags & FF_ALLSIDES))
-					continue;
+				if (pindex >= MAXLIGHTSCALE)
+					pindex = MAXLIGHTSCALE - 1;
 
-				if (rover->norender == leveltime)
-					continue;
+				dc_colormap = walllights[pindex];
 
-#ifdef ESLOPE
-				SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight)
-				SLOPEPARAMS(*rover->b_slope, low1,  lowslope1,  *rover->bottomheight)
+				if (frontsector->extra_colormap)
+					dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
 
-				if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
-					continue;
-#else
-				if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
-					continue;
-#endif
+				sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
+				dc_iscale = 0xffffffffu / (unsigned)spryscale;
 
-				for (r2 = backsector->ffloors; r2; r2 = r2->next)
+				// draw the texture
+				col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
+
+//#ifdef POLYOBJECTS_PLANES
+#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red
+				if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES))
 				{
-					if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
-						continue;
+					fixed_t my_topscreen;
+					fixed_t my_bottomscreen;
+					fixed_t my_yl, my_yh;
 
-					if (r2->norender == leveltime)
-						continue;
+					my_topscreen = sprtopscreen + spryscale*col->topdelta;
+					my_bottomscreen = sprbotscreen == INT32_MAX ? my_topscreen + spryscale*col->length
+					                                         : sprbotscreen + spryscale*col->length;
 
-					if (rover->flags & FF_EXTRA)
-					{
-						if (!(r2->flags & FF_CUTEXTRA))
-							continue;
+					my_yl = (my_topscreen+FRACUNIT-1)>>FRACBITS;
+					my_yh = (my_bottomscreen-1)>>FRACBITS;
+	//				CONS_Debug(DBG_RENDER, "my_topscreen: %d\nmy_bottomscreen: %d\nmy_yl: %d\nmy_yh: %d\n", my_topscreen, my_bottomscreen, my_yl, my_yh);
 
-						if (r2->flags & FF_EXTRA && (r2->flags & (FF_TRANSLUCENT|FF_FOG)) != (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
-							continue;
-					}
-					else
+					if (numffloors)
 					{
-						if (!(r2->flags & FF_CUTSOLIDS))
-							continue;
-					}
+						INT32 top = my_yl;
+						INT32 bottom = my_yh;
 
-#ifdef ESLOPE
-					SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight)
-					SLOPEPARAMS(*r2->b_slope, low2,  lowslope2,  *r2->bottomheight)
-					if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope))
-						continue;
-					if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2))
-						continue;
-#else
-					if (*r2->topheight < lowcut || *r2->bottomheight > highcut)
-						continue;
-					if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
-						continue;
-#endif
+						for (i = 0; i < numffloors; i++)
+						{
+							if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)
+								continue;
 
-					break;
-				}
-				if (r2)
-					continue;
+							if (ffloor[i].height < viewz)
+							{
+								INT32 top_w = ffloor[i].plane->top[dc_x];
+
+	//							CONS_Debug(DBG_RENDER, "Leveltime : %d\n", leveltime);
+	//							CONS_Debug(DBG_RENDER, "Top is %d, top_w is %d\n", top, top_w);
+								if (top_w < top)
+								{
+									ffloor[i].plane->top[dc_x] = (INT16)top;
+									ffloor[i].plane->picnum = 0;
+								}
+	//							CONS_Debug(DBG_RENDER, "top_w is now %d\n", ffloor[i].plane->top[dc_x]);
+							}
+							else if (ffloor[i].height > viewz)
+							{
+								INT32 bottom_w = ffloor[i].plane->bottom[dc_x];
 
-				ds_p->thicksides[i] = rover;
-				i++;
+								if (bottom_w > bottom)
+								{
+									ffloor[i].plane->bottom[dc_x] = (INT16)bottom;
+									ffloor[i].plane->picnum = 0;
+								}
+							}
+						}
+					}
+				}
+				else
+#endif
+					colfunc_2s(col);
 			}
+			spryscale += rw_scalestep;
 		}
-		else if (backsector->ffloors)
-		{
-			for (rover = backsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next)
-			{
-				if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || rover->flags & FF_INVERTSIDES)
-					continue;
-				if (rover->norender == leveltime)
-					continue;
+	}
+	colfunc = colfuncs[BASEDRAWFUNC];
+}
+
+// Loop through R_DrawMaskedColumn calls
+static void R_DrawRepeatMaskedColumn(column_t *col)
+{
+	while (sprtopscreen < sprbotscreen) {
+		R_DrawMaskedColumn(col);
+		if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
+			sprtopscreen = INT32_MAX;
+		else
+			sprtopscreen += dc_texheight*spryscale;
+	}
+}
+
+static void R_DrawRepeatFlippedMaskedColumn(column_t *col)
+{
+	do {
+		R_DrawFlippedMaskedColumn(col, column2s_length);
+		sprtopscreen += dc_texheight*spryscale;
+	} while (sprtopscreen < sprbotscreen);
+}
 
+//
+// R_RenderThickSideRange
+// Renders all the thick sides in the given range.
+void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
+{
+	size_t          pindex;
+	column_t *      col;
+	INT32             lightnum;
+	INT32            texnum;
+	sector_t        tempsec;
+	INT32             templight;
+	INT32             i, p;
+	fixed_t         bottombounds = viewheight << FRACBITS;
+	fixed_t         topbounds = (con_clipviewtop - 1) << FRACBITS;
+	fixed_t         offsetvalue = 0;
+	lightlist_t     *light;
+	r_lightlist_t   *rlight;
 #ifdef ESLOPE
-				// Oy vey.
-				if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz
-						&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz)
-						||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz
-						&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz))
-					continue;
-#else
-				if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight)
-					continue;
+	INT32           range;
 #endif
-
-				ds_p->thicksides[i] = rover;
-				i++;
-			}
-		}
-		else if (frontsector->ffloors)
-		{
-			for (rover = frontsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next)
-			{
-				if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_ALLSIDES))
-					continue;
-				if (rover->norender == leveltime)
-					continue;
+#ifndef ESLOPE
+	fixed_t         lheight;
+#endif
+	line_t          *newline = NULL;
 #ifdef ESLOPE
-				// Oy vey.
-				if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz
-						&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz)
-						||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz
-						&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz))
-					continue;
-
-				if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldlow+viewz
-						&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldlowslope+viewz)
-						||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldhigh+viewz
-						&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldhighslope+viewz))
-					continue;
-#else
-				if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight)
-					continue;
-				if (*rover->topheight <= backsector->floorheight || *rover->bottomheight >= backsector->ceilingheight)
-					continue;
+	// Render FOF sides kinda like normal sides, with the frac and step and everything
+	// NOTE: INT64 instead of fixed_t because overflow concerns
+	INT64         top_frac, top_step, bottom_frac, bottom_step;
+	// skew FOF walls with slopes?
+	boolean	      slopeskew = false;
+	fixed_t       ffloortextureslide = 0;
+	INT32         oldx = -1;
+	fixed_t       left_top, left_bottom; // needed here for slope skewing
+	pslope_t      *skewslope = NULL;
 #endif
 
-				ds_p->thicksides[i] = rover;
-				i++;
-			}
-		}
+	void (*colfunc_2s) (column_t *);
 
-		ds_p->numthicksides = numthicksides = i;
-	}
+	// Calculate light table.
+	// Use different light tables
+	//   for horizontal / vertical / diagonal. Diagonal?
+	// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
 
-	if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures)
-	{
-		// masked midtexture
-		if (!ds_p->thicksidecol)
-		{
-			ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw.x;
-			lastopening += rw.stopx - rw.x;
-		}
-		else
-			ds_p->maskedtexturecol = ds_p->thicksidecol;
+	curline = ds->curline;
+	backsector = pfloor->target;
+	frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
+	texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture);
 
-#ifdef ESLOPE
-		maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0])
+	colfunc = colfuncs[BASEDRAWFUNC];
 
-#ifdef POLYOBJECTS
-		if (curline->polyseg) { // use REAL front and back floors please, so midtexture rendering isn't mucked up
-			rw.midtextureslide = rw.midtexturebackslide = 0;
-			if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3))
-				rw.midtexturemid = rw.midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz;
-			else
-				rw.midtexturemid = rw.midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz;
-		} else
-#endif
-		// Set midtexture starting height
-		if (linedef->flags & ML_EFFECT2) { // Ignore slopes when texturing
-			rw.midtextureslide = rw.midtexturebackslide = 0;
-			if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3))
-				rw.midtexturemid = rw.midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz;
-			else
-				rw.midtexturemid = rw.midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz;
+	if (pfloor->master->flags & ML_TFERLINE)
+	{
+		size_t linenum = curline->linedef-backsector->lines[0];
+		newline = pfloor->master->frontsector->lines[0] + linenum;
+		texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
+	}
 
-		} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
-			rw.midtexturemid = worldbottom;
-			rw.midtextureslide = floorfrontslide;
-			rw.midtextureback = worldlow;
-			rw.midtexturebackslide = floorbackslide;
-		} else {
-			rw.midtexturemid = worldtop;
-			rw.midtextureslide = ceilingfrontslide;
-			rw.midtextureback = worldhigh;
-			rw.midtexturebackslide = ceilingbackslide;
-		}
-		rw.midtexturemid += sidedef->rowoffset;
-		rw.midtextureback += sidedef->rowoffset;
-#endif
+	if (pfloor->flags & FF_TRANSLUCENT)
+	{
+		boolean fuzzy = true;
+
+		// Hacked up support for alpha value in software mode Tails 09-24-2002
+		if (pfloor->alpha < 12)
+			return; // Don't even draw it
+		else if (pfloor->alpha < 38)
+			dc_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT);
+		else if (pfloor->alpha < 64)
+			dc_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT);
+		else if (pfloor->alpha < 89)
+			dc_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT);
+		else if (pfloor->alpha < 115)
+			dc_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT);
+		else if (pfloor->alpha < 140)
+			dc_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
+		else if (pfloor->alpha < 166)
+			dc_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT);
+		else if (pfloor->alpha < 192)
+			dc_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT);
+		else if (pfloor->alpha < 217)
+			dc_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT);
+		else if (pfloor->alpha < 243)
+			dc_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT);
+		else
+			fuzzy = false; // Opaque
 
-		maskedtexture = true;
+		if (fuzzy)
+			colfunc = colfuncs[COLDRAWFUNC_FUZZY];
 	}
-}
+	else if (pfloor->flags & FF_FOG)
+		colfunc = colfuncs[COLDRAWFUNC_FOG];
 
-//
-// R_CheckWallTextures
-// Self-explanatory, I hope?!
-//
-static void R_CheckWallTextures(void)
-{
-	if (!backsector)
-	{
-		fixed_t texheight;
-		// single sided line
-		midtexture = R_GetTextureNum(sidedef->midtexture);
-		texheight = textureheight[midtexture];
-		// a single sided line is terminal, so it must mark ends
-		markfloor = markceiling = true;
 #ifdef ESLOPE
-		if (linedef->flags & ML_EFFECT2) {
-			if (linedef->flags & ML_DONTPEGBOTTOM)
-				rw.midtexturemid = frontsector->floorheight + texheight - viewz;
-			else
-				rw.midtexturemid = frontsector->ceilingheight - viewz;
-		}
-		else
+	range = max(ds->x2-ds->x1, 1);
 #endif
-		if (linedef->flags & ML_DONTPEGBOTTOM)
+	//SoM: Moved these up here so they are available for my lightlist calculations
+	rw_scalestep = ds->scalestep;
+	spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
+
+	dc_numlights = 0;
+	if (frontsector->numlights)
+	{
+		dc_numlights = frontsector->numlights;
+		if (dc_numlights > dc_maxlights)
 		{
-#ifdef ESLOPE
-			rw.midtexturemid = worldbottom + texheight;
-			rw.midtextureslide = floorfrontslide;
-#else
-			vtop = frontsector->floorheight + texheight;
-			// bottom of texture at bottom
-			rw.midtexturemid = vtop - viewz;
-#endif
+			dc_maxlights = dc_numlights;
+			dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL);
 		}
-		else
+
+		for (i = p = 0; i < dc_numlights; i++)
 		{
-			// top of texture at top
-			rw.midtexturemid = worldtop;
 #ifdef ESLOPE
-			rw.midtextureslide = ceilingfrontslide;
+			fixed_t leftheight, rightheight;
+			fixed_t pfloorleft, pfloorright;
+			INT64 overflow_test;
 #endif
-		}
-		rw.midtexturemid += sidedef->rowoffset;
-	}
-	else
-	{
-		// check TOP TEXTURE
-		if (!bothceilingssky // never draw the top texture if on
-			&& (worldhigh < worldtop
+			light = &frontsector->lightlist[i];
+			rlight = &dc_lightlist[p];
 #ifdef ESLOPE
-				|| worldhighslope < worldtopslope
-#endif
-			))
-		{
-			fixed_t texheight;
-			// top texture
-			if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM))
-				&& linedef->sidenum[1] != 0xffff)
-			{
-				// Special case... use offsets from 2nd side but only if it has a texture.
-				side_t *def = &sides[linedef->sidenum[1]];
-				toptexture = R_GetTextureNum(def->toptexture);
 
-				if (!toptexture) //Second side has no texture, use the first side's instead.
-					toptexture = R_GetTextureNum(sidedef->toptexture);
-				texheight = textureheight[toptexture];
-			}
-			else
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+	if (slope) { \
+		end1 = P_GetZAt(slope, ds->leftpos.x, ds->leftpos.y); \
+		end2 = P_GetZAt(slope, ds->rightpos.x, ds->rightpos.y); \
+	} else \
+		end1 = end2 = normalheight;
+
+			SLOPEPARAMS(light->slope,     leftheight, rightheight, light->height)
+			SLOPEPARAMS(*pfloor->b_slope, pfloorleft, pfloorright, *pfloor->bottomheight)
+
+			if (leftheight < pfloorleft && rightheight < pfloorright)
+				continue;
+
+			SLOPEPARAMS(*pfloor->t_slope, pfloorleft, pfloorright, *pfloor->topheight)
+
+			if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights)
 			{
-				toptexture = R_GetTextureNum(sidedef->toptexture);
-				texheight = textureheight[toptexture];
+				lightlist_t *nextlight = &frontsector->lightlist[i+1];
+				if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft
+				 && (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright)
+					continue;
 			}
-#ifdef ESLOPE
-			if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
-				if (linedef->flags & ML_DONTPEGTOP)
-					rw.toptexturemid = frontsector->ceilingheight - viewz;
-				else
-					rw.toptexturemid = backsector->ceilingheight - viewz;
-			} else
-#endif
-			if (linedef->flags & ML_DONTPEGTOP)
-			{
-				// top of texture at top
-				rw.toptexturemid = worldtop;
-#ifdef ESLOPE
-				rw.toptextureslide = ceilingfrontslide;
+
+			leftheight -= viewz;
+			rightheight -= viewz;
+
+#define CLAMPMAX INT32_MAX
+#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out.
+			// Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave.
+			overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS);
+			if      (overflow_test > (INT64)CLAMPMAX) rlight->height = CLAMPMAX;
+			else if (overflow_test > (INT64)CLAMPMIN) rlight->height = (fixed_t)overflow_test;
+			else                                      rlight->height = CLAMPMIN;
+
+			overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS);
+			if      (overflow_test > (INT64)CLAMPMAX) rlight->heightstep = CLAMPMAX;
+			else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test;
+			else                                      rlight->heightstep = CLAMPMIN;
+			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
+#else
+			if (light->height < *pfloor->bottomheight)
+				continue;
+
+			if (light->height > *pfloor->topheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > *pfloor->topheight)
+				continue;
+
+			lheight = light->height;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : light->height;
+			rlight->heightstep = -FixedMul (rw_scalestep, (lheight - viewz));
+			rlight->height = (centeryfrac) - FixedMul((lheight - viewz), spryscale);
 #endif
-			}
-			else
+			rlight->flags = light->flags;
+			if (light->flags & FF_CUTLEVEL)
 			{
 #ifdef ESLOPE
-				rw.toptexturemid = worldhigh + texheight;
-				rw.toptextureslide = ceilingbackslide;
+				SLOPEPARAMS(*light->caster->b_slope, leftheight, rightheight, *light->caster->bottomheight)
+#undef SLOPEPARAMS
+				leftheight -= viewz;
+				rightheight -= viewz;
+
+				// Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave.
+				overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS);
+				if      (overflow_test > (INT64)CLAMPMAX) rlight->botheight = CLAMPMAX;
+				else if (overflow_test > (INT64)CLAMPMIN) rlight->botheight = (fixed_t)overflow_test;
+				else                                      rlight->botheight = CLAMPMIN;
+
+				overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS);
+				if      (overflow_test > (INT64)CLAMPMAX) rlight->botheightstep = CLAMPMAX;
+				else if (overflow_test > (INT64)CLAMPMIN) rlight->botheightstep = (fixed_t)overflow_test;
+				else                                      rlight->botheightstep = CLAMPMIN;
+				rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range);
 #else
-				vtop = backsector->ceilingheight + texheight;
-				// bottom of texture
-				rw.toptexturemid = vtop - viewz;
+				lheight = *light->caster->bottomheight;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : *light->caster->bottomheight;
+				rlight->botheightstep = -FixedMul (rw_scalestep, (lheight - viewz));
+				rlight->botheight = (centeryfrac) - FixedMul((lheight - viewz), spryscale);
 #endif
 			}
+
+			rlight->lightlevel = *light->lightlevel;
+			rlight->extra_colormap = *light->extra_colormap;
+
+			// Check if the current light effects the colormap/lightlevel
+			if (pfloor->flags & FF_FOG)
+				rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
+			else
+				rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
+
+			if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
+				;
+			else if (curline->v1->y == curline->v2->y)
+				rlight->lightnum--;
+			else if (curline->v1->x == curline->v2->x)
+				rlight->lightnum++;
+
+			p++;
 		}
-		// check BOTTOM TEXTURE
-		if (!bothfloorssky // never draw the bottom texture if on
-			&& (worldlow > worldbottom
-#ifdef ESLOPE
-				|| worldlowslope > worldbottomslope
-#endif
-			))     //seulement si VISIBLE!!!
-		{
-			// bottom texture
-			bottomtexture = R_GetTextureNum(sidedef->bottomtexture);
+
+		dc_numlights = p;
+	}
+	else
+	{
+		// Get correct light level!
+		if ((frontsector->extra_colormap && frontsector->extra_colormap->fog))
+			lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
+		else if (pfloor->flags & FF_FOG)
+			lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
+		else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
+			lightnum = LIGHTLEVELS-1;
+		else
+			lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)
+				->lightlevel >> LIGHTSEGSHIFT;
+
+		if (pfloor->flags & FF_FOG || (frontsector->extra_colormap && frontsector->extra_colormap->fog));
+			else if (curline->v1->y == curline->v2->y)
+		lightnum--;
+		else if (curline->v1->x == curline->v2->x)
+			lightnum++;
+
+		if (lightnum < 0)
+			walllights = scalelight[0];
+		else if (lightnum >= LIGHTLEVELS)
+			walllights = scalelight[LIGHTLEVELS-1];
+		else
+			walllights = scalelight[lightnum];
+	}
+
+	maskedtexturecol = ds->thicksidecol;
+
+	mfloorclip = ds->sprbottomclip;
+	mceilingclip = ds->sprtopclip;
+	dc_texheight = textureheight[texnum]>>FRACBITS;
 
 #ifdef ESLOPE
-			if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
-				if (linedef->flags & ML_DONTPEGBOTTOM)
-					rw.bottomtexturemid = frontsector->floorheight - viewz;
-				else
-					rw.bottomtexturemid = backsector->floorheight - viewz;
-			} else
+	// calculate both left ends
+	if (*pfloor->t_slope)
+		left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
+	else
+		left_top = *pfloor->topheight - viewz;
+
+	if (*pfloor->b_slope)
+		left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
+	else
+		left_bottom = *pfloor->bottomheight - viewz;
+	skewslope = *pfloor->t_slope; // skew using top slope by default
+	if (newline)
+	{
+		if (newline->flags & ML_DONTPEGTOP)
+			slopeskew = true;
+	}
+	else if (pfloor->master->flags & ML_DONTPEGTOP)
+		slopeskew = true;
+
+	if (slopeskew)
+		dc_texturemid = left_top;
+	else
 #endif
-			if (linedef->flags & ML_DONTPEGBOTTOM)
-			{
-				// bottom of texture at bottom
-				// top of texture at top
-				rw.bottomtexturemid = worldbottom;
+	dc_texturemid = *pfloor->topheight - viewz;
+
+	if (newline)
+	{
+		offsetvalue = sides[newline->sidenum[0]].rowoffset;
+		if (newline->flags & ML_DONTPEGBOTTOM)
+		{
 #ifdef ESLOPE
-				rw.bottomtextureslide = floorfrontslide;
+			skewslope = *pfloor->b_slope; // skew using bottom slope
+			if (slopeskew)
+				dc_texturemid = left_bottom;
+			else
 #endif
-			}
-			else {   // top of texture at top
-				rw.bottomtexturemid = worldlow;
+			offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
+		}
+	}
+	else
+	{
+		offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset;
+		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
+		{
 #ifdef ESLOPE
-				rw.bottomtextureslide = floorbackslide;
+			skewslope = *pfloor->b_slope; // skew using bottom slope
+			if (slopeskew)
+				dc_texturemid = left_bottom;
+			else
 #endif
-			}
+			offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
 		}
+	}
+
+#ifdef ESLOPE
+	if (slopeskew)
+	{
+		angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y);
 
-		rw.toptexturemid += sidedef->rowoffset;
-		rw.bottomtexturemid += sidedef->rowoffset;
+		if (skewslope)
+			ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT));
 	}
-}
+#endif
 
-//
-// R_StoreWallSilhouette
-// Sets the silhouette for the current seg.
-// Also checks if any floors or ceilings have to be marked.
-//
-static void R_StoreWallSilhouette(void)
-{
-	if (!backsector)
+	dc_texturemid += offsetvalue;
+
+	// Texture must be cached before setting colfunc_2s,
+	// otherwise texture[texnum]->holes may be false when it shouldn't be
+	R_CheckTextureCache(texnum);
+	//faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
+	//     are not stored per-column with post info anymore in Doom Legacy
+	if (textures[texnum]->holes)
 	{
-		ds_p->silhouette = SIL_BOTH;
-		ds_p->sprtopclip = screenheightarray;
-		ds_p->sprbottomclip = negonearray;
-		ds_p->bsilheight = INT32_MAX;
-		ds_p->tsilheight = INT32_MIN;
+		if (textures[texnum]->flip & 2) // vertically flipped?
+		{
+			colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
+			column2s_length = textures[texnum]->height;
+		}
+		else
+			colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture
 	}
 	else
 	{
-		// two sided line
-		bothceilingssky = false; // turned on if both back and front ceilings are sky
-		bothfloorssky = false; // likewise, but for floors
+		colfunc_2s = R_Render2sidedMultiPatchColumn;        //render multipatch with no holes (no post_t info)
+		column2s_length = textures[texnum]->height;
+	}
 
 #ifdef ESLOPE
-		SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight)
-		SLOPEPARAMS(backsector->f_slope, worldlow,  worldlowslope,  backsector->floorheight)
-		worldhigh -= viewz;
-		worldhighslope -= viewz;
-		worldlow -= viewz;
-		worldlowslope -= viewz;
-#else
-		worldhigh = backsector->ceilingheight - viewz;
-		worldlow = backsector->floorheight - viewz;
-#endif
+	// Set heights according to plane, or slope, whichever
+	{
+		fixed_t right_top, right_bottom;
 
-		// hack to allow height changes in outdoor areas
-		// This is what gets rid of the upper textures if there should be sky
-		if (frontsector->ceilingpic == skyflatnum
-			&& backsector->ceilingpic == skyflatnum)
-		{
-			bothceilingssky = true;
-		}
+		// calculate right ends now
+		if (*pfloor->t_slope)
+			right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
+		else
+			right_top = *pfloor->topheight - viewz;
 
-		// likewise, but for floors and upper textures
-		if (frontsector->floorpic == skyflatnum
-			&& backsector->floorpic == skyflatnum)
-		{
-			bothfloorssky = true;
-		}
+		if (*pfloor->b_slope)
+			right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
+		else
+			right_bottom = *pfloor->bottomheight - viewz;
 
-		ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
-		ds_p->silhouette = 0;
+		// using INT64 to avoid 32bit overflow
+		top_frac =    (INT64)centeryfrac - (((INT64)left_top     * ds->scale1) >> FRACBITS);
+		bottom_frac = (INT64)centeryfrac - (((INT64)left_bottom  * ds->scale1) >> FRACBITS);
+		top_step =    (INT64)centeryfrac - (((INT64)right_top    * ds->scale2) >> FRACBITS);
+		bottom_step = (INT64)centeryfrac - (((INT64)right_bottom * ds->scale2) >> FRACBITS);
 
-		if (!bothfloorssky)
-		{
-			if (
-#ifdef ESLOPE
-				worldbottomslope > worldlowslope ||
-#endif
-				worldbottom > worldlow)
-			{
-				ds_p->silhouette = SIL_BOTTOM;
-#ifdef ESLOPE
-				if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
-					ds_p->bsilheight = INT32_MAX;
-				else
-					ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight);
-#else
-				ds_p->bsilheight = frontsector->floorheight;
-#endif
-			}
-#ifdef ESLOPE
-			else if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
-#else
-			else if (backsector->floorheight > viewz)
+		top_step = (top_step-top_frac)/(range);
+		bottom_step = (bottom_step-bottom_frac)/(range);
+
+		top_frac += top_step * (x1 - ds->x1);
+		bottom_frac += bottom_step * (x1 - ds->x1);
+	}
 #endif
-			{
-				ds_p->silhouette = SIL_BOTTOM;
-				ds_p->bsilheight = INT32_MAX;
-				// ds_p->sprbottomclip = negonearray;
-			}
-		}
 
-		if (!bothceilingssky)
+	// draw the columns
+	for (dc_x = x1; dc_x <= x2; dc_x++)
+	{
+		if (maskedtexturecol[dc_x] != INT16_MAX)
 		{
-			if (
-#ifdef ESLOPE
-				worldtopslope < worldhighslope ||
-#endif
-				worldtop < worldhigh)
-			{
-				ds_p->silhouette |= SIL_TOP;
 #ifdef ESLOPE
-				if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
-					ds_p->tsilheight = INT32_MIN;
-				else
-					ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight);
-#else
-				ds_p->tsilheight = frontsector->ceilingheight;
-#endif
+			if (ffloortextureslide) { // skew FOF walls
+				if (oldx != -1)
+					dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])<<FRACBITS);
+				oldx = dc_x;
 			}
-#ifdef ESLOPE
-			else if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
-#else
-			else if (backsector->ceilingheight < viewz)
 #endif
-			{
-				ds_p->silhouette |= SIL_TOP;
-				ds_p->tsilheight = INT32_MIN;
-				// ds_p->sprtopclip = screenheightarray;
-			}
-		}
+			// Calculate bounds
+			// clamp the values if necessary to avoid overflows and rendering glitches caused by them
 
-		if (!bothceilingssky && !bothfloorssky)
-		{
 #ifdef ESLOPE
-			if (worldhigh <= worldbottom && worldhighslope <= worldbottomslope)
-#else
-			if (worldhigh <= worldbottom)
-#endif
-			{
-				ds_p->sprbottomclip = negonearray;
-				ds_p->bsilheight = INT32_MAX;
-				ds_p->silhouette |= SIL_BOTTOM;
-			}
+			if      (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX;
+			else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac;
+			else                                 sprtopscreen = windowtop = CLAMPMIN;
+			if      (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX;
+			else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac;
+			else                                    sprbotscreen = windowbottom = CLAMPMIN;
 
-#ifdef ESLOPE
-			if (worldlow >= worldtop && worldlowslope >= worldtopslope)
+			top_frac += top_step;
+			bottom_frac += bottom_step;
 #else
-			if (worldlow >= worldtop)
+			sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale));
+			sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen;
 #endif
-			{
-				ds_p->sprtopclip = screenheightarray;
-				ds_p->tsilheight = INT32_MIN;
-				ds_p->silhouette |= SIL_TOP;
-			}
-		}
 
-		//SoM: 3/25/2000: This code fixes an automap bug that didn't check
-		// frontsector->ceiling and backsector->floor to see if a door was closed.
-		// Without the following code, sprites get displayed behind closed doors.
-		if (!bothceilingssky && !bothfloorssky)
-		{
-#ifdef ESLOPE
-			if (doorclosed || (worldhigh <= worldbottom && worldhighslope <= worldbottomslope))
-#else
-			if (doorclosed || backsector->ceilingheight <= frontsector->floorheight)
-#endif
+			// SoM: If column is out of range, why bother with it??
+			if (windowbottom < topbounds || windowtop > bottombounds)
 			{
-				ds_p->sprbottomclip = negonearray;
-				ds_p->bsilheight = INT32_MAX;
-				ds_p->silhouette |= SIL_BOTTOM;
-			}
-#ifdef ESLOPE
-			if (doorclosed || (worldlow >= worldtop && worldlowslope >= worldtopslope))
-#else
-			if (doorclosed || backsector->floorheight >= frontsector->ceilingheight)
-#endif
-			{                   // killough 1/17/98, 2/8/98
-				ds_p->sprtopclip = screenheightarray;
-				ds_p->tsilheight = INT32_MIN;
-				ds_p->silhouette |= SIL_TOP;
+				if (dc_numlights)
+				{
+					for (i = 0; i < dc_numlights; i++)
+					{
+						rlight = &dc_lightlist[i];
+						rlight->height += rlight->heightstep;
+						if (rlight->flags & FF_CUTLEVEL)
+							rlight->botheight += rlight->botheightstep;
+					}
+				}
+				spryscale += rw_scalestep;
+				continue;
 			}
-		}
 
-		if (bothfloorssky)
-		{
-			// see double ceiling skies comment
-			// this is the same but for upside down thok barriers where the floor is sky and the ceiling is normal
-			markfloor = false;
-		}
-		else if (worldlow != worldbottom
-#ifdef ESLOPE
-			|| worldlowslope != worldbottomslope
-			|| backsector->f_slope != frontsector->f_slope
-#endif
-		    || backsector->floorpic != frontsector->floorpic
-		    || backsector->lightlevel != frontsector->lightlevel
-		    //SoM: 3/22/2000: Check floor x and y offsets.
-		    || backsector->floor_xoffs != frontsector->floor_xoffs
-		    || backsector->floor_yoffs != frontsector->floor_yoffs
-		    || backsector->floorpic_angle != frontsector->floorpic_angle
-		    //SoM: 3/22/2000: Prevents bleeding.
-		    || (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum)
-		    || backsector->floorlightsec != frontsector->floorlightsec
-		    //SoM: 4/3/2000: Check for colormaps
-		    || frontsector->extra_colormap != backsector->extra_colormap
-		    || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag))
-		{
-			markfloor = true;
-		}
-		else
-		{
-			// same plane on both sides
-			markfloor = false;
-		}
+			dc_iscale = 0xffffffffu / (unsigned)spryscale;
 
-		if (bothceilingssky)
-		{
-			// double ceiling skies are special
-			// we don't want to lower the ceiling clipping, (no new plane is drawn anyway)
-			// so we can see the floor of thok barriers always regardless of sector properties
-			markceiling = false;
-		}
-		else if (worldhigh != worldtop
-#ifdef ESLOPE
-			|| worldhighslope != worldtopslope
-			|| backsector->c_slope != frontsector->c_slope
-#endif
-		    || backsector->ceilingpic != frontsector->ceilingpic
-		    || backsector->lightlevel != frontsector->lightlevel
-		    //SoM: 3/22/2000: Check floor x and y offsets.
-		    || backsector->ceiling_xoffs != frontsector->ceiling_xoffs
-		    || backsector->ceiling_yoffs != frontsector->ceiling_yoffs
-		    || backsector->ceilingpic_angle != frontsector->ceilingpic_angle
-		    //SoM: 3/22/2000: Prevents bleeding.
-		    || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum)
-		    || backsector->ceilinglightsec != frontsector->ceilinglightsec
-		    //SoM: 4/3/2000: Check for colormaps
-		    || frontsector->extra_colormap != backsector->extra_colormap
-		    || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag))
-		{
-				markceiling = true;
-		}
-		else
-		{
-			// same plane on both sides
-			markceiling = false;
-		}
+			// Get data for the column
+			col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3);
 
-		if (!bothceilingssky && !bothfloorssky)
-		{
-#ifdef ESLOPE
-			if ((worldhigh <= worldbottom && worldhighslope <= worldbottomslope)
-			 || (worldlow >= worldtop && worldlowslope >= worldtopslope))
-#else
-			if (backsector->ceilingheight <= frontsector->floorheight
-			 || backsector->floorheight >= frontsector->ceilingheight)
-#endif
+			// SoM: New code does not rely on R_DrawColumnShadowed_8 which
+			// will (hopefully) put less strain on the stack.
+			if (dc_numlights)
 			{
-				// closed door
-				markceiling = markfloor = true;
-			}
-		}
-	}
-}
+				lighttable_t **xwalllights;
+				fixed_t height;
+				fixed_t bheight = 0;
+				INT32 solid = 0;
+				INT32 lighteffect = 0;
 
-//
-// R_WorldStep
-// Does... stepping... stuff?
-//
-static void R_WorldStep(INT32 range)
-{
-	worldtop >>= 4;
-	worldbottom >>= 4;
-#ifdef ESLOPE
-	worldtopslope >>= 4;
-	worldbottomslope >>= 4;
-#else
-	(void)range;
-#endif
+				for (i = 0; i < dc_numlights; i++)
+				{
+					// Check if the current light effects the colormap/lightlevel
+					rlight = &dc_lightlist[i];
+					lighteffect = !(dc_lightlist[i].flags & FF_NOSHADE);
+					if (lighteffect)
+					{
+						lightnum = rlight->lightnum;
 
-	if (linedef->special == HORIZONSPECIAL) { // HORIZON LINES
-		topstep = bottomstep = 0;
-		topfrac = bottomfrac = (centeryfrac>>4);
-		topfrac++; // Prevent 1px HOM
-	} else {
-		topstep = -FixedMul (rw.scalestep, worldtop);
-		topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw.scale);
+						if (lightnum < 0)
+							xwalllights = scalelight[0];
+						else if (lightnum >= LIGHTLEVELS)
+							xwalllights = scalelight[LIGHTLEVELS-1];
+						else
+							xwalllights = scalelight[lightnum];
 
-		bottomstep = -FixedMul (rw.scalestep,worldbottom);
-		bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw.scale);
+						pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
 
-#ifdef ESLOPE
-		if (frontsector->c_slope) {
-			fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldtopslope, ds_p->scale2);
-			topstep = (topfracend-topfrac)/(range);
-		}
-		if (frontsector->f_slope) {
-			fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldbottomslope, ds_p->scale2);
-			bottomstep = (bottomfracend-bottomfrac)/(range);
+						if (pindex >= MAXLIGHTSCALE)
+							pindex = MAXLIGHTSCALE-1;
+
+						if (pfloor->flags & FF_FOG)
+						{
+							if (pfloor->master->frontsector->extra_colormap)
+								rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
+							else
+								rlight->rcolormap = xwalllights[pindex];
+						}
+						else
+						{
+							if (rlight->extra_colormap)
+								rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
+							else
+								rlight->rcolormap = xwalllights[pindex];
+						}
+					}
+
+					solid = 0; // don't carry over solid-cutting flag from the previous light
+
+					// Check if the current light can cut the current 3D floor.
+					if (rlight->flags & FF_CUTSOLIDS && !(pfloor->flags & FF_EXTRA))
+						solid = 1;
+					else if (rlight->flags & FF_CUTEXTRA && pfloor->flags & FF_EXTRA)
+					{
+						if (rlight->flags & FF_EXTRA)
+						{
+							// The light is from an extra 3D floor... Check the flags so
+							// there are no undesired cuts.
+							if ((rlight->flags & (FF_FOG|FF_SWIMMABLE)) == (pfloor->flags & (FF_FOG|FF_SWIMMABLE)))
+								solid = 1;
+						}
+						else
+							solid = 1;
+					}
+					else
+						solid = 0;
+
+					height = rlight->height;
+					rlight->height += rlight->heightstep;
+
+					if (solid)
+					{
+						bheight = rlight->botheight - (FRACUNIT >> 1);
+						rlight->botheight += rlight->botheightstep;
+					}
+
+					if (height <= windowtop)
+					{
+						if (lighteffect)
+							dc_colormap = rlight->rcolormap;
+						if (solid && windowtop < bheight)
+							windowtop = bheight;
+						continue;
+					}
+
+					windowbottom = height;
+					if (windowbottom >= sprbotscreen)
+					{
+						windowbottom = sprbotscreen;
+						// draw the texture
+						colfunc_2s (col);
+						for (i++; i < dc_numlights; i++)
+						{
+							rlight = &dc_lightlist[i];
+							rlight->height += rlight->heightstep;
+							if (rlight->flags & FF_CUTLEVEL)
+								rlight->botheight += rlight->botheightstep;
+						}
+						continue;
+					}
+					// draw the texture
+					colfunc_2s (col);
+					if (solid)
+						windowtop = bheight;
+					else
+						windowtop = windowbottom + 1;
+					if (lighteffect)
+						dc_colormap = rlight->rcolormap;
+				}
+				windowbottom = sprbotscreen;
+				// draw the texture, if there is any space left
+				if (windowtop < windowbottom)
+					colfunc_2s (col);
+
+				spryscale += rw_scalestep;
+				continue;
+			}
+
+			// calculate lighting
+			pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
+
+			if (pindex >= MAXLIGHTSCALE)
+				pindex = MAXLIGHTSCALE - 1;
+
+			dc_colormap = walllights[pindex];
+
+			if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap)
+				dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
+			else if (frontsector->extra_colormap)
+				dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
+
+			// draw the texture
+			colfunc_2s (col);
+			spryscale += rw_scalestep;
 		}
-#endif
 	}
+	colfunc = colfuncs[BASEDRAWFUNC];
+
+#undef CLAMPMAX
+#undef CLAMPMIN
 }
 
+// R_ExpandPlaneY
 //
-// R_WorldBackStep
-// Does... stepping... stuff? For backsides?!?!?!?!?!?!
-//
-static void R_WorldBackStep(INT32 range)
+// A simple function to modify a vsplane's top and bottom for a particular column
+// Sort of like R_ExpandPlane in r_plane.c, except this is vertical expansion
+static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bottom)
 {
-	INT32 i;
+	// Expand the plane, don't shrink it!
+	// note: top and bottom default to 0xFFFF and 0x0000 respectively, which is totally compatible with this
+	if (pl->top[x] > top)       pl->top[x] = top;
+	if (pl->bottom[x] < bottom) pl->bottom[x] = bottom;
+}
 
-	worldhigh >>= 4;
-	worldlow >>= 4;
-#ifdef ESLOPE
-	worldhighslope >>= 4;
-	worldlowslope >>= 4;
-#else
-	(void)range;
-#endif
+//
+// R_RenderSegLoop
+// Draws zero, one, or two textures (and possibly a masked
+//  texture) for walls.
+// Can draw or mark the starting pixel of floor and ceiling
+//  textures.
+// CALLED: CORE LOOPING ROUTINE.
+//
+#define HEIGHTBITS              12
+#define HEIGHTUNIT              (1<<HEIGHTBITS)
 
-	if (toptexture)
-	{
-		pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw.scale);
-		pixhighstep = -FixedMul (rw.scalestep,worldhigh);
 
-#ifdef ESLOPE
-		if (backsector->c_slope) {
-			fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2);
-			pixhighstep = (topfracend-pixhigh)/(range);
-		}
+//profile stuff ---------------------------------------------------------
+//#define TIMING
+#ifdef TIMING
+#include "p5prof.h"
+INT64 mycount;
+INT64 mytotal = 0;
+UINT32 nombre = 100000;
+//static   char runtest[10][80];
 #endif
-	}
+//profile stuff ---------------------------------------------------------
 
-	if (bottomtexture)
-	{
-		pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw.scale);
-		pixlowstep = -FixedMul (rw.scalestep,worldlow);
-#ifdef ESLOPE
-		if (backsector->f_slope) {
-			fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldlowslope, ds_p->scale2);
-			pixlowstep = (bottomfracend-pixlow)/(range);
-		}
-#endif
-	}
+static void R_RenderSegLoop (void)
+{
+	angle_t angle;
+	size_t  pindex;
+	INT32     yl;
+	INT32     yh;
 
-	{
-		ffloor_t * rover;
+	INT32     mid;
+	fixed_t texturecolumn = 0;
 #ifdef ESLOPE
-		fixed_t roverleft, roverright;
-		fixed_t planevistest;
+	fixed_t oldtexturecolumn = -1;
 #endif
-		i = 0;
-
-		if (backsector->ffloors)
-		{
-			for (rover = backsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next)
-			{
-				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES))
-					continue;
-				if (rover->norender == leveltime)
-					continue;
+	INT32     top;
+	INT32     bottom;
+	INT32     i;
 
-#ifdef ESLOPE
-				// Let the renderer know this sector is sloped.
-				if (*rover->b_slope || *rover->t_slope)
-					backsector->hasslope = true;
+	for (; rw_x < rw_stopx; rw_x++)
+	{
+		// mark floor / ceiling areas
+		yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
 
-				roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
-				roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
-				planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
+		top = ceilingclip[rw_x]+1;
 
-				if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
-					(roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
-					((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) ||
-					 (viewz > planevistest && (rover->flags & FF_BOTHPLANES))))
-				{
-					//ffloor[i].slope = *rover->b_slope;
-					ffloor[i].b_pos = roverleft;
-					ffloor[i].b_pos_slope = roverright;
-					ffloor[i].b_pos >>= 4;
-					ffloor[i].b_pos_slope >>= 4;
-					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-					ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
-					ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
-					i++;
-				}
+		// no space above wall?
+		if (yl < top)
+			yl = top;
 
-				if (i >= MAXFFLOORS)
-					break;
+		if (markceiling)
+		{
+#if 0
+			bottom = yl-1;
 
-				roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
-				roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
-				planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
+			if (bottom >= floorclip[rw_x])
+				bottom = floorclip[rw_x]-1;
 
-				if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
-					(roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
-					((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) ||
-					 (viewz < planevistest && (rover->flags & FF_BOTHPLANES))))
-				{
-					//ffloor[i].slope = *rover->t_slope;
-					ffloor[i].b_pos = roverleft;
-					ffloor[i].b_pos_slope = roverright;
-					ffloor[i].b_pos >>= 4;
-					ffloor[i].b_pos_slope >>= 4;
-					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-					ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
-					ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
-					i++;
-				}
+			if (top <= bottom)
 #else
-				if (*rover->bottomheight <= backsector->ceilingheight &&
-					*rover->bottomheight >= backsector->floorheight &&
-					((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
-					 (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES))))
-				{
-					ffloor[i].b_pos = *rover->bottomheight;
-					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-					ffloor[i].b_step = FixedMul(-rw.scalestep, ffloor[i].b_pos);
-					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-					i++;
-				}
-
-				if (i >= MAXFFLOORS)
-					break;
+			bottom = yl > floorclip[rw_x] ? floorclip[rw_x] : yl;
 
-				if (*rover->topheight >= backsector->floorheight &&
-					*rover->topheight <= backsector->ceilingheight &&
-					((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) ||
-					 (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES))))
-				{
-					ffloor[i].b_pos = *rover->topheight;
-					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-					ffloor[i].b_step = FixedMul(-rw.scalestep, ffloor[i].b_pos);
-					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-					i++;
-				}
+			if (top <= --bottom && ceilingplane)
 #endif
-			}
+				R_ExpandPlaneY(ceilingplane, rw_x, top, bottom);
 		}
-		else if (frontsector && frontsector->ffloors)
-		{
-			for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next)
-			{
-				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES))
-					continue;
-				if (rover->norender == leveltime)
-					continue;
 
 
-#ifdef ESLOPE
-				// Let the renderer know this sector is sloped.
-				if (*rover->b_slope || *rover->t_slope)
-					frontsector->hasslope = true;
-
-				roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
-				roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
-				planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
+		yh = bottomfrac>>HEIGHTBITS;
 
-				if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
-					(roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
-					((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) ||
-					 (viewz > planevistest && (rover->flags & FF_BOTHPLANES))))
-				{
-					//ffloor[i].slope = *rover->b_slope;
-					ffloor[i].b_pos = roverleft;
-					ffloor[i].b_pos_slope = roverright;
-					ffloor[i].b_pos >>= 4;
-					ffloor[i].b_pos_slope >>= 4;
-					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-					ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
-					ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
-					i++;
-				}
+		bottom = floorclip[rw_x]-1;
 
-				if (i >= MAXFFLOORS)
-					break;
+		if (yh > bottom)
+			yh = bottom;
 
-				roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
-				roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
-				planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
+		if (markfloor)
+		{
+			top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh;
 
-				if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
-					(roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
-					((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) ||
-					 (viewz < planevistest && (rover->flags & FF_BOTHPLANES))))
-				{
-					//ffloor[i].slope = *rover->t_slope;
-					ffloor[i].b_pos = roverleft;
-					ffloor[i].b_pos_slope = roverright;
-					ffloor[i].b_pos >>= 4;
-					ffloor[i].b_pos_slope >>= 4;
-					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-					ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
-					ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
-					i++;
-				}
-#else
-				if (*rover->bottomheight <= frontsector->ceilingheight &&
-					*rover->bottomheight >= frontsector->floorheight &&
-					((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
-					 (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES))))
-				{
-					ffloor[i].b_pos = *rover->bottomheight;
-					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-					ffloor[i].b_step = FixedMul(-rw.scalestep, ffloor[i].b_pos);
-					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-					i++;
-				}
-				if (i >= MAXFFLOORS)
-					break;
-				if (*rover->topheight >= frontsector->floorheight &&
-					*rover->topheight <= frontsector->ceilingheight &&
-					((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) ||
-					 (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES))))
-				{
-					ffloor[i].b_pos = *rover->topheight;
-					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-					ffloor[i].b_step = FixedMul(-rw.scalestep, ffloor[i].b_pos);
-					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-					i++;
-				}
-#endif
-			}
+			if (++top <= bottom && floorplane)
+				R_ExpandPlaneY(floorplane, rw_x, top, bottom);
 		}
 
-#ifdef POLYOBJECTS_PLANES
-		if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES))
+		if (numffloors)
 		{
-			while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++;
-			if (i < numffloors && backsector->floorheight <= frontsector->ceilingheight &&
-				backsector->floorheight >= frontsector->floorheight &&
-				(viewz < backsector->floorheight))
-			{
-				if (ffloor[i].plane->minx > ds_p->x1)
-					ffloor[i].plane->minx = ds_p->x1;
-
-				if (ffloor[i].plane->maxx < ds_p->x2)
-					ffloor[i].plane->maxx = ds_p->x2;
+			firstseg->frontscale[rw_x] = frontscale[rw_x];
+			top = ceilingclip[rw_x]+1; // PRBoom
+			bottom = floorclip[rw_x]-1; // PRBoom
 
-#ifdef ESLOPE
-				ffloor[i].slope = NULL;
-#endif
-				ffloor[i].b_pos = backsector->floorheight;
-				ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-				ffloor[i].b_step = FixedMul(-rw.scalestep, ffloor[i].b_pos);
-				ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-				i++;
-			}
-			if (i < numffloors && backsector->ceilingheight >= frontsector->floorheight &&
-				backsector->ceilingheight <= frontsector->ceilingheight &&
-				(viewz > backsector->ceilingheight))
+			for (i = 0; i < numffloors; i++)
 			{
-				if (ffloor[i].plane->minx > ds_p->x1)
-					ffloor[i].plane->minx = ds_p->x1;
+#ifdef POLYOBJECTS_PLANES
+				if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
+					continue;
+#endif
 
-				if (ffloor[i].plane->maxx < ds_p->x2)
-					ffloor[i].plane->maxx = ds_p->x2;
+				if (ffloor[i].height < viewz)
+				{
+					INT32 top_w = (ffloor[i].f_frac >> HEIGHTBITS) + 1;
+					INT32 bottom_w = ffloor[i].f_clip[rw_x];
 
-#ifdef ESLOPE
-				ffloor[i].slope = NULL;
-#endif
-				ffloor[i].b_pos = backsector->ceilingheight;
-				ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-				ffloor[i].b_step = FixedMul(-rw.scalestep, ffloor[i].b_pos);
-				ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw.scale);
-				i++;
-			}
-		}
-#endif
+					if (top_w < top)
+						top_w = top;
 
-		numbackffloors = i;
-	}
-}
+					if (bottom_w > bottom)
+						bottom_w = bottom;
 
-//
-// R_WorldFFloorStep
-// Does... stepping... stuff? For FOFs?!
-//
-static void R_WorldFFloorStep(INT32 range)
-{
-	INT32 i;
-
-#ifndef ESLOPE
-	(void)range; // Not needed!
+#ifdef POLYOBJECTS_PLANES
+					// Polyobject-specific hack to fix plane leaking -Red
+					if (ffloor[i].polyobj && top_w >= bottom_w) {
+						ffloor[i].plane->top[rw_x] = 0xFFFF;
+						ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
+					} else
 #endif
 
-	for (i = 0; i < numffloors; i++)
-	{
-		ffloor[i].f_pos >>= 4;
-#ifdef ESLOPE
-		ffloor[i].f_pos_slope >>= 4;
-#endif
-		if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too.
-		{
-			ffloor[i].f_step = 0;
-			ffloor[i].f_frac = (centeryfrac>>4);
-			topfrac++; // Prevent 1px HOM
-		}
-		else
-		{
-#ifdef ESLOPE
-			ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw.scale);
-			ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(range);
-#else
-			ffloor[i].f_step = FixedMul(-rw.scalestep, ffloor[i].f_pos);
-			ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw.scale);
-#endif
-		}
-	}
-}
+					if (top_w <= bottom_w)
+					{
+						ffloor[i].plane->top[rw_x] = (INT16)top_w;
+						ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
+					}
+				}
+				else if (ffloor[i].height > viewz)
+				{
+					INT32 top_w = ffloor[i].c_clip[rw_x] + 1;
+					INT32 bottom_w = (ffloor[i].f_frac >> HEIGHTBITS);
 
-//
-// R_WorldLightLists
-// Creates light lists.
-//
-static void R_WorldLightLists(INT32 range)
-{
-	INT32 i, p;
-	lightlist_t   *light;
-	r_lightlist_t *rlight;
+					if (top_w < top)
+						top_w = top;
 
-#ifndef ESLOPE
-	(void)range; // Not needed!
-#endif
+					if (bottom_w > bottom)
+						bottom_w = bottom;
 
-	dc_numlights = 0;
+#ifdef POLYOBJECTS_PLANES
+					// Polyobject-specific hack to fix plane leaking -Red
+					if (ffloor[i].polyobj && top_w >= bottom_w) {
+						ffloor[i].plane->top[rw_x] = 0xFFFF;
+						ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
+					} else
+#endif
 
-	if (frontsector->numlights)
-	{
-		dc_numlights = frontsector->numlights;
-		if (dc_numlights >= dc_maxlights)
-		{
-			dc_maxlights = dc_numlights;
-			dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL);
+					if (top_w <= bottom_w)
+					{
+						ffloor[i].plane->top[rw_x] = (INT16)top_w;
+						ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
+					}
+				}
+			}
 		}
 
-		for (i = p = 0; i < dc_numlights; i++)
-		{
+		//SoM: Calculate offsets for Thick fake floors.
+		// calculate texture offset
+		angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
+		texturecolumn = rw_offset-FixedMul(FINETANGENT(angle),rw_distance);
+
 #ifdef ESLOPE
-			fixed_t leftheight, rightheight;
+		if (oldtexturecolumn != -1) {
+			rw_bottomtexturemid += FixedMul(rw_bottomtextureslide,  oldtexturecolumn-texturecolumn);
+			rw_midtexturemid    += FixedMul(rw_midtextureslide,     oldtexturecolumn-texturecolumn);
+			rw_toptexturemid    += FixedMul(rw_toptextureslide,     oldtexturecolumn-texturecolumn);
+			rw_midtextureback   += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn);
+		}
+		oldtexturecolumn = texturecolumn;
 #endif
 
-			light = &frontsector->lightlist[i];
-			rlight = &dc_lightlist[p];
+		texturecolumn >>= FRACBITS;
 
-#ifdef ESLOPE
-			if (light->slope) {
-				leftheight = P_GetZAt(light->slope, segleft.x, segleft.y);
-				rightheight = P_GetZAt(light->slope, segright.x, segright.y);
+		// texturecolumn and lighting are independent of wall tiers
+		if (segtextured)
+		{
+			// calculate lighting
+			pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
 
-				// Flag sector as having slopes
-				frontsector->hasslope = true;
-			} else
-				leftheight = rightheight = light->height;
+			if (pindex >=  MAXLIGHTSCALE)
+				pindex = MAXLIGHTSCALE-1;
 
-			leftheight -= viewz;
-			rightheight -= viewz;
+			dc_colormap = walllights[pindex];
+			dc_x = rw_x;
+			dc_iscale = 0xffffffffu / (unsigned)rw_scale;
 
-			leftheight >>= 4;
-			rightheight >>= 4;
-#endif
+			if (frontsector->extra_colormap)
+				dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
+		}
 
-			if (i != 0)
+		if (dc_numlights)
+		{
+			lighttable_t **xwalllights;
+			for (i = 0; i < dc_numlights; i++)
 			{
-#ifdef ESLOPE
-				if (leftheight < worldbottom && rightheight < worldbottomslope)
-					continue;
-
-				if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
-					continue;
-#else
-				if (light->height < frontsector->floorheight)
-					continue;
-
-				if (light->height > frontsector->ceilingheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
-					continue;
-#endif
-			}
-
-#ifdef ESLOPE
-			rlight->height = (centeryfrac>>4) - FixedMul(leftheight, rw.scale);
-			rlight->heightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
-			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
-#else
-			rlight->height = (centeryfrac>>4) - FixedMul((light->height - viewz) >> 4, rw.scale);
-			rlight->heightstep = -FixedMul (rw.scalestep, (light->height - viewz) >> 4);
-#endif
-			rlight->flags = light->flags;
+				INT32 lightnum;
+				lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT);
 
-			if (light->caster && light->caster->flags & FF_CUTSOLIDS)
-			{
-#ifdef ESLOPE
-				if (*light->caster->b_slope) {
-					leftheight = P_GetZAt(*light->caster->b_slope, segleft.x, segleft.y);
-					rightheight = P_GetZAt(*light->caster->b_slope, segright.x, segright.y);
+				if (dc_lightlist[i].extra_colormap)
+					;
+				else if (curline->v1->y == curline->v2->y)
+					lightnum--;
+				else if (curline->v1->x == curline->v2->x)
+					lightnum++;
 
-					// Flag sector as having slopes
-					frontsector->hasslope = true;
-				} else
-					leftheight = rightheight = *light->caster->bottomheight;
+				if (lightnum < 0)
+					xwalllights = scalelight[0];
+				else if (lightnum >= LIGHTLEVELS)
+					xwalllights = scalelight[LIGHTLEVELS-1];
+				else
+					xwalllights = scalelight[lightnum];
 
-				leftheight -= viewz;
-				rightheight -= viewz;
+				pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
 
-				leftheight >>= 4;
-				rightheight >>= 4;
+				if (pindex >=  MAXLIGHTSCALE)
+					pindex = MAXLIGHTSCALE-1;
 
-				rlight->botheight = (centeryfrac>>4) - FixedMul(leftheight, rw.scale);
-				rlight->botheightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
-				rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range);
+				if (dc_lightlist[i].extra_colormap)
+					dc_lightlist[i].rcolormap = dc_lightlist[i].extra_colormap->colormap + (xwalllights[pindex] - colormaps);
+				else
+					dc_lightlist[i].rcolormap = xwalllights[pindex];
 
-#else
-				rlight->botheight = (centeryfrac >> 4) - FixedMul((*light->caster->bottomheight - viewz) >> 4, rw.scale);
-				rlight->botheightstep = -FixedMul (rw.scalestep, (*light->caster->bottomheight - viewz) >> 4);
-#endif
+				colfunc = colfuncs[COLDRAWFUNC_SHADOWED];
 			}
-
-			rlight->lightlevel = *light->lightlevel;
-			rlight->extra_colormap = *light->extra_colormap;
-			p++;
 		}
 
-		dc_numlights = p;
-	}
-}
-
-//
-// R_MarkPlanes
-// Creates visplanes.
-//
-static void R_MarkPlanes(void)
-{
-	INT32 i;
-
-	// get a new or use the same visplane
-	if (markceiling)
-	{
-		if (ceilingplane) //SoM: 3/29/2000: Check for null ceiling planes
-			ceilingplane = R_CheckPlane (ceilingplane, rw.x, rw.stopx-1);
-		else
-			markceiling = false;
-
-		// Don't mark ceiling flat lines for polys unless this line has an upper texture, otherwise we get flat leakage pulling downward
-		// (If it DOES have an upper texture and we do this, the ceiling won't render at all)
-		if (curline->polyseg && !curline->sidedef->toptexture)
-			markceiling = false;
-	}
+		frontscale[rw_x] = rw_scale;
 
-	// get a new or use the same visplane
-	if (markfloor)
-	{
-		if (floorplane) //SoM: 3/29/2000: Check for null planes
-			floorplane = R_CheckPlane (floorplane, rw.x, rw.stopx-1);
-		else
-			markfloor = false;
+		// draw the wall tiers
+		if (midtexture)
+		{
+			// single sided line
+			if (yl <= yh && yh >= 0 && yl < viewheight)
+			{
+				dc_yl = yl;
+				dc_yh = yh;
+				dc_texturemid = rw_midtexturemid;
+				dc_source = R_GetColumn(midtexture,texturecolumn);
+				dc_texheight = textureheight[midtexture]>>FRACBITS;
 
-		// Don't mark floor flat lines for polys unless this line has a lower texture, otherwise we get flat leakage pulling upward
-		// (If it DOES have a lower texture and we do this, the floor won't render at all)
-		if (curline->polyseg && !curline->sidedef->bottomtexture)
-			markfloor = false;
-	}
+				//profile stuff ---------------------------------------------------------
+#ifdef TIMING
+				ProfZeroTimer();
+#endif
+				colfunc();
+#ifdef TIMING
+				RDMSR(0x10,&mycount);
+				mytotal += mycount;      //64bit add
 
-	ds_p->numffloorplanes = 0;
-	if (numffloors)
-	{
-		if (!firstseg)
-		{
-			ds_p->numffloorplanes = numffloors;
+				if (nombre--==0)
+					I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1),
+						(INT32)mytotal);
+#endif
+				//profile stuff ---------------------------------------------------------
 
-			for (i = 0; i < numffloors; i++)
+				// dont draw anything more for this column, since
+				// a midtexture blocks the view
+				ceilingclip[rw_x] = (INT16)viewheight;
+				floorclip[rw_x] = -1;
+			}
+			else
 			{
-				ds_p->ffloorplanes[i] = ffloor[i].plane =
-					R_CheckPlane(ffloor[i].plane, rw.x, rw.stopx - 1);
+				// note: don't use min/max macros, since casting from INT32 to INT16 is involved here
+				if (markceiling)
+					ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
+				if (markfloor)
+					floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
 			}
-
-			firstseg = ds_p;
 		}
 		else
 		{
-			for (i = 0; i < numffloors; i++)
-				R_ExpandPlane(ffloor[i].plane, rw.x, rw.stopx - 1);
-		}
-#ifdef POLYOBJECTS_PLANES
-		// FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red
-		if (curline->polyseg)
-		{
-			for (i = 0; i < numffloors; i++)
+			// two sided line
+			if (toptexture)
 			{
-				if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)
-					continue;
-				if (ffloor[i].plane->minx > rw.x)
-					ffloor[i].plane->minx = rw.x;
+				// top wall
+				mid = pixhigh>>HEIGHTBITS;
+				pixhigh += pixhighstep;
 
-				if (ffloor[i].plane->maxx < rw.stopx - 1)
-					ffloor[i].plane->maxx = rw.stopx - 1;
-			}
-		}
-#endif
-	}
-}
+				if (mid >= floorclip[rw_x])
+					mid = floorclip[rw_x]-1;
 
-//
-// R_RemoveOpeningLimits
-// Code to remove limits on openings.
-//
-static void R_RemoveOpeningLimits(INT32 start)
-{
-	size_t pos = lastopening - openings;
-	size_t need = (rw.stopx - start)*4 + pos;
-	if (need > maxopenings)
-	{
-		drawseg_t *ds;  //needed for fix from *cough* zdoom *cough*
-		INT16 *oldopenings = openings;
-		INT16 *oldlast = lastopening;
-
-		do
-			maxopenings = maxopenings ? maxopenings*2 : 16384;
-		while (need > maxopenings);
-		openings = Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL);
-		lastopening = openings + pos;
-
-		// borrowed fix from *cough* zdoom *cough*
-		// [RH] We also need to adjust the openings pointers that
-		//    were already stored in drawsegs.
-		for (ds = drawsegs; ds < ds_p; ds++)
-		{
-#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings;
-			ADJUST(maskedtexturecol);
-			ADJUST(sprtopclip);
-			ADJUST(sprbottomclip);
-			ADJUST(thicksidecol);
-#undef ADJUST
-		}
+				if (mid >= yl) // back ceiling lower than front ceiling ?
+				{
+					if (yl >= viewheight) // entirely off bottom of screen
+						ceilingclip[rw_x] = (INT16)viewheight;
+					else if (mid >= 0) // safe to draw top texture
+					{
+						dc_yl = yl;
+						dc_yh = mid;
+						dc_texturemid = rw_toptexturemid;
+						dc_source = R_GetColumn(toptexture,texturecolumn);
+						dc_texheight = textureheight[toptexture]>>FRACBITS;
+						colfunc();
+						ceilingclip[rw_x] = (INT16)mid;
+					}
+					else // entirely off top of screen
+						ceilingclip[rw_x] = -1;
+				}
+				else
+					ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
+			}
+			else if (markceiling) // no top wall
+				ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
+
+			if (bottomtexture)
+			{
+				// bottom wall
+				mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
+				pixlow += pixlowstep;
+
+				// no space above wall?
+				if (mid <= ceilingclip[rw_x])
+					mid = ceilingclip[rw_x]+1;
+
+				if (mid <= yh) // back floor higher than front floor ?
+				{
+					if (yh < 0) // entirely off top of screen
+						floorclip[rw_x] = -1;
+					else if (mid < viewheight) // safe to draw bottom texture
+					{
+						dc_yl = mid;
+						dc_yh = yh;
+						dc_texturemid = rw_bottomtexturemid;
+						dc_source = R_GetColumn(bottomtexture,
+							texturecolumn);
+						dc_texheight = textureheight[bottomtexture]>>FRACBITS;
+						colfunc();
+						floorclip[rw_x] = (INT16)mid;
+					}
+					else  // entirely off bottom of screen
+						floorclip[rw_x] = (INT16)viewheight;
+				}
+				else
+					floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
+			}
+			else if (markfloor) // no bottom wall
+				floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
+		}
+
+		if (maskedtexture || numthicksides)
+		{
+			// save texturecol
+			//  for backdrawing of masked mid texture
+			maskedtexturecol[rw_x] = (INT16)texturecolumn;
+
+#ifdef ESLOPE
+			if (maskedtextureheight != NULL) {
+				maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ?
+											max(rw_midtexturemid, rw_midtextureback) :
+											min(rw_midtexturemid, rw_midtextureback));
+			}
+#endif
+		}
+
+		if (dc_numlights)
+		{
+			for (i = 0; i < dc_numlights; i++)
+			{
+				dc_lightlist[i].height += dc_lightlist[i].heightstep;
+				if (dc_lightlist[i].flags & FF_CUTSOLIDS)
+					dc_lightlist[i].botheight += dc_lightlist[i].botheightstep;
+			}
+		}
+
+		for (i = 0; i < numffloors; i++)
+			ffloor[i].f_frac += ffloor[i].f_step;
+
+		for (i = 0; i < numbackffloors; i++)
+		{
+			ffloor[i].f_clip[rw_x] = ffloor[i].c_clip[rw_x] = (INT16)((ffloor[i].b_frac >> HEIGHTBITS) & 0xFFFF);
+			ffloor[i].b_frac += ffloor[i].b_step;
+		}
+
+		rw_scale += rw_scalestep;
+		topfrac += topstep;
+		bottomfrac += bottomstep;
+	}
+}
+
+// Uses precalculated seg->length
+static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2)
+{
+	if (!seg->linedef->dy)
+		return llabs(y2 - seg->v1->y);
+	else if (!seg->linedef->dx)
+		return llabs(x2 - seg->v1->x);
+	else
+	{
+		INT64 dx = (seg->v2->x)-(seg->v1->x);
+		INT64 dy = (seg->v2->y)-(seg->v1->y);
+		INT64 vdx = x2-(seg->v1->x);
+		INT64 vdy = y2-(seg->v1->y);
+		return ((dy*vdx)-(dx*vdy))/(seg->length);
 	}
 }
 
@@ -1948,8 +1718,15 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 #ifndef ESLOPE
 	fixed_t       vtop;
 #endif
-	INT32           i;
+	INT32           lightnum;
+	INT32           i, p;
+	lightlist_t   *light;
+	r_lightlist_t *rlight;
 	INT32 range;
+#ifdef ESLOPE
+	vertex_t segleft, segright;
+	fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide;
+#endif
 	static size_t maxdrawsegs = 0;
 
 #ifdef ESLOPE
@@ -1979,9 +1756,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	sidedef = curline->sidedef;
 	linedef = curline->linedef;
 
-	// calculate rw.distance for scale calculation
-	rw.normalangle = curline->angle + ANGLE_90;
-	offsetangle = abs((INT32)(rw.normalangle-rw.angle1));
+	// calculate rw_distance for scale calculation
+	rw_normalangle = curline->angle + ANGLE_90;
+	offsetangle = abs((INT32)(rw_normalangle-rw_angle1));
 
 	if (offsetangle > ANGLE_90)
 		offsetangle = ANGLE_90;
@@ -1990,38 +1767,154 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	sineval = FINESINE(distangle>>ANGLETOFINESHIFT);
 
 	hyp = R_PointToDist(curline->v1->x, curline->v1->y);
+	rw_distance = FixedMul(hyp, sineval);
 	longboi = (hyp >= INT32_MAX);
 
-	// The seg is vertical.
-	if (curline->v1->y == curline->v2->y)
-		rw.distance = (fixed_t)(llabs(viewy - curline->v1->y));
-	// The seg is horizontal.
-	else if (curline->v1->x == curline->v2->x)
-		rw.distance = (fixed_t)(llabs(viewx - curline->v1->x));
 	// big room fix
-#ifdef SOFTWARE_USE_FLOATS
-	else if ((curline->length >= 1024<<FRACBITS) || longboi)
-#else
-	else if (longboi)
-#endif
-		R_CalculateSegDistance(curline, viewx, viewy, longboi);
-	else
-		rw.distance = FixedMul(hyp, sineval);
+	if (longboi)
+		rw_distance = (fixed_t)R_CalcSegDist(curline,viewx,viewy);
 
-	ds_p->x1 = rw.x = start;
+	ds_p->x1 = rw_x = start;
 	ds_p->x2 = stop;
 	ds_p->curline = curline;
-	rw.stopx = stop+1;
+	rw_stopx = stop+1;
 
 	//SoM: Code to remove limits on openings.
-	R_RemoveOpeningLimits(start);
+	{
+		size_t pos = lastopening - openings;
+		size_t need = (rw_stopx - start)*4 + pos;
+		if (need > maxopenings)
+		{
+			drawseg_t *ds;  //needed for fix from *cough* zdoom *cough*
+			INT16 *oldopenings = openings;
+			INT16 *oldlast = lastopening;
+
+			do
+				maxopenings = maxopenings ? maxopenings*2 : 16384;
+			while (need > maxopenings);
+			openings = Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL);
+			lastopening = openings + pos;
+
+			// borrowed fix from *cough* zdoom *cough*
+			// [RH] We also need to adjust the openings pointers that
+			//    were already stored in drawsegs.
+			for (ds = drawsegs; ds < ds_p; ds++)
+			{
+#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings;
+				ADJUST(maskedtexturecol);
+				ADJUST(sprtopclip);
+				ADJUST(sprbottomclip);
+				ADJUST(thicksidecol);
+#undef ADJUST
+			}
+		}
+	}  // end of code to remove limits on openings
 
 	// calculate scale at both ends and step
-	range = R_CalculateWallScale(start, stop);
+	ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]);
+
+	if (stop > start)
+	{
+		ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]);
+		range = stop-start;
+	}
+	else
+	{
+		// UNUSED: try to fix the stretched line bug
+#if 0
+		if (rw_distance < FRACUNIT/2)
+		{
+			fixed_t         tr_x,tr_y;
+			fixed_t         gxt,gyt;
+			CONS_Debug(DBG_RENDER, "TRYING TO FIX THE STRETCHED ETC\n");
+
+			tr_x = curline->v1->x - viewx;
+			tr_y = curline->v1->y - viewy;
+
+			gxt = FixedMul(tr_x, viewcos);
+			gyt = -FixedMul(tr_y, viewsin);
+			ds_p->scale1 = FixedDiv(projection, gxt - gyt);
+		}
+#endif
+		ds_p->scale2 = ds_p->scale1;
+		range = 1;
+	}
+
+	ds_p->scalestep = rw_scalestep = (ds_p->scale2 - rw_scale) / (range);
 
 	// calculate texture boundaries
 	//  and decide if floor / ceiling marks are needed
-	R_WorldTopAndBottom(start, stop);
+#ifdef ESLOPE
+	// Figure out map coordinates of where start and end are mapping to on seg, so we can clip right for slope bullshit
+	if (frontsector->hasslope || (backsector && backsector->hasslope)) // Commenting this out for FOFslop. -Red
+	{
+		angle_t temp;
+
+		// left
+		temp = xtoviewangle[start]+viewangle;
+
+		{
+			// Both lines can be written in slope-intercept form, so figure out line intersection
+			float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector...
+			///TODO: convert to FPU
+
+			a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y);
+			b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x);
+			c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y);
+
+			a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT));
+			b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT));
+			c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy);
+
+			det = a1*b2 - a2*b1;
+
+			ds_p->leftpos.x = segleft.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det);
+			ds_p->leftpos.y = segleft.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det);
+		}
+
+		// right
+		temp = xtoviewangle[stop]+viewangle;
+
+		{
+			// Both lines can be written in slope-intercept form, so figure out line intersection
+			float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector...
+			///TODO: convert to FPU
+
+			a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y);
+			b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x);
+			c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y);
+
+			a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT));
+			b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT));
+			c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy);
+
+			det = a1*b2 - a2*b1;
+
+			ds_p->rightpos.x = segright.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det);
+			ds_p->rightpos.y = segright.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det);
+		}
+	}
+
+
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+	if (slope) { \
+		end1 = P_GetZAt(slope, segleft.x, segleft.y); \
+		end2 = P_GetZAt(slope, segright.x, segright.y); \
+	} else \
+		end1 = end2 = normalheight;
+
+	SLOPEPARAMS(frontsector->c_slope, worldtop,    worldtopslope,    frontsector->ceilingheight)
+	SLOPEPARAMS(frontsector->f_slope, worldbottom, worldbottomslope, frontsector->floorheight)
+	// subtract viewz from these to turn them into
+	// positions relative to the camera's z position
+	worldtop -= viewz;
+	worldtopslope -= viewz;
+	worldbottom -= viewz;
+	worldbottomslope -= viewz;
+#else
+	worldtop = frontsector->ceilingheight - viewz;
+	worldbottom = frontsector->floorheight - viewz;
+#endif
 
 	midtexture = toptexture = bottomtexture = maskedtexture = 0;
 	ds_p->maskedtexturecol = NULL;
@@ -2056,7 +1949,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 #ifdef ESLOPE
 	// Set up texture Y offset slides for sloped walls
-	rw.toptextureslide = rw.midtextureslide = rw.bottomtextureslide = 0;
+	rw_toptextureslide = rw_midtextureslide = rw_bottomtextureslide = 0;
 	ceilingfrontslide = floorfrontslide = ceilingbackslide = floorbackslide = 0;
 
 	{
@@ -2076,1051 +1969,762 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	}
 #endif
 
-	// Check for textures
-	R_StoreWallSilhouette();
-	R_CheckWallTextures();
-	if (backsector)
-		R_CheckMaskedTextures();
-
-#undef SLOPEPARAMS
-
-	// Calculate rw.offset (only needed for textured lines)
-	segtextured = midtexture || toptexture || bottomtexture || maskedtexture || (numthicksides > 0);
-	if (segtextured)
-		R_SegTextured(hyp, longboi);
-
-	// if a floor / ceiling plane is on the wrong side
-	//  of the view plane, it is definitely invisible
-	//  and doesn't need to be marked.
-	if (frontsector->heightsec == -1)
+	if (!backsector)
 	{
-		if (frontsector->floorpic != skyflatnum
-		&& (
+		fixed_t texheight;
+		// single sided line
+		midtexture = R_GetTextureNum(sidedef->midtexture);
+		texheight = textureheight[midtexture];
+		// a single sided line is terminal, so it must mark ends
+		markfloor = markceiling = true;
 #ifdef ESLOPE
-			frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) :
+		if (linedef->flags & ML_EFFECT2) {
+			if (linedef->flags & ML_DONTPEGBOTTOM)
+				rw_midtexturemid = frontsector->floorheight + texheight - viewz;
+			else
+				rw_midtexturemid = frontsector->ceilingheight - viewz;
+		}
+		else
 #endif
-			frontsector->floorheight) >= viewz)
+		if (linedef->flags & ML_DONTPEGBOTTOM)
 		{
-			// above view plane
-			markfloor = false;
-		}
-
-		if (frontsector->ceilingpic != skyflatnum
-		&& (
 #ifdef ESLOPE
-			frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) :
+			rw_midtexturemid = worldbottom + texheight;
+			rw_midtextureslide = floorfrontslide;
+#else
+			vtop = frontsector->floorheight + texheight;
+			// bottom of texture at bottom
+			rw_midtexturemid = vtop - viewz;
 #endif
-			frontsector->ceilingheight) <= viewz)
+		}
+		else
 		{
-			// below view plane
-			markceiling = false;
+			// top of texture at top
+			rw_midtexturemid = worldtop;
+#ifdef ESLOPE
+			rw_midtextureslide = ceilingfrontslide;
+#endif
 		}
-	}
-
-	// Calculate incremental stepping values for texture edges
-	R_WorldStep(range);
+		rw_midtexturemid += sidedef->rowoffset;
 
-	// Create light lists
-	R_WorldLightLists(range);
+		ds_p->silhouette = SIL_BOTH;
+		ds_p->sprtopclip = screenheightarray;
+		ds_p->sprbottomclip = negonearray;
+		ds_p->bsilheight = INT32_MAX;
+		ds_p->tsilheight = INT32_MIN;
+	}
+	else
+	{
+		// two sided line
+		boolean bothceilingssky = false; // turned on if both back and front ceilings are sky
+		boolean bothfloorssky = false; // likewise, but for floors
 
-	// Step FOFs
-	if (numffloors)
-		 R_WorldFFloorStep(range);
-
-	// Step world back
-	if (backsector)
-		R_WorldBackStep(range);
-
-	// Mark floor and or ceiling visplanes
-	R_MarkPlanes();
-
-#ifdef WALLSPLATS
-	if (linedef->splats && cv_splats.value)
-	{
-		// Isn't a bit wasteful to copy the ENTIRE array for every drawseg?
-		M_Memcpy(last_ceilingclip + ds_p->x1, ceilingclip + ds_p->x1,
-			sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1));
-		M_Memcpy(last_floorclip + ds_p->x1, floorclip + ds_p->x1,
-			sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1));
-		R_RenderSegLoop();
-		R_DrawWallSplats();
-	}
-	else
-#endif
-		R_RenderSegLoop();
-	colfunc = colfuncs[BASEDRAWFUNC];
-
-	if (portalline) // if curline is a portal, set portalrender for drawseg
-		ds_p->portalpass = portalrender+1;
-	else
-		ds_p->portalpass = 0;
-
-	// save sprite clipping info
-	if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
-	{
-		M_Memcpy(lastopening, ceilingclip+start, 2*(rw.stopx - start));
-		ds_p->sprtopclip = lastopening - start;
-		lastopening += rw.stopx - start;
-	}
-
-	if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
-	{
-		M_Memcpy(lastopening, floorclip + start, 2*(rw.stopx-start));
-		ds_p->sprbottomclip = lastopening - start;
-		lastopening += rw.stopx - start;
-	}
-
-	if (maskedtexture && !(ds_p->silhouette & SIL_TOP))
-	{
-		ds_p->silhouette |= SIL_TOP;
-		ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX;
-	}
-	if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM))
-	{
-		ds_p->silhouette |= SIL_BOTTOM;
-		ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN;
-	}
-
-	ds_p++;
-}
-
-// ==========================================================================
-// R_Splats Wall Splats Drawer
-// ==========================================================================
-
-#ifdef WALLSPLATS
-static INT16 last_ceilingclip[MAXVIDWIDTH];
-static INT16 last_floorclip[MAXVIDWIDTH];
-
-static void R_DrawSplatColumn(column_t *column)
-{
-	INT32 topscreen, bottomscreen;
-	fixed_t basetexturemid;
-	INT32 topdelta, prevdelta = -1;
-
-	basetexturemid = dc_texturemid;
-
-	for (; column->topdelta != 0xff ;)
-	{
-		// calculate unclipped screen coordinates for post
-		topdelta = column->topdelta;
-		if (topdelta <= prevdelta)
-			topdelta += prevdelta;
-		prevdelta = topdelta;
-		topscreen = sprtopscreen + spryscale*topdelta;
-		bottomscreen = topscreen + spryscale*column->length;
-
-		dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
-		dc_yh = (bottomscreen-1)>>FRACBITS;
-
-		if (dc_yh >= last_floorclip[dc_x])
-			dc_yh = last_floorclip[dc_x] - 1;
-		if (dc_yl <= last_ceilingclip[dc_x])
-			dc_yl = last_ceilingclip[dc_x] + 1;
-		if (dc_yl <= dc_yh && dl_yh < vid.height && yh > 0)
-		{
-			dc_source = (UINT8 *)column + 3;
-			dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
-
-			// Drawn by R_DrawColumn.
-			colfunc();
-		}
-		column = (column_t *)((UINT8 *)column + column->length + 4);
-	}
-
-	dc_texturemid = basetexturemid;
-}
-
-static void R_DrawWallSplats(void)
-{
-	wallsplat_t *splat;
-	seg_t *seg;
-	angle_t angle, angle1, angle2;
-	INT32 x1, x2;
-	size_t pindex;
-	column_t *col;
-	patch_t *patch;
-	fixed_t texturecolumn;
-
-	splat = (wallsplat_t *)linedef->splats;
-
-	I_Assert(splat != NULL);
-
-	seg = ds_p->curline;
-
-	// draw all splats from the line that touches the range of the seg
-	for (; splat; splat = splat->next)
-	{
-		angle1 = R_PointToAngle(splat->v1.x, splat->v1.y);
-		angle2 = R_PointToAngle(splat->v2.x, splat->v2.y);
-		angle1 = (angle1 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT;
-		angle2 = (angle2 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT;
-		// out of the viewangletox lut
-		/// \todo clip it to the screen
-		if (angle1 > FINEANGLES/2 || angle2 > FINEANGLES/2)
-			continue;
-		x1 = viewangletox[angle1];
-		x2 = viewangletox[angle2];
-
-		if (x1 >= x2)
-			continue; // does not cross a pixel
-
-		// splat is not in this seg range
-		if (x2 < ds_p->x1 || x1 > ds_p->x2)
-			continue;
-
-		if (x1 < ds_p->x1)
-			x1 = ds_p->x1;
-		if (x2 > ds_p->x2)
-			x2 = ds_p->x2;
-		if (x2 <= x1)
-			continue;
-
-		// calculate incremental stepping values for texture edges
-		rw.scalestep = ds_p->scalestep;
-		spryscale = ds_p->scale1 + (x1 - ds_p->x1)*rw.scalestep;
-		mfloorclip = floorclip;
-		mceilingclip = ceilingclip;
-
-		patch = W_CachePatchNum(splat->patch, PU_PATCH);
-
-		dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz;
-		if (splat->yoffset)
-			dc_texturemid += *splat->yoffset;
-
-		sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
-
-		// set drawing mode
-		switch (splat->flags & SPLATDRAWMODE_MASK)
-		{
-			case SPLATDRAWMODE_OPAQUE:
-				colfunc = colfuncs[BASEDRAWFUNC];
-				break;
-			case SPLATDRAWMODE_TRANS:
-				if (!cv_translucency.value)
-					colfunc = colfuncs[BASEDRAWFUNC];
-				else
-				{
-					dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT);
-					colfunc = colfuncs[COLDRAWFUNC_FUZZY];
-				}
-
-				break;
-			case SPLATDRAWMODE_SHADE:
-				colfunc = colfuncs[COLDRAWFUNC_SHADE];
-				break;
-		}
-
-		dc_texheight = 0;
-
-		// draw the columns
-		for (dc_x = x1; dc_x <= x2; dc_x++, spryscale += rw.scalestep)
-		{
-			pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
-			if (pindex >= MAXLIGHTSCALE)
-				pindex = MAXLIGHTSCALE - 1;
-			dc_colormap = walllights[pindex];
-
-			if (frontsector->extra_colormap)
-				dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
-
-			sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
-			dc_iscale = 0xffffffffu / (unsigned)spryscale;
-
-			// find column of patch, from perspective
-			angle = (rw.centerangle + xtoviewangle[dc_x])>>ANGLETOFINESHIFT;
-				texturecolumn = rw.offset2 - splat->offset
-					- FixedMul(FINETANGENT(angle), rw.distance);
-
-			// FIXME!
-			texturecolumn >>= FRACBITS;
-			if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
-				continue;
-
-			// draw the texture
-			col = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
-			R_DrawSplatColumn(col);
-		}
-	} // next splat
-
-	colfunc = colfuncs[BASEDRAWFUNC];
-}
-
-#endif //WALLSPLATS
-
-// ==========================================================================
-// R_RenderMaskedSegRange
-// ==========================================================================
-
-// If we have a multi-patch texture on a 2sided wall (rare) then we draw
-//  it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this
-//  way we don't have to store extra post_t info with each column for
-//  multi-patch textures. They are not normally needed as multi-patch
-//  textures don't have holes in it. At least not for now.
-
-static void R_Render2sidedMultiPatchColumn(column_t *column)
-{
-	INT32 topscreen, bottomscreen;
-
-	topscreen = sprtopscreen; // + spryscale*column->topdelta;  topdelta is 0 for the wall
-	bottomscreen = topscreen + spryscale * rw.column2s_length;
-
-	dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
-	dc_yh = (bottomscreen-1)>>FRACBITS;
-
-	if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
-	{
-		dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
-		dc_yh = (windowbottom - 1)>>FRACBITS;
-	}
-
-	if (dc_yh >= mfloorclip[dc_x])
-		dc_yh =  mfloorclip[dc_x] - 1;
-	if (dc_yl <= mceilingclip[dc_x])
-		dc_yl =  mceilingclip[dc_x] + 1;
-
-	if (dc_yl >= vid.height || dc_yh < 0)
-		return;
-
-	if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
-	{
-		dc_source = (UINT8 *)column + 3;
-
-		if (colfunc == colfuncs[BASEDRAWFUNC])
-			(colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])();
-		else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
-			(colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])();
-		else
-			colfunc();
-	}
-}
-
-// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value
-// uses column2s_length for texture->height as above
-static void R_DrawFlippedMaskedSegColumn(column_t *column)
-{
-	R_DrawFlippedMaskedColumn(column, rw.column2s_length);
-}
-
-//
-// R_RenderMaskedSegLoop
-// Like R_RenderSegLoop, but for masked segs.
-//
-static void R_RenderMaskedSegLoop(drawseg_t *ds)
-{
-	size_t pindex;
-	column_t *col;
-	INT32 i;
-	fixed_t height, realbot;
-	r_lightlist_t *rlight;
-	INT64 overflow_test;
-
-	for (dc_x = rw.x; dc_x <= rw.stopx; dc_x++)
-	{
-#ifdef ESLOPE
-		dc_texturemid = ds->maskedtextureheight[dc_x];
-
-		if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3))
-			dc_texturemid += (textureheight[rw.texnum])*rw.maskedrepeat + textureheight[rw.texnum];
-		else
-			dc_texturemid -= (textureheight[rw.texnum])*rw.maskedrepeat;
-#endif
-		// calculate lighting
-		if (maskedtexturecol[dc_x] != INT16_MAX)
-		{
-			// Check for overflows first
-			overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS);
-			if (overflow_test < 0) overflow_test = -overflow_test;
-			if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL)
-			{
-				// Eh, no, go away, don't waste our time
-				if (dc_numlights)
-				{
-					for (i = 0; i < dc_numlights; i++)
-					{
-						rlight = &dc_lightlist[i];
-						rlight->height += rlight->heightstep;
-					}
-				}
-				spryscale += rw.scalestep;
-				continue;
-			}
-
-			if (dc_numlights)
-			{
-				lighttable_t **xwalllights;
-
-				sprbotscreen = INT32_MAX;
-				sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale));
-
-				realbot = windowbottom = FixedMul(textureheight[rw.texnum], spryscale) + sprtopscreen;
-				dc_iscale = 0xffffffffu / (unsigned)spryscale;
-
-				// draw the texture
-				col = (column_t *)((UINT8 *)R_GetColumn(rw.texnum, maskedtexturecol[dc_x]) - 3);
-
-				for (i = 0; i < dc_numlights; i++)
-				{
-					rlight = &dc_lightlist[i];
-
-					if ((rlight->flags & FF_NOSHADE))
-						continue;
-
-					if (rlight->lightnum < 0)
-						xwalllights = scalelight[0];
-					else if (rlight->lightnum >= LIGHTLEVELS)
-						xwalllights = scalelight[LIGHTLEVELS-1];
-					else
-						xwalllights = scalelight[rlight->lightnum];
-
-					pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
-
-					if (pindex >= MAXLIGHTSCALE)
-						pindex = MAXLIGHTSCALE - 1;
-
-					if (rlight->extra_colormap)
-						rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
-					else
-						rlight->rcolormap = xwalllights[pindex];
-
-					height = rlight->height;
-					rlight->height += rlight->heightstep;
-
-					if (height <= windowtop)
-					{
-						dc_colormap = rlight->rcolormap;
-						continue;
-					}
-
-					windowbottom = height;
-					if (windowbottom >= realbot)
-					{
-						windowbottom = realbot;
-						rw.colfunc_2s(col);
-						for (i++; i < dc_numlights; i++)
-						{
-							rlight = &dc_lightlist[i];
-							rlight->height += rlight->heightstep;
-						}
-
-						continue;
-					}
-					rw.colfunc_2s(col);
-					windowtop = windowbottom + 1;
-					dc_colormap = rlight->rcolormap;
-				}
-				windowbottom = realbot;
-				if (windowtop < windowbottom)
-					rw.colfunc_2s(col);
-
-				spryscale += rw.scalestep;
-				continue;
-			}
-
-			// calculate lighting
-			pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
-
-			if (pindex >= MAXLIGHTSCALE)
-				pindex = MAXLIGHTSCALE - 1;
-
-			dc_colormap = walllights[pindex];
-
-			if (frontsector->extra_colormap)
-				dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
-
-			sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
-			dc_iscale = 0xffffffffu / (unsigned)spryscale;
-
-			// draw the texture
-			col = (column_t *)((UINT8 *)R_GetColumn(rw.texnum, maskedtexturecol[dc_x]) - 3);
-
-//#ifdef POLYOBJECTS_PLANES
-#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red
-			if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES))
-			{
-				fixed_t my_topscreen;
-				fixed_t my_bottomscreen;
-				fixed_t my_yl, my_yh;
-
-				my_topscreen = sprtopscreen + spryscale*col->topdelta;
-				my_bottomscreen = sprbotscreen == INT32_MAX ? my_topscreen + spryscale*col->length
-														 : sprbotscreen + spryscale*col->length;
-
-				my_yl = (my_topscreen+FRACUNIT-1)>>FRACBITS;
-				my_yh = (my_bottomscreen-1)>>FRACBITS;
-//				CONS_Debug(DBG_RENDER, "my_topscreen: %d\nmy_bottomscreen: %d\nmy_yl: %d\nmy_yh: %d\n", my_topscreen, my_bottomscreen, my_yl, my_yh);
-
-				if (numffloors)
-				{
-					INT32 top = my_yl;
-					INT32 bottom = my_yh;
-
-					for (i = 0; i < numffloors; i++)
-					{
-						if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)
-							continue;
-
-						if (ffloor[i].height < viewz)
-						{
-							INT32 top_w = ffloor[i].plane->top[dc_x];
-
-//							CONS_Debug(DBG_RENDER, "Leveltime : %d\n", leveltime);
-//							CONS_Debug(DBG_RENDER, "Top is %d, top_w is %d\n", top, top_w);
-							if (top_w < top)
-							{
-								ffloor[i].plane->top[dc_x] = (INT16)top;
-								ffloor[i].plane->picnum = 0;
-							}
-//							CONS_Debug(DBG_RENDER, "top_w is now %d\n", ffloor[i].plane->top[dc_x]);
-						}
-						else if (ffloor[i].height > viewz)
-						{
-							INT32 bottom_w = ffloor[i].plane->bottom[dc_x];
-
-							if (bottom_w > bottom)
-							{
-								ffloor[i].plane->bottom[dc_x] = (INT16)bottom;
-								ffloor[i].plane->picnum = 0;
-							}
-						}
-					}
-				}
-			}
-			else
+#ifdef ESLOPE
+		SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight)
+		SLOPEPARAMS(backsector->f_slope, worldlow,  worldlowslope,  backsector->floorheight)
+		worldhigh -= viewz;
+		worldhighslope -= viewz;
+		worldlow -= viewz;
+		worldlowslope -= viewz;
+#else
+		worldhigh = backsector->ceilingheight - viewz;
+		worldlow = backsector->floorheight - viewz;
 #endif
-				rw.colfunc_2s(col);
-		}
-		spryscale += rw.scalestep;
-	}
-}
-
-//
-// R_MaskedLightLists
-// Creates light lists, but for masked segs.
-//
-static void R_MaskedLightLists(drawseg_t *ds, INT32 range)
-{
-	lightlist_t *light;
-	r_lightlist_t *rlight;
-	INT32 lightnum, i;
 
-	dc_numlights = 0;
+		// hack to allow height changes in outdoor areas
+		// This is what gets rid of the upper textures if there should be sky
+		if (frontsector->ceilingpic == skyflatnum
+			&& backsector->ceilingpic == skyflatnum)
+		{
+			bothceilingssky = true;
+		}
 
-	if (frontsector->numlights)
-	{
-		dc_numlights = frontsector->numlights;
-		if (dc_numlights >= dc_maxlights)
+		// likewise, but for floors and upper textures
+		if (frontsector->floorpic == skyflatnum
+			&& backsector->floorpic == skyflatnum)
 		{
-			dc_maxlights = dc_numlights;
-			dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL);
+			bothfloorssky = true;
 		}
 
-		for (i = 0; i < dc_numlights; i++)
+		ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
+		ds_p->silhouette = 0;
+
+		if (!bothfloorssky)
 		{
+			if (
 #ifdef ESLOPE
-			fixed_t leftheight, rightheight;
+				worldbottomslope > worldlowslope ||
+#endif
+				worldbottom > worldlow)
+			{
+				ds_p->silhouette = SIL_BOTTOM;
+#ifdef ESLOPE
+				if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
+					ds_p->bsilheight = INT32_MAX;
+				else
+					ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight);
 #else
-			(void)range;
+				ds_p->bsilheight = frontsector->floorheight;
 #endif
-			light = &frontsector->lightlist[i];
-			rlight = &dc_lightlist[i];
+			}
 #ifdef ESLOPE
-			if (light->slope) {
-				leftheight = P_GetZAt(light->slope, ds->leftpos.x, ds->leftpos.y);
-				rightheight = P_GetZAt(light->slope, ds->rightpos.x, ds->rightpos.y);
-			} else
-				leftheight = rightheight = light->height;
-
-			leftheight -= viewz;
-			rightheight -= viewz;
-
-			rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1);
-			rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2);
-			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
-			//if (x1 > ds->x1)
-				//rlight->height -= (x1 - ds->x1)*rlight->heightstep;
+			else if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
 #else
-			rlight->height = (centeryfrac) - FixedMul((light->height - viewz), spryscale);
-			rlight->heightstep = -FixedMul(rw.scalestep, (light->height - viewz));
+			else if (backsector->floorheight > viewz)
 #endif
-			rlight->startheight = rlight->height; // keep starting value here to reset for each repeat
-			rlight->lightlevel = *light->lightlevel;
-			rlight->extra_colormap = *light->extra_colormap;
-			rlight->flags = light->flags;
-
-			if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
-				lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
-			else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
-				lightnum = LIGHTLEVELS - 1;
-			else
-				lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
-
-			if (rlight->extra_colormap && rlight->extra_colormap->fog)
-				;
-			else if (curline->v1->y == curline->v2->y)
-				lightnum--;
-			else if (curline->v1->x == curline->v2->x)
-				lightnum++;
-
-			rlight->lightnum = lightnum;
-		}
-	}
-	else
-	{
-		if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
-		{
-			if (frontsector->extra_colormap && frontsector->extra_colormap->fog)
-				lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
-			else
-				lightnum = LIGHTLEVELS - 1;
+			{
+				ds_p->silhouette = SIL_BOTTOM;
+				ds_p->bsilheight = INT32_MAX;
+				// ds_p->sprbottomclip = negonearray;
+			}
 		}
-		else
-			lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
-
-		if (colfunc == colfuncs[COLDRAWFUNC_FOG]
-			|| (frontsector->extra_colormap && frontsector->extra_colormap->fog))
-			;
-		else if (curline->v1->y == curline->v2->y)
-			lightnum--;
-		else if (curline->v1->x == curline->v2->x)
-			lightnum++;
-
-		if (lightnum < 0)
-			walllights = scalelight[0];
-		else if (lightnum >= LIGHTLEVELS)
-			walllights = scalelight[LIGHTLEVELS - 1];
-		else
-			walllights = scalelight[lightnum];
-	}
-}
-
-//
-// R_RenderMaskedSegRange
-// Renders all the masked segs in the given range.
-//
-void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
-{
-	INT32 texnum, i;
-	r_lightlist_t *rlight;
-	line_t *ldef;
-	sector_t *front, *back;
-	INT32 times, repeats;
-	INT32 range;
-
-	// Calculate light table.
-	// Use different light tables
-	//   for horizontal / vertical / diagonal. Diagonal?
-	// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
-	curline = ds->curline;
-	frontsector = curline->frontsector;
-	backsector = curline->backsector;
-	texnum = R_GetTextureNum(curline->sidedef->midtexture);
-	windowbottom = windowtop = sprbotscreen = INT32_MAX;
-
-	rw.x = x1;
-	rw.stopx = x2;
-	rw.texnum = texnum;
-
-	// hack translucent linedef types (900-909 for transtables 1-9)
-	ldef = curline->linedef;
-	switch (ldef->special)
-	{
-		case 900:
-		case 901:
-		case 902:
-		case 903:
-		case 904:
-		case 905:
-		case 906:
-		case 907:
-		case 908:
-			dc_transmap = transtables + ((ldef->special-900)<<FF_TRANSSHIFT);
-			colfunc = colfuncs[COLDRAWFUNC_FUZZY];
-			break;
-		case 909:
-			colfunc = colfuncs[COLDRAWFUNC_FOG];
-			windowtop = frontsector->ceilingheight;
-			windowbottom = frontsector->floorheight;
-			break;
-		default:
-			colfunc = colfuncs[BASEDRAWFUNC];
-			break;
-	}
-
-	if (curline->polyseg && curline->polyseg->translucency > 0)
-	{
-		if (curline->polyseg->translucency >= NUMTRANSMAPS)
-			return;
-
-		dc_transmap = transtables + ((curline->polyseg->translucency-1)<<FF_TRANSSHIFT);
-		colfunc = colfuncs[COLDRAWFUNC_FUZZY];
-	}
 
+		if (!bothceilingssky)
+		{
+			if (
 #ifdef ESLOPE
-	range = max(ds->x2-ds->x1, 1);
+				worldtopslope < worldhighslope ||
 #endif
-	rw.scalestep = ds->scalestep;
-	spryscale = ds->scale1 + (x1 - ds->x1)*rw.scalestep;
-
-	// Texture must be cached before setting colfunc_2s,
-	// otherwise texture[texnum]->holes may be false when it shouldn't be
-	R_CheckTextureCache(texnum);
-	// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
-	// are not stored per-column with post info in SRB2
-	if (textures[texnum]->holes)
-	{
-		if (textures[texnum]->flip & 2) // vertically flipped?
-		{
-			rw.colfunc_2s = R_DrawFlippedMaskedSegColumn;
-			rw.column2s_length = textures[texnum]->height;
-		}
-		else
-			rw.colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
-	}
-	else
-	{
-		rw.colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info)
-		rw.column2s_length = textures[texnum]->height;
-	}
-
-	// Setup lighting based on the presence/lack-of 3D floors.
-	R_MaskedLightLists(ds, range);
-
-	maskedtexturecol = ds->maskedtexturecol;
-
-	mfloorclip = ds->sprbottomclip;
-	mceilingclip = ds->sprtopclip;
-
-	if (frontsector->heightsec != -1)
-		front = &sectors[frontsector->heightsec];
-	else
-		front = frontsector;
-
-	if (backsector->heightsec != -1)
-		back = &sectors[backsector->heightsec];
-	else
-		back = backsector;
-
-	if (ds->curline->sidedef->repeatcnt)
-		repeats = 1 + ds->curline->sidedef->repeatcnt;
-	else if (ldef->flags & ML_EFFECT5)
-	{
-		fixed_t high, low;
-
-		if (front->ceilingheight > back->ceilingheight)
-			high = back->ceilingheight;
-		else
-			high = front->ceilingheight;
+				worldtop < worldhigh)
+			{
+				ds_p->silhouette |= SIL_TOP;
+#ifdef ESLOPE
+				if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
+					ds_p->tsilheight = INT32_MIN;
+				else
+					ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight);
+#else
+				ds_p->tsilheight = frontsector->ceilingheight;
+#endif
+			}
+#ifdef ESLOPE
+			else if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
+#else
+			else if (backsector->ceilingheight < viewz)
+#endif
+			{
+				ds_p->silhouette |= SIL_TOP;
+				ds_p->tsilheight = INT32_MIN;
+				// ds_p->sprtopclip = screenheightarray;
+			}
+		}
 
-		if (front->floorheight > back->floorheight)
-			low = front->floorheight;
-		else
-			low = back->floorheight;
+		if (!bothceilingssky && !bothfloorssky)
+		{
+#ifdef ESLOPE
+			if (worldhigh <= worldbottom && worldhighslope <= worldbottomslope)
+#else
+			if (worldhigh <= worldbottom)
+#endif
+			{
+				ds_p->sprbottomclip = negonearray;
+				ds_p->bsilheight = INT32_MAX;
+				ds_p->silhouette |= SIL_BOTTOM;
+			}
 
-		repeats = (high - low)/textureheight[texnum];
-		if ((high-low)%textureheight[texnum])
-			repeats++; // tile an extra time to fill the gap -- Monster Iestyn
-	}
-	else
-		repeats = 1;
+#ifdef ESLOPE
+			if (worldlow >= worldtop && worldlowslope >= worldtopslope)
+#else
+			if (worldlow >= worldtop)
+#endif
+			{
+				ds_p->sprtopclip = screenheightarray;
+				ds_p->tsilheight = INT32_MIN;
+				ds_p->silhouette |= SIL_TOP;
+			}
+		}
 
-	for (times = 0; times < repeats; times++)
-	{
-		if (times > 0)
+		//SoM: 3/25/2000: This code fixes an automap bug that didn't check
+		// frontsector->ceiling and backsector->floor to see if a door was closed.
+		// Without the following code, sprites get displayed behind closed doors.
+		if (!bothceilingssky && !bothfloorssky)
 		{
-			rw.scalestep = ds->scalestep;
-			spryscale = ds->scale1 + (x1 - ds->x1)*rw.scalestep;
-			if (dc_numlights)
-			{ // reset all lights to their starting heights
-				for (i = 0; i < dc_numlights; i++)
-				{
-					rlight = &dc_lightlist[i];
-					rlight->height = rlight->startheight;
-				}
+#ifdef ESLOPE
+			if (doorclosed || (worldhigh <= worldbottom && worldhighslope <= worldbottomslope))
+#else
+			if (doorclosed || backsector->ceilingheight <= frontsector->floorheight)
+#endif
+			{
+				ds_p->sprbottomclip = negonearray;
+				ds_p->bsilheight = INT32_MAX;
+				ds_p->silhouette |= SIL_BOTTOM;
+			}
+#ifdef ESLOPE
+			if (doorclosed || (worldlow >= worldtop && worldlowslope >= worldtopslope))
+#else
+			if (doorclosed || backsector->floorheight >= frontsector->ceilingheight)
+#endif
+			{                   // killough 1/17/98, 2/8/98
+				ds_p->sprtopclip = screenheightarray;
+				ds_p->tsilheight = INT32_MIN;
+				ds_p->silhouette |= SIL_TOP;
 			}
 		}
 
-#ifndef ESLOPE
-		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
+		if (bothfloorssky)
 		{
-			dc_texturemid = front->floorheight > back->floorheight
-				? front->floorheight : back->floorheight;
-			dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
+			// see double ceiling skies comment
+			// this is the same but for upside down thok barriers where the floor is sky and the ceiling is normal
+			markfloor = false;
+		}
+		else if (worldlow != worldbottom
+#ifdef ESLOPE
+			|| worldlowslope != worldbottomslope
+			|| backsector->f_slope != frontsector->f_slope
+#endif
+		    || backsector->floorpic != frontsector->floorpic
+		    || backsector->lightlevel != frontsector->lightlevel
+		    //SoM: 3/22/2000: Check floor x and y offsets.
+		    || backsector->floor_xoffs != frontsector->floor_xoffs
+		    || backsector->floor_yoffs != frontsector->floor_yoffs
+		    || backsector->floorpic_angle != frontsector->floorpic_angle
+		    //SoM: 3/22/2000: Prevents bleeding.
+		    || (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum)
+		    || backsector->floorlightsec != frontsector->floorlightsec
+		    //SoM: 4/3/2000: Check for colormaps
+		    || frontsector->extra_colormap != backsector->extra_colormap
+		    || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag))
+		{
+			markfloor = true;
 		}
 		else
 		{
-			dc_texturemid = front->ceilingheight < back->ceilingheight
-				? front->ceilingheight : back->ceilingheight;
-			dc_texturemid = dc_texturemid - viewz;
+			// same plane on both sides
+			markfloor = false;
 		}
-		dc_texturemid += curline->sidedef->rowoffset;
 
-		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
-			dc_texturemid += (textureheight[texnum])*times;
-		else
-			dc_texturemid -= (textureheight[texnum])*times;
+		if (bothceilingssky)
+		{
+			// double ceiling skies are special
+			// we don't want to lower the ceiling clipping, (no new plane is drawn anyway)
+			// so we can see the floor of thok barriers always regardless of sector properties
+			markceiling = false;
+		}
+		else if (worldhigh != worldtop
+#ifdef ESLOPE
+			|| worldhighslope != worldtopslope
+			|| backsector->c_slope != frontsector->c_slope
 #endif
-
-		dc_texheight = textureheight[texnum]>>FRACBITS;
-
-		// draw the columns
-		rw.maskedrepeat = times;
-		R_RenderMaskedSegLoop(ds);
-	}
-	colfunc = colfuncs[BASEDRAWFUNC];
-}
-
-// Loop through R_DrawMaskedColumn calls
-static void R_DrawRepeatMaskedColumn(column_t *col)
-{
-	while (sprtopscreen < sprbotscreen) {
-		R_DrawMaskedColumn(col);
-		if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
-			sprtopscreen = INT32_MAX;
+		    || backsector->ceilingpic != frontsector->ceilingpic
+		    || backsector->lightlevel != frontsector->lightlevel
+		    //SoM: 3/22/2000: Check floor x and y offsets.
+		    || backsector->ceiling_xoffs != frontsector->ceiling_xoffs
+		    || backsector->ceiling_yoffs != frontsector->ceiling_yoffs
+		    || backsector->ceilingpic_angle != frontsector->ceilingpic_angle
+		    //SoM: 3/22/2000: Prevents bleeding.
+		    || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum)
+		    || backsector->ceilinglightsec != frontsector->ceilinglightsec
+		    //SoM: 4/3/2000: Check for colormaps
+		    || frontsector->extra_colormap != backsector->extra_colormap
+		    || (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag))
+		{
+				markceiling = true;
+		}
 		else
-			sprtopscreen += dc_texheight*spryscale;
-	}
-}
+		{
+			// same plane on both sides
+			markceiling = false;
+		}
 
-static void R_DrawRepeatFlippedMaskedColumn(column_t *col)
-{
-	do {
-		R_DrawFlippedMaskedColumn(col, rw.column2s_length);
-		sprtopscreen += dc_texheight*spryscale;
-	} while (sprtopscreen < sprbotscreen);
-}
+		if (!bothceilingssky && !bothfloorssky)
+		{
+#ifdef ESLOPE
+			if ((worldhigh <= worldbottom && worldhighslope <= worldbottomslope)
+			 || (worldlow >= worldtop && worldlowslope >= worldtopslope))
+#else
+			if (backsector->ceilingheight <= frontsector->floorheight
+			 || backsector->floorheight >= frontsector->ceilingheight)
+#endif
+			{
+				// closed door
+				markceiling = markfloor = true;
+			}
+		}
 
-//
-// R_RenderThickSegLoop
-// Like R_RenderSegLoop, but for thick sides.
-//
-static void R_RenderThickSegLoop(void)
-{
-	column_t *col;
-	size_t pindex;
-	INT32 i;
-	INT32 lightnum;
-	r_lightlist_t *rlight;
+		// check TOP TEXTURE
+		if (!bothceilingssky // never draw the top texture if on
+			&& (worldhigh < worldtop
+#ifdef ESLOPE
+				|| worldhighslope < worldtopslope
+#endif
+			))
+		{
+			fixed_t texheight;
+			// top texture
+			if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM))
+				&& linedef->sidenum[1] != 0xffff)
+			{
+				// Special case... use offsets from 2nd side but only if it has a texture.
+				side_t *def = &sides[linedef->sidenum[1]];
+				toptexture = R_GetTextureNum(def->toptexture);
 
-	ffloor_t *pfloor = rw.pfloor;
-	fixed_t bottombounds = viewheight << FRACBITS;
-	fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS;
+				if (!toptexture) //Second side has no texture, use the first side's instead.
+					toptexture = R_GetTextureNum(sidedef->toptexture);
+				texheight = textureheight[toptexture];
+			}
+			else
+			{
+				toptexture = R_GetTextureNum(sidedef->toptexture);
+				texheight = textureheight[toptexture];
+			}
+#ifdef ESLOPE
+			if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
+				if (linedef->flags & ML_DONTPEGTOP)
+					rw_toptexturemid = frontsector->ceilingheight - viewz;
+				else
+					rw_toptexturemid = backsector->ceilingheight - viewz;
+			} else
+#endif
+			if (linedef->flags & ML_DONTPEGTOP)
+			{
+				// top of texture at top
+				rw_toptexturemid = worldtop;
+#ifdef ESLOPE
+				rw_toptextureslide = ceilingfrontslide;
+#endif
+			}
+			else
+			{
+#ifdef ESLOPE
+				rw_toptexturemid = worldhigh + texheight;
+				rw_toptextureslide = ceilingbackslide;
+#else
+				vtop = backsector->ceilingheight + texheight;
+				// bottom of texture
+				rw_toptexturemid = vtop - viewz;
+#endif
+			}
+		}
+		// check BOTTOM TEXTURE
+		if (!bothfloorssky // never draw the bottom texture if on
+			&& (worldlow > worldbottom
+#ifdef ESLOPE
+				|| worldlowslope > worldbottomslope
+#endif
+			))     //seulement si VISIBLE!!!
+		{
+			// bottom texture
+			bottomtexture = R_GetTextureNum(sidedef->bottomtexture);
 
 #ifdef ESLOPE
-	INT32 oldx = -1;
+			if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
+				if (linedef->flags & ML_DONTPEGBOTTOM)
+					rw_bottomtexturemid = frontsector->floorheight - viewz;
+				else
+					rw_bottomtexturemid = backsector->floorheight - viewz;
+			} else
+#endif
+			if (linedef->flags & ML_DONTPEGBOTTOM)
+			{
+				// bottom of texture at bottom
+				// top of texture at top
+				rw_bottomtexturemid = worldbottom;
+#ifdef ESLOPE
+				rw_bottomtextureslide = floorfrontslide;
+#endif
+			}
+			else {   // top of texture at top
+				rw_bottomtexturemid = worldlow;
+#ifdef ESLOPE
+				rw_bottomtextureslide = floorbackslide;
 #endif
+			}
+		}
 
-	for (dc_x = rw.x; dc_x <= rw.stopx; dc_x++)
-	{
-		if (maskedtexturecol[dc_x] != INT16_MAX)
+		rw_toptexturemid += sidedef->rowoffset;
+		rw_bottomtexturemid += sidedef->rowoffset;
+
+		// allocate space for masked texture tables
+		if (frontsector && backsector && frontsector->tag != backsector->tag && (backsector->ffloors || frontsector->ffloors))
 		{
+			ffloor_t *rover;
+			ffloor_t *r2;
+			fixed_t   lowcut, highcut;
 #ifdef ESLOPE
-			if (rw.ffloortextureslide) { // skew FOF walls
-				if (oldx != -1)
-					dc_texturemid += FixedMul(rw.ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])<<FRACBITS);
-				oldx = dc_x;
-			}
+			fixed_t lowcutslope, highcutslope;
+
+			// Used for height comparisons and etc across FOFs and slopes
+			fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2;
 #endif
-			// Calculate bounds
-			// clamp the values if necessary to avoid overflows and rendering glitches caused by them
-#ifdef ESLOPE
-			#define CLAMPMAX INT32_MAX
-			#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out.
-			if      (rw.top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX;
-			else if (rw.top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)rw.top_frac;
-			else                                 sprtopscreen = windowtop = CLAMPMIN;
-			if      (rw.bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX;
-			else if (rw.bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)rw.bottom_frac;
-			else                                    sprbotscreen = windowbottom = CLAMPMIN;
 
-			rw.top_frac += rw.top_step;
-			rw.bottom_frac += rw.bottom_step;
-#else
-			sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale));
-			sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen;
+			//markceiling = markfloor = true;
+			maskedtexture = true;
+
+			ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x;
+			lastopening += rw_stopx - rw_x;
+
+			lowcut = max(worldbottom, worldlow) + viewz;
+			highcut = min(worldtop, worldhigh) + viewz;
+#ifdef ESLOPE
+			lowcutslope = max(worldbottomslope, worldlowslope) + viewz;
+			highcutslope = min(worldtopslope, worldhighslope) + viewz;
 #endif
 
-			// SoM: If column is out of range, why bother with it??
-			if (windowbottom < topbounds || windowtop > bottombounds)
+			if (frontsector->ffloors && backsector->ffloors)
 			{
-				if (dc_numlights)
+				i = 0;
+				for (rover = backsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next)
 				{
-					for (i = 0; i < dc_numlights; i++)
-					{
-						rlight = &dc_lightlist[i];
-						rlight->height += rlight->heightstep;
-						if (rlight->flags & FF_CUTLEVEL)
-							rlight->botheight += rlight->botheightstep;
-					}
-				}
-				spryscale += rw.scalestep;
-				continue;
-			}
+					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS))
+						continue;
+					if (rover->flags & FF_INVERTSIDES)
+						continue;
 
-			dc_iscale = 0xffffffffu / (unsigned)spryscale;
+					if (rover->norender == leveltime)
+						continue;
 
-			// Get data for the column
-			col = (column_t *)((UINT8 *)R_GetColumn(rw.texnum,maskedtexturecol[dc_x]) - 3);
+#ifdef ESLOPE
+					SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight)
+					SLOPEPARAMS(*rover->b_slope, low1,  lowslope1,  *rover->bottomheight)
 
-			// SoM: New code does not rely on R_DrawColumnShadowed_8 which
-			// will (hopefully) put less strain on the stack.
-			if (dc_numlights)
-			{
-				lighttable_t **xwalllights;
-				fixed_t height;
-				fixed_t bheight = 0;
-				INT32 solid = 0;
-				INT32 lighteffect = 0;
+					if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
+						continue;
+#else
+					if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
+						continue;
+#endif
 
-				for (i = 0; i < dc_numlights; i++)
-				{
-					// Check if the current light effects the colormap/lightlevel
-					rlight = &dc_lightlist[i];
-					lighteffect = !(dc_lightlist[i].flags & FF_NOSHADE);
-					if (lighteffect)
+					for (r2 = frontsector->ffloors; r2; r2 = r2->next)
 					{
-						lightnum = rlight->lightnum;
-
-						if (lightnum < 0)
-							xwalllights = scalelight[0];
-						else if (lightnum >= LIGHTLEVELS)
-							xwalllights = scalelight[LIGHTLEVELS-1];
-						else
-							xwalllights = scalelight[lightnum];
-
-						pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
+						if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
+							continue;
 
-						if (pindex >= MAXLIGHTSCALE)
-							pindex = MAXLIGHTSCALE-1;
+						if (r2->norender == leveltime)
+							continue;
 
-						if (pfloor->flags & FF_FOG)
+						if (rover->flags & FF_EXTRA)
 						{
-							if (pfloor->master->frontsector->extra_colormap)
-								rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
-							else
-								rlight->rcolormap = xwalllights[pindex];
+							if (!(r2->flags & FF_CUTEXTRA))
+								continue;
+
+							if (r2->flags & FF_EXTRA && (r2->flags & (FF_TRANSLUCENT|FF_FOG)) != (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
+								continue;
 						}
 						else
 						{
-							if (rlight->extra_colormap)
-								rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
-							else
-								rlight->rcolormap = xwalllights[pindex];
+							if (!(r2->flags & FF_CUTSOLIDS))
+								continue;
 						}
+
+#ifdef ESLOPE
+						SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight)
+						SLOPEPARAMS(*r2->b_slope, low2,  lowslope2,  *r2->bottomheight)
+
+						if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope))
+							continue;
+						if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2))
+							continue;
+#else
+						if (*r2->topheight < lowcut || *r2->bottomheight > highcut)
+							continue;
+						if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
+							continue;
+#endif
+
+						break;
 					}
+					if (r2)
+						continue;
 
-					solid = 0; // don't carry over solid-cutting flag from the previous light
+					ds_p->thicksides[i] = rover;
+					i++;
+				}
 
-					// Check if the current light can cut the current 3D floor.
-					if (rlight->flags & FF_CUTSOLIDS && !(pfloor->flags & FF_EXTRA))
-						solid = 1;
-					else if (rlight->flags & FF_CUTEXTRA && pfloor->flags & FF_EXTRA)
+				for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next)
+				{
+					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS))
+						continue;
+					if (!(rover->flags & FF_ALLSIDES))
+						continue;
+
+					if (rover->norender == leveltime)
+						continue;
+
+#ifdef ESLOPE
+					SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight)
+					SLOPEPARAMS(*rover->b_slope, low1,  lowslope1,  *rover->bottomheight)
+
+					if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
+						continue;
+#else
+					if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
+						continue;
+#endif
+
+					for (r2 = backsector->ffloors; r2; r2 = r2->next)
 					{
-						if (rlight->flags & FF_EXTRA)
+						if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
+							continue;
+
+						if (r2->norender == leveltime)
+							continue;
+
+						if (rover->flags & FF_EXTRA)
 						{
-							// The light is from an extra 3D floor... Check the flags so
-							// there are no undesired cuts.
-							if ((rlight->flags & (FF_FOG|FF_SWIMMABLE)) == (pfloor->flags & (FF_FOG|FF_SWIMMABLE)))
-								solid = 1;
+							if (!(r2->flags & FF_CUTEXTRA))
+								continue;
+
+							if (r2->flags & FF_EXTRA && (r2->flags & (FF_TRANSLUCENT|FF_FOG)) != (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
+								continue;
 						}
 						else
-							solid = 1;
-					}
-					else
-						solid = 0;
+						{
+							if (!(r2->flags & FF_CUTSOLIDS))
+								continue;
+						}
 
-					height = rlight->height;
-					rlight->height += rlight->heightstep;
+#ifdef ESLOPE
+						SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight)
+						SLOPEPARAMS(*r2->b_slope, low2,  lowslope2,  *r2->bottomheight)
+#undef SLOPEPARAMS
+						if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope))
+							continue;
+						if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2))
+							continue;
+#else
+						if (*r2->topheight < lowcut || *r2->bottomheight > highcut)
+							continue;
+						if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
+							continue;
+#endif
 
-					if (solid)
-					{
-						bheight = rlight->botheight - (FRACUNIT >> 1);
-						rlight->botheight += rlight->botheightstep;
+						break;
 					}
+					if (r2)
+						continue;
 
-					if (height <= windowtop)
-					{
-						if (lighteffect)
-							dc_colormap = rlight->rcolormap;
-						if (solid && windowtop < bheight)
-							windowtop = bheight;
+					ds_p->thicksides[i] = rover;
+					i++;
+				}
+			}
+			else if (backsector->ffloors)
+			{
+				for (rover = backsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next)
+				{
+					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || rover->flags & FF_INVERTSIDES)
+						continue;
+					if (rover->norender == leveltime)
 						continue;
-					}
 
-					windowbottom = height;
-					if (windowbottom >= sprbotscreen)
-					{
-						windowbottom = sprbotscreen;
-						// draw the texture
-						rw.colfunc_2s (col);
-						for (i++; i < dc_numlights; i++)
-						{
-							rlight = &dc_lightlist[i];
-							rlight->height += rlight->heightstep;
-							if (rlight->flags & FF_CUTLEVEL)
-								rlight->botheight += rlight->botheightstep;
-						}
+#ifdef ESLOPE
+					// Oy vey.
+					if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz
+							&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz)
+							||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz
+							&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz))
 						continue;
-					}
-					// draw the texture
-					rw.colfunc_2s (col);
-					if (solid)
-						windowtop = bheight;
-					else
-						windowtop = windowbottom + 1;
-					if (lighteffect)
-						dc_colormap = rlight->rcolormap;
+#else
+					if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight)
+						continue;
+#endif
+
+					ds_p->thicksides[i] = rover;
+					i++;
 				}
-				windowbottom = sprbotscreen;
-				// draw the texture, if there is any space left
-				if (windowtop < windowbottom)
-					rw.colfunc_2s (col);
+			}
+			else if (frontsector->ffloors)
+			{
+				for (rover = frontsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next)
+				{
+					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_ALLSIDES))
+						continue;
+					if (rover->norender == leveltime)
+						continue;
+#ifdef ESLOPE
+					// Oy vey.
+					if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz
+							&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz)
+							||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz
+							&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz))
+						continue;
+
+					if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldlow+viewz
+							&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldlowslope+viewz)
+							||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldhigh+viewz
+							&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldhighslope+viewz))
+						continue;
+#else
+					if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight)
+						continue;
+					if (*rover->topheight <= backsector->floorheight || *rover->bottomheight >= backsector->ceilingheight)
+						continue;
+#endif
+
+					ds_p->thicksides[i] = rover;
+					i++;
+				}
+			}
+
+			ds_p->numthicksides = numthicksides = i;
+		}
+		if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures)
+		{
+			// masked midtexture
+			if (!ds_p->thicksidecol)
+			{
+				ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
+				lastopening += rw_stopx - rw_x;
+			}
+			else
+				ds_p->maskedtexturecol = ds_p->thicksidecol;
+
+#ifdef ESLOPE
+			maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0])
+
+#ifdef POLYOBJECTS
+			if (curline->polyseg) { // use REAL front and back floors please, so midtexture rendering isn't mucked up
+				rw_midtextureslide = rw_midtexturebackslide = 0;
+				if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3))
+					rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz;
+				else
+					rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz;
+			} else
+#endif
+			// Set midtexture starting height
+			if (linedef->flags & ML_EFFECT2) { // Ignore slopes when texturing
+				rw_midtextureslide = rw_midtexturebackslide = 0;
+				if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3))
+					rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz;
+				else
+					rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz;
+
+			} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
+				rw_midtexturemid = worldbottom;
+				rw_midtextureslide = floorfrontslide;
+				rw_midtextureback = worldlow;
+				rw_midtexturebackslide = floorbackslide;
+			} else {
+				rw_midtexturemid = worldtop;
+				rw_midtextureslide = ceilingfrontslide;
+				rw_midtextureback = worldhigh;
+				rw_midtexturebackslide = ceilingbackslide;
+			}
+			rw_midtexturemid += sidedef->rowoffset;
+			rw_midtextureback += sidedef->rowoffset;
+#endif
+
+			maskedtexture = true;
+		}
+	}
+
+	// calculate rw_offset (only needed for textured lines)
+	segtextured = midtexture || toptexture || bottomtexture || maskedtexture || (numthicksides > 0);
+
+	if (segtextured)
+	{
+		offsetangle = rw_normalangle-rw_angle1;
+
+		if (offsetangle > ANGLE_180)
+			offsetangle = -(signed)offsetangle;
+
+		if (offsetangle > ANGLE_90)
+			offsetangle = ANGLE_90;
+
+		sineval = FINESINE(offsetangle>>ANGLETOFINESHIFT);
+		rw_offset = FixedMul(hyp, sineval);
+
+		// big room fix
+		if (longboi)
+		{
+			INT64 dx = (curline->v2->x)-(curline->v1->x);
+			INT64 dy = (curline->v2->y)-(curline->v1->y);
+			INT64 vdx = viewx-(curline->v1->x);
+			INT64 vdy = viewy-(curline->v1->y);
+			rw_offset = ((dx*vdx-dy*vdy))/(curline->length);
+		}
+
+		if (rw_normalangle-rw_angle1 < ANGLE_180)
+			rw_offset = -rw_offset;
+
+		/// don't use texture offset for splats
+		rw_offset2 = rw_offset + curline->offset;
+		rw_offset += sidedef->textureoffset + curline->offset;
+		rw_centerangle = ANGLE_90 + viewangle - rw_normalangle;
+
+		// calculate light table
+		//  use different light tables
+		//  for horizontal / vertical / diagonal
+		// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
+		lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
+
+		if (curline->v1->y == curline->v2->y)
+			lightnum--;
+		else if (curline->v1->x == curline->v2->x)
+			lightnum++;
+
+		if (lightnum < 0)
+			walllights = scalelight[0];
+		else if (lightnum >= LIGHTLEVELS)
+			walllights = scalelight[LIGHTLEVELS - 1];
+		else
+			walllights = scalelight[lightnum];
+	}
 
-				spryscale += rw.scalestep;
-				continue;
-			}
+	// if a floor / ceiling plane is on the wrong side
+	//  of the view plane, it is definitely invisible
+	//  and doesn't need to be marked.
+	if (frontsector->heightsec == -1)
+	{
+		if (frontsector->floorpic != skyflatnum
+		&& (
+#ifdef ESLOPE
+			frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) :
+#endif
+			frontsector->floorheight) >= viewz)
+		{
+			// above view plane
+			markfloor = false;
+		}
 
-			// calculate lighting
-			pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
+		if (frontsector->ceilingpic != skyflatnum
+		&& (
+#ifdef ESLOPE
+			frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) :
+#endif
+			frontsector->ceilingheight) <= viewz)
+		{
+			// below view plane
+			markceiling = false;
+		}
+	}
 
-			if (pindex >= MAXLIGHTSCALE)
-				pindex = MAXLIGHTSCALE - 1;
+	// calculate incremental stepping values for texture edges
+	worldtop >>= 4;
+	worldbottom >>= 4;
+#ifdef ESLOPE
+	worldtopslope >>= 4;
+	worldbottomslope >>= 4;
+#endif
 
-			dc_colormap = walllights[pindex];
+	if (linedef->special == HORIZONSPECIAL) { // HORIZON LINES
+		topstep = bottomstep = 0;
+		topfrac = bottomfrac = (centeryfrac>>4);
+		topfrac++; // Prevent 1px HOM
+	} else {
+		topstep = -FixedMul (rw_scalestep, worldtop);
+		topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
 
-			if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap)
-				dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
-			else if (frontsector->extra_colormap)
-				dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
+		bottomstep = -FixedMul (rw_scalestep,worldbottom);
+		bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
 
-			// draw the texture
-			rw.colfunc_2s (col);
-			spryscale += rw.scalestep;
+#ifdef ESLOPE
+		if (frontsector->c_slope) {
+			fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldtopslope, ds_p->scale2);
+			topstep = (topfracend-topfrac)/(range);
+		}
+		if (frontsector->f_slope) {
+			fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldbottomslope, ds_p->scale2);
+			bottomstep = (bottomfracend-bottomfrac)/(range);
 		}
+#endif
 	}
-}
-
-//
-// R_ThickLightLists
-// Creates light lists, but for thick sides.
-//
-static void R_ThickLightLists(drawseg_t *ds, INT32 range)
-{
-	INT32 lightnum;
-	sector_t tempsec;
-	INT32 templight;
-	INT32 i, p;
-
-	lightlist_t *light;
-	r_lightlist_t *rlight;
-	ffloor_t *pfloor = rw.pfloor;
 
 	dc_numlights = 0;
 
 	if (frontsector->numlights)
 	{
 		dc_numlights = frontsector->numlights;
-		if (dc_numlights > dc_maxlights)
+		if (dc_numlights >= dc_maxlights)
 		{
 			dc_maxlights = dc_numlights;
 			dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL);
@@ -3130,364 +2734,491 @@ static void R_ThickLightLists(drawseg_t *ds, INT32 range)
 		{
 #ifdef ESLOPE
 			fixed_t leftheight, rightheight;
-			fixed_t pfloorleft, pfloorright;
-			INT64 overflow_test;
-#else
-			(void)range;
 #endif
+
 			light = &frontsector->lightlist[i];
 			rlight = &dc_lightlist[p];
-#ifdef ESLOPE
 
-#define SLOPEPARAMS(slope, end1, end2, normalheight) \
-	if (slope) { \
-		end1 = P_GetZAt(slope, ds->leftpos.x, ds->leftpos.y); \
-		end2 = P_GetZAt(slope, ds->rightpos.x, ds->rightpos.y); \
-	} else \
-		end1 = end2 = normalheight;
+#ifdef ESLOPE
+			if (light->slope) {
+				leftheight = P_GetZAt(light->slope, segleft.x, segleft.y);
+				rightheight = P_GetZAt(light->slope, segright.x, segright.y);
 
-			SLOPEPARAMS(light->slope,     leftheight, rightheight, light->height)
-			SLOPEPARAMS(*pfloor->b_slope, pfloorleft, pfloorright, *pfloor->bottomheight)
+				// Flag sector as having slopes
+				frontsector->hasslope = true;
+			} else
+				leftheight = rightheight = light->height;
 
-			if (leftheight < pfloorleft && rightheight < pfloorright)
-				continue;
+			leftheight -= viewz;
+			rightheight -= viewz;
 
-			SLOPEPARAMS(*pfloor->t_slope, pfloorleft, pfloorright, *pfloor->topheight)
+			leftheight >>= 4;
+			rightheight >>= 4;
+#endif
 
-			if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights)
+			if (i != 0)
 			{
-				lightlist_t *nextlight = &frontsector->lightlist[i+1];
-				if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft
-				 && (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright)
+#ifdef ESLOPE
+				if (leftheight < worldbottom && rightheight < worldbottomslope)
 					continue;
-			}
 
-			leftheight -= viewz;
-			rightheight -= viewz;
+				if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
+					continue;
+#else
+				if (light->height < frontsector->floorheight)
+					continue;
 
-			// Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave.
-			overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS);
-			if      (overflow_test > (INT64)CLAMPMAX) rlight->height = CLAMPMAX;
-			else if (overflow_test > (INT64)CLAMPMIN) rlight->height = (fixed_t)overflow_test;
-			else                                      rlight->height = CLAMPMIN;
+				if (light->height > frontsector->ceilingheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
+					continue;
+#endif
+			}
 
-			overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS);
-			if      (overflow_test > (INT64)CLAMPMAX) rlight->heightstep = CLAMPMAX;
-			else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test;
-			else                                      rlight->heightstep = CLAMPMIN;
+#ifdef ESLOPE
+			rlight->height = (centeryfrac>>4) - FixedMul(leftheight, rw_scale);
+			rlight->heightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
 			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
 #else
-			if (light->height < *pfloor->bottomheight)
-				continue;
-
-			if (light->height > *pfloor->topheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > *pfloor->topheight)
-				continue;
-
-			lheight = light->height;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : light->height;
-			rlight->heightstep = -FixedMul (rw.scalestep, (lheight - viewz));
-			rlight->height = (centeryfrac) - FixedMul((lheight - viewz), spryscale);
+			rlight->height = (centeryfrac>>4) - FixedMul((light->height - viewz) >> 4, rw_scale);
+			rlight->heightstep = -FixedMul (rw_scalestep, (light->height - viewz) >> 4);
 #endif
 			rlight->flags = light->flags;
-			if (light->flags & FF_CUTLEVEL)
+
+			if (light->caster && light->caster->flags & FF_CUTSOLIDS)
 			{
 #ifdef ESLOPE
-				SLOPEPARAMS(*light->caster->b_slope, leftheight, rightheight, *light->caster->bottomheight)
-#undef SLOPEPARAMS
+				if (*light->caster->b_slope) {
+					leftheight = P_GetZAt(*light->caster->b_slope, segleft.x, segleft.y);
+					rightheight = P_GetZAt(*light->caster->b_slope, segright.x, segright.y);
+
+					// Flag sector as having slopes
+					frontsector->hasslope = true;
+				} else
+					leftheight = rightheight = *light->caster->bottomheight;
+
 				leftheight -= viewz;
 				rightheight -= viewz;
 
-				// Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave.
-				overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS);
-				if      (overflow_test > (INT64)CLAMPMAX) rlight->botheight = CLAMPMAX;
-				else if (overflow_test > (INT64)CLAMPMIN) rlight->botheight = (fixed_t)overflow_test;
-				else                                      rlight->botheight = CLAMPMIN;
+				leftheight >>= 4;
+				rightheight >>= 4;
 
-				overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS);
-				if      (overflow_test > (INT64)CLAMPMAX) rlight->botheightstep = CLAMPMAX;
-				else if (overflow_test > (INT64)CLAMPMIN) rlight->botheightstep = (fixed_t)overflow_test;
-				else                                      rlight->botheightstep = CLAMPMIN;
+				rlight->botheight = (centeryfrac>>4) - FixedMul(leftheight, rw_scale);
+				rlight->botheightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
 				rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range);
+
 #else
-				lheight = *light->caster->bottomheight;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : *light->caster->bottomheight;
-				rlight->botheightstep = -FixedMul (rw.scalestep, (lheight - viewz));
-				rlight->botheight = (centeryfrac) - FixedMul((lheight - viewz), spryscale);
+				rlight->botheight = (centeryfrac >> 4) - FixedMul((*light->caster->bottomheight - viewz) >> 4, rw_scale);
+				rlight->botheightstep = -FixedMul (rw_scalestep, (*light->caster->bottomheight - viewz) >> 4);
 #endif
 			}
 
 			rlight->lightlevel = *light->lightlevel;
 			rlight->extra_colormap = *light->extra_colormap;
-
-			// Check if the current light effects the colormap/lightlevel
-			if (pfloor->flags & FF_FOG)
-				rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
-			else
-				rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
-
-			if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
-				;
-			else if (curline->v1->y == curline->v2->y)
-				rlight->lightnum--;
-			else if (curline->v1->x == curline->v2->x)
-				rlight->lightnum++;
-
 			p++;
 		}
 
 		dc_numlights = p;
 	}
-	else
+
+	if (numffloors)
 	{
-		// Get correct light level!
-		if ((frontsector->extra_colormap && frontsector->extra_colormap->fog))
-			lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
-		else if (pfloor->flags & FF_FOG)
-			lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
-		else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
-			lightnum = LIGHTLEVELS-1;
-		else
-			lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)
-				->lightlevel >> LIGHTSEGSHIFT;
+		for (i = 0; i < numffloors; i++)
+		{
+			ffloor[i].f_pos >>= 4;
+#ifdef ESLOPE
+			ffloor[i].f_pos_slope >>= 4;
+#endif
+			if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too.
+			{
+				ffloor[i].f_step = 0;
+				ffloor[i].f_frac = (centeryfrac>>4);
+				topfrac++; // Prevent 1px HOM
+			}
+			else
+			{
+#ifdef ESLOPE
+				ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale);
+				ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(range);
+#else
+				ffloor[i].f_step = FixedMul(-rw_scalestep, ffloor[i].f_pos);
+				ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale);
+#endif
+			}
+		}
+	}
 
-		if (pfloor->flags & FF_FOG || (frontsector->extra_colormap && frontsector->extra_colormap->fog));
-			else if (curline->v1->y == curline->v2->y)
-		lightnum--;
-		else if (curline->v1->x == curline->v2->x)
-			lightnum++;
+	if (backsector)
+	{
+		worldhigh >>= 4;
+		worldlow >>= 4;
+#ifdef ESLOPE
+		worldhighslope >>= 4;
+		worldlowslope >>= 4;
+#endif
+
+		if (toptexture)
+		{
+			pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
+			pixhighstep = -FixedMul (rw_scalestep,worldhigh);
+
+#ifdef ESLOPE
+			if (backsector->c_slope) {
+				fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2);
+				pixhighstep = (topfracend-pixhigh)/(range);
+			}
+#endif
+		}
+
+		if (bottomtexture)
+		{
+			pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
+			pixlowstep = -FixedMul (rw_scalestep,worldlow);
+#ifdef ESLOPE
+			if (backsector->f_slope) {
+				fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldlowslope, ds_p->scale2);
+				pixlowstep = (bottomfracend-pixlow)/(range);
+			}
+#endif
+		}
+
+		{
+			ffloor_t * rover;
+#ifdef ESLOPE
+			fixed_t roverleft, roverright;
+			fixed_t planevistest;
+#endif
+			i = 0;
+
+			if (backsector->ffloors)
+			{
+				for (rover = backsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next)
+				{
+					if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES))
+						continue;
+					if (rover->norender == leveltime)
+						continue;
+
+#ifdef ESLOPE
+					// Let the renderer know this sector is sloped.
+					if (*rover->b_slope || *rover->t_slope)
+						backsector->hasslope = true;
+
+					roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
+					roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
+					planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
+
+					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
+					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
+					    ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz > planevistest && (rover->flags & FF_BOTHPLANES))))
+					{
+						//ffloor[i].slope = *rover->b_slope;
+						ffloor[i].b_pos = roverleft;
+						ffloor[i].b_pos_slope = roverright;
+						ffloor[i].b_pos >>= 4;
+						ffloor[i].b_pos_slope >>= 4;
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
+						i++;
+					}
+
+					if (i >= MAXFFLOORS)
+						break;
+
+					roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
+					roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
+					planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
+
+					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
+					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
+					    ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz < planevistest && (rover->flags & FF_BOTHPLANES))))
+					{
+						//ffloor[i].slope = *rover->t_slope;
+						ffloor[i].b_pos = roverleft;
+						ffloor[i].b_pos_slope = roverright;
+						ffloor[i].b_pos >>= 4;
+						ffloor[i].b_pos_slope >>= 4;
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
+						i++;
+					}
+#else
+					if (*rover->bottomheight <= backsector->ceilingheight &&
+					    *rover->bottomheight >= backsector->floorheight &&
+					    ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES))))
+					{
+						ffloor[i].b_pos = *rover->bottomheight;
+						ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
+						ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						i++;
+					}
+
+					if (i >= MAXFFLOORS)
+						break;
+
+					if (*rover->topheight >= backsector->floorheight &&
+					    *rover->topheight <= backsector->ceilingheight &&
+					    ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES))))
+					{
+						ffloor[i].b_pos = *rover->topheight;
+						ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
+						ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						i++;
+					}
+#endif
+				}
+			}
+			else if (frontsector && frontsector->ffloors)
+			{
+				for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next)
+				{
+					if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES))
+						continue;
+					if (rover->norender == leveltime)
+						continue;
 
-		if (lightnum < 0)
-			walllights = scalelight[0];
-		else if (lightnum >= LIGHTLEVELS)
-			walllights = scalelight[LIGHTLEVELS-1];
-		else
-			walllights = scalelight[lightnum];
-	}
-}
 
-//
-// R_ThickStepping
-// Set stepping values for thick sides.
-//
 #ifdef ESLOPE
-static void R_ThickStepping(drawseg_t *ds, INT32 range)
-{
-	fixed_t right_top, right_bottom;
-	ffloor_t *pfloor = rw.pfloor;
+					// Let the renderer know this sector is sloped.
+					if (*rover->b_slope || *rover->t_slope)
+						frontsector->hasslope = true;
 
-	// calculate right ends now
-	if (*pfloor->t_slope)
-		right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
-	else
-		right_top = *pfloor->topheight - viewz;
+					roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
+					roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
+					planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
 
-	if (*pfloor->b_slope)
-		right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
-	else
-		right_bottom = *pfloor->bottomheight - viewz;
+					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
+					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
+					    ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz > planevistest && (rover->flags & FF_BOTHPLANES))))
+					{
+						//ffloor[i].slope = *rover->b_slope;
+						ffloor[i].b_pos = roverleft;
+						ffloor[i].b_pos_slope = roverright;
+						ffloor[i].b_pos >>= 4;
+						ffloor[i].b_pos_slope >>= 4;
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
+						i++;
+					}
 
-	// using INT64 to avoid 32bit overflow
-	rw.top_frac =    (INT64)centeryfrac - (((INT64)rw.left_top     * ds->scale1) >> FRACBITS);
-	rw.bottom_frac = (INT64)centeryfrac - (((INT64)rw.left_bottom  * ds->scale1) >> FRACBITS);
-	rw.top_step =    (INT64)centeryfrac - (((INT64)right_top       * ds->scale2) >> FRACBITS);
-	rw.bottom_step = (INT64)centeryfrac - (((INT64)right_bottom    * ds->scale2) >> FRACBITS);
+					if (i >= MAXFFLOORS)
+						break;
 
-	rw.top_step = (rw.top_step-rw.top_frac)/(range);
-	rw.bottom_step = (rw.bottom_step-rw.bottom_frac)/(range);
+					roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
+					roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
+					planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
 
-	rw.top_frac += rw.top_step * (rw.x - ds->x1);
-	rw.bottom_frac += rw.bottom_step * (rw.x - ds->x1);
-}
+					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
+					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
+					    ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz < planevistest && (rover->flags & FF_BOTHPLANES))))
+					{
+						//ffloor[i].slope = *rover->t_slope;
+						ffloor[i].b_pos = roverleft;
+						ffloor[i].b_pos_slope = roverright;
+						ffloor[i].b_pos >>= 4;
+						ffloor[i].b_pos_slope >>= 4;
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
+						i++;
+					}
+#else
+					if (*rover->bottomheight <= frontsector->ceilingheight &&
+					    *rover->bottomheight >= frontsector->floorheight &&
+					    ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES))))
+					{
+						ffloor[i].b_pos = *rover->bottomheight;
+						ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
+						ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						i++;
+					}
+					if (i >= MAXFFLOORS)
+						break;
+					if (*rover->topheight >= frontsector->floorheight &&
+					    *rover->topheight <= frontsector->ceilingheight &&
+					    ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES))))
+					{
+						ffloor[i].b_pos = *rover->topheight;
+						ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
+						ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						i++;
+					}
 #endif
+				}
+			}
+#ifdef POLYOBJECTS_PLANES
+			if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES))
+			{
+				while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++;
+				if (i < numffloors && backsector->floorheight <= frontsector->ceilingheight &&
+					backsector->floorheight >= frontsector->floorheight &&
+					(viewz < backsector->floorheight))
+				{
+					if (ffloor[i].plane->minx > ds_p->x1)
+						ffloor[i].plane->minx = ds_p->x1;
 
-//
-// R_RenderThickSideRange
-// Renders all the thick sides in the given range.
-//
-void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
-{
-	INT32 texnum;
+					if (ffloor[i].plane->maxx < ds_p->x2)
+						ffloor[i].plane->maxx = ds_p->x2;
 
-	fixed_t         offsetvalue = 0;
-	INT32           range;
-#ifndef ESLOPE
-	fixed_t         lheight;
-#endif
-	line_t          *newline = NULL;
 #ifdef ESLOPE
-	// skew FOF walls with slopes?
-	boolean	      slopeskew = false;
-	pslope_t      *skewslope = NULL;
+					ffloor[i].slope = NULL;
 #endif
+					ffloor[i].b_pos = backsector->floorheight;
+					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
+					ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
+					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+					i++;
+				}
+				if (i < numffloors && backsector->ceilingheight >= frontsector->floorheight &&
+					backsector->ceilingheight <= frontsector->ceilingheight &&
+					(viewz > backsector->ceilingheight))
+				{
+					if (ffloor[i].plane->minx > ds_p->x1)
+						ffloor[i].plane->minx = ds_p->x1;
 
-	rw.x = x1;
-	rw.stopx = x2;
-	rw.pfloor = pfloor;
-
-	// Calculate light table.
-	// Use different light tables
-	//   for horizontal / vertical / diagonal. Diagonal?
-	// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
+					if (ffloor[i].plane->maxx < ds_p->x2)
+						ffloor[i].plane->maxx = ds_p->x2;
 
-	curline = ds->curline;
-	backsector = pfloor->target;
-	frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
-	texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture);
+#ifdef ESLOPE
+					ffloor[i].slope = NULL;
+#endif
+					ffloor[i].b_pos = backsector->ceilingheight;
+					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
+					ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
+					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+					i++;
+				}
+			}
+#endif
 
-	colfunc = colfuncs[BASEDRAWFUNC];
+			numbackffloors = i;
+		}
+	}
 
-	if (pfloor->master->flags & ML_TFERLINE)
+	// get a new or use the same visplane
+	if (markceiling)
 	{
-		size_t linenum = curline->linedef-backsector->lines[0];
-		newline = pfloor->master->frontsector->lines[0] + linenum;
-		texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
+		if (ceilingplane) //SoM: 3/29/2000: Check for null ceiling planes
+			ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
+		else
+			markceiling = false;
+
+		// Don't mark ceiling flat lines for polys unless this line has an upper texture, otherwise we get flat leakage pulling downward
+		// (If it DOES have an upper texture and we do this, the ceiling won't render at all)
+		if (curline->polyseg && !curline->sidedef->toptexture)
+			markceiling = false;
 	}
 
-	if (pfloor->flags & FF_TRANSLUCENT)
+	// get a new or use the same visplane
+	if (markfloor)
 	{
-		boolean fuzzy = true;
-
-		// Hacked up support for alpha value in software mode Tails 09-24-2002
-		if (pfloor->alpha < 12)
-			return; // Don't even draw it
-		else if (pfloor->alpha < 38)
-			dc_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT);
-		else if (pfloor->alpha < 64)
-			dc_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT);
-		else if (pfloor->alpha < 89)
-			dc_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT);
-		else if (pfloor->alpha < 115)
-			dc_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT);
-		else if (pfloor->alpha < 140)
-			dc_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
-		else if (pfloor->alpha < 166)
-			dc_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT);
-		else if (pfloor->alpha < 192)
-			dc_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT);
-		else if (pfloor->alpha < 217)
-			dc_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT);
-		else if (pfloor->alpha < 243)
-			dc_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT);
+		if (floorplane) //SoM: 3/29/2000: Check for null planes
+			floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
 		else
-			fuzzy = false; // Opaque
+			markfloor = false;
 
-		if (fuzzy)
-			colfunc = colfuncs[COLDRAWFUNC_FUZZY];
+		// Don't mark floor flat lines for polys unless this line has a lower texture, otherwise we get flat leakage pulling upward
+		// (If it DOES have a lower texture and we do this, the floor won't render at all)
+		if (curline->polyseg && !curline->sidedef->bottomtexture)
+			markfloor = false;
 	}
-	else if (pfloor->flags & FF_FOG)
-		colfunc = colfuncs[COLDRAWFUNC_FOG];
-
-#ifdef ESLOPE
-	range = max(ds->x2-ds->x1, 1);
-#endif
-	//SoM: Moved these up here so they are available for my lightlist calculations
-	rw.scalestep = ds->scalestep;
-	spryscale = ds->scale1 + (x1 - ds->x1)*rw.scalestep;
 
-	R_ThickLightLists(ds, range);
+	ds_p->numffloorplanes = 0;
+	if (numffloors)
+	{
+		if (!firstseg)
+		{
+			ds_p->numffloorplanes = numffloors;
 
-	maskedtexturecol = ds->thicksidecol;
+			for (i = 0; i < numffloors; i++)
+			{
+				ds_p->ffloorplanes[i] = ffloor[i].plane =
+					R_CheckPlane(ffloor[i].plane, rw_x, rw_stopx - 1);
+			}
 
-	mfloorclip = ds->sprbottomclip;
-	mceilingclip = ds->sprtopclip;
-	dc_texheight = textureheight[texnum]>>FRACBITS;
+			firstseg = ds_p;
+		}
+		else
+		{
+			for (i = 0; i < numffloors; i++)
+				R_ExpandPlane(ffloor[i].plane, rw_x, rw_stopx - 1);
+		}
+#ifdef POLYOBJECTS_PLANES
+		// FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red
+		if (curline->polyseg)
+		{
+			for (i = 0; i < numffloors; i++)
+			{
+				if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)
+					continue;
+				if (ffloor[i].plane->minx > rw_x)
+					ffloor[i].plane->minx = rw_x;
 
-#ifdef ESLOPE
-	// calculate both left ends
-	if (*pfloor->t_slope)
-		rw.left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
-	else
-		rw.left_top = *pfloor->topheight - viewz;
+				if (ffloor[i].plane->maxx < rw_stopx - 1)
+					ffloor[i].plane->maxx = rw_stopx - 1;
+			}
+		}
+#endif
+	}
 
-	if (*pfloor->b_slope)
-		rw.left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
-	else
-		rw.left_bottom = *pfloor->bottomheight - viewz;
-	skewslope = *pfloor->t_slope; // skew using top slope by default
-	if (newline)
+#ifdef WALLSPLATS
+	if (linedef->splats && cv_splats.value)
 	{
-		if (newline->flags & ML_DONTPEGTOP)
-			slopeskew = true;
+		// Isn't a bit wasteful to copy the ENTIRE array for every drawseg?
+		M_Memcpy(last_ceilingclip + ds_p->x1, ceilingclip + ds_p->x1,
+			sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1));
+		M_Memcpy(last_floorclip + ds_p->x1, floorclip + ds_p->x1,
+			sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1));
+		R_RenderSegLoop();
+		R_DrawWallSplats();
 	}
-	else if (pfloor->master->flags & ML_DONTPEGTOP)
-		slopeskew = true;
-
-	if (slopeskew)
-		dc_texturemid = rw.left_top;
 	else
 #endif
-	dc_texturemid = *pfloor->topheight - viewz;
+		R_RenderSegLoop();
+	colfunc = colfuncs[BASEDRAWFUNC];
 
-	if (newline)
-	{
-		offsetvalue = sides[newline->sidenum[0]].rowoffset;
-		if (newline->flags & ML_DONTPEGBOTTOM)
-		{
-#ifdef ESLOPE
-			skewslope = *pfloor->b_slope; // skew using bottom slope
-			if (slopeskew)
-				dc_texturemid = rw.left_bottom;
-			else
-#endif
-			offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
-		}
-	}
+	if (portalline) // if curline is a portal, set portalrender for drawseg
+		ds_p->portalpass = portalrender+1;
 	else
+		ds_p->portalpass = 0;
+
+	// save sprite clipping info
+	if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
 	{
-		offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset;
-		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
-		{
-#ifdef ESLOPE
-			skewslope = *pfloor->b_slope; // skew using bottom slope
-			if (slopeskew)
-				dc_texturemid = rw.left_bottom;
-			else
-#endif
-			offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
-		}
+		M_Memcpy(lastopening, ceilingclip+start, 2*(rw_stopx - start));
+		ds_p->sprtopclip = lastopening - start;
+		lastopening += rw_stopx - start;
 	}
 
-#ifdef ESLOPE
-	if (slopeskew)
+	if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
 	{
-		angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y);
-
-		if (skewslope)
-			rw.ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT));
+		M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx-start));
+		ds_p->sprbottomclip = lastopening - start;
+		lastopening += rw_stopx - start;
 	}
-#endif
-
-	dc_texturemid += offsetvalue;
 
-	// Texture must be cached before setting colfunc_2s,
-	// otherwise texture[texnum]->holes may be false when it shouldn't be
-	R_CheckTextureCache(texnum);
-	//faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
-	//     are not stored per-column with post info anymore in Doom Legacy
-	if (textures[texnum]->holes)
+	if (maskedtexture && !(ds_p->silhouette & SIL_TOP))
 	{
-		if (textures[texnum]->flip & 2) // vertically flipped?
-		{
-			rw.colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
-			rw.column2s_length = textures[texnum]->height;
-		}
-		else
-			rw.colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture
+		ds_p->silhouette |= SIL_TOP;
+		ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX;
 	}
-	else
+	if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM))
 	{
-		rw.colfunc_2s = R_Render2sidedMultiPatchColumn;        //render multipatch with no holes (no post_t info)
-		rw.column2s_length = textures[texnum]->height;
+		ds_p->silhouette |= SIL_BOTTOM;
+		ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN;
 	}
-
-#ifdef ESLOPE
-	// Set heights according to plane, or slope, whichever
-	R_ThickStepping(ds, range);
-#endif
-
-	// draw the columns
-	rw.texnum = texnum;
-	R_RenderThickSegLoop();
-	colfunc = colfuncs[BASEDRAWFUNC];
-
-#undef CLAMPMAX
-#undef CLAMPMIN
+	ds_p++;
 }
diff --git a/src/r_state.h b/src/r_state.h
index 2c5e5fcf7f0d1796c77a451a3e8a768a9129258c..75566923b140adfdffb47a3f64282e3f4ea3a3b5 100644
--- a/src/r_state.h
+++ b/src/r_state.h
@@ -93,41 +93,10 @@ extern angle_t doubleclipangle;
 extern INT32 viewangletox[FINEANGLES/2];
 extern angle_t xtoviewangle[MAXVIDWIDTH+1];
 
-// Wall rendering
-typedef struct
-{
-	INT32 x, stopx;
-	angle_t centerangle;
-	fixed_t offset;
-	fixed_t offset2; // for splats
-	fixed_t scale, scalestep;
-	fixed_t midtexturemid, toptexturemid, bottomtexturemid;
-#ifdef ESLOPE
-	fixed_t toptextureslide, midtextureslide, bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes
-	fixed_t midtextureback, midtexturebackslide; // Values for masked midtexture height calculation
-#endif
-	fixed_t distance;
-	angle_t normalangle;
-	angle_t angle1; // angle to line origin
-
-	// for masked segs and thick sides
-	INT32 texnum;
-	void (*colfunc_2s) (column_t *);
-	INT32 column2s_length; // column->length : for multi-patch on 2sided wall = texture->height
-
-	// masked segs
-	INT32 maskedrepeat;
-
-	// thick sides
-	ffloor_t *pfloor;
-#ifdef ESLOPE
-	// Render FOF sides kinda like normal sides, with the frac and step and everything
-	// NOTE: INT64 instead of fixed_t because overflow concerns
-	INT64 top_frac, top_step, bottom_frac, bottom_step;
-	fixed_t ffloortextureslide;
-	fixed_t left_top, left_bottom; // needed here for slope skewing
-#endif
-} renderwall_t;
-extern renderwall_t rw;
+extern fixed_t rw_distance;
+extern angle_t rw_normalangle;
+
+// angle to line origin
+extern angle_t rw_angle1;
 
 #endif