diff --git a/src/r_segs.c b/src/r_segs.c
index 35750f9dcf780e8e4c89ba7433e7302ea959a39e..d8267ea6fbb03c605b230ce83bb8decf3978c108 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -109,12 +109,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 	fixed_t height, realbot;
 	lightlist_t *light;
 	r_lightlist_t *rlight;
-	void (*colfunc_2s)(column_t *);
+	void (*colfunc_2s)(column_t *, unsigned);
 	line_t *ldef;
 	sector_t *front, *back;
 	INT32 times, repeats;
 	INT64 overflow_test;
 	INT32 range;
+	unsigned lengthcol;
 
 	// Calculate light table.
 	// Use different light tables
@@ -391,7 +392,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 					if (windowbottom >= realbot)
 					{
 						windowbottom = realbot;
-						colfunc_2s(col);
+						colfunc_2s(col, lengthcol);
 						for (i++; i < dc_numlights; i++)
 						{
 							rlight = &dc_lightlist[i];
@@ -400,13 +401,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 
 						continue;
 					}
-					colfunc_2s(col);
+					colfunc_2s(col, lengthcol);
 					windowtop = windowbottom + 1;
 					dc_colormap = rlight->rcolormap;
 				}
 				windowbottom = realbot;
 				if (windowtop < windowbottom)
-					colfunc_2s(col);
+					colfunc_2s(col, lengthcol);
 
 				spryscale += rw_scalestep;
 				continue;
@@ -428,7 +429,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 
 			// draw the texture
 			col = R_GetColumn(texnum, maskedtexturecol[dc_x] >> FRACBITS);
-			colfunc_2s(col);
+			colfunc_2s(col, lengthcol);
 
 			spryscale += rw_scalestep;
 		}
@@ -437,10 +438,10 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 }
 
 // Loop through R_DrawMaskedColumn calls
-static void R_DrawRepeatMaskedColumn(column_t *col)
+static void R_DrawRepeatMaskedColumn(column_t *col, unsigned lengthcol)
 {
 	while (sprtopscreen < sprbotscreen) {
-		R_DrawMaskedColumn(col);
+		R_DrawMaskedColumn(col, lengthcol);
 		if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
 			sprtopscreen = INT32_MAX;
 		else
@@ -448,10 +449,10 @@ static void R_DrawRepeatMaskedColumn(column_t *col)
 	}
 }
 
-static void R_DrawRepeatFlippedMaskedColumn(column_t *col)
+static void R_DrawRepeatFlippedMaskedColumn(column_t *col, unsigned lengthcol)
 {
 	do {
-		R_DrawFlippedMaskedColumn(col);
+		R_DrawFlippedMaskedColumn(col, lengthcol);
 		sprtopscreen += dc_texheight*spryscale;
 	} while (sprtopscreen < sprbotscreen);
 }
@@ -502,8 +503,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	boolean do_texture_skew;
 	INT16 lineflags;
 	fixed_t wall_scalex, wall_scaley;
+	unsigned lengthcol;
 
-	void (*colfunc_2s) (column_t *);
+	void (*colfunc_2s) (column_t *, unsigned);
 
 	// Calculate light table.
 	// Use different light tables
@@ -901,7 +903,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 				{
 					windowbottom = sprbotscreen;
 					// draw the texture
-					colfunc_2s (col);
+					colfunc_2s (col, lengthcol);
 					for (i++; i < dc_numlights; i++)
 					{
 						rlight = &dc_lightlist[i];
@@ -912,7 +914,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 					continue;
 				}
 				// draw the texture
-				colfunc_2s (col);
+				colfunc_2s (col, lengthcol);
 				if (solid)
 					windowtop = bheight;
 				else
@@ -923,7 +925,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 			windowbottom = sprbotscreen;
 			// draw the texture, if there is any space left
 			if (windowtop < windowbottom)
-				colfunc_2s (col);
+				colfunc_2s (col, lengthcol);
 
 			spryscale += rw_scalestep;
 			continue;
@@ -943,7 +945,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 			dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
 
 		// draw the texture
-		colfunc_2s (col);
+		colfunc_2s (col, lengthcol);
 		spryscale += rw_scalestep;
 	}
 	colfunc = colfuncs[BASEDRAWFUNC];
diff --git a/src/r_things.c b/src/r_things.c
index 9bff693dd38040602ef88db1b11febb77014385c..9a34adcba150196a38b981a27609b604ffb73dca 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -634,10 +634,12 @@ INT16 *mceilingclip;
 fixed_t spryscale = 0, sprtopscreen = 0, sprbotscreen = 0;
 fixed_t windowtop = 0, windowbottom = 0;
 
-void R_DrawMaskedColumn(column_t *column)
+void R_DrawMaskedColumn(column_t *column, unsigned lengthcol)
 {
 	fixed_t basetexturemid = dc_texturemid;
 
+	(void)lengthcol;
+
 	for (unsigned i = 0; i < column->num_posts; i++)
 	{
 		post_t *post = &column->posts[i];
@@ -670,25 +672,17 @@ void R_DrawMaskedColumn(column_t *column)
 			dc_source = column->pixels + post->data_offset;
 			dc_texturemid = basetexturemid - (post->topdelta<<FRACBITS);
 
-			// Drawn by R_DrawColumn.
-			// This stuff is a likely cause of the splitscreen water crash bug.
-			// FIXTHIS: Figure out what "something more proper" is and do it.
-			// quick fix... something more proper should be done!!!
-			if (ylookup[dc_yl])
-				colfunc();
-#ifdef PARANOIA
-			else
-				I_Error("R_DrawMaskedColumn: Invalid ylookup for dc_yl %d", dc_yl);
-#endif
+			colfunc();
 		}
 	}
 
 	dc_texturemid = basetexturemid;
 }
 
-INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height
+static UINT8 *flippedcol = NULL;
+static size_t flippedcolsize = 0;
 
-void R_DrawFlippedMaskedColumn(column_t *column)
+void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol)
 {
 	INT32 topscreen;
 	INT32 bottomscreen;
@@ -698,6 +692,9 @@ void R_DrawFlippedMaskedColumn(column_t *column)
 	for (unsigned i = 0; i < column->num_posts; i++)
 	{
 		post_t *post = &column->posts[i];
+		if (!post->length)
+			continue;
+
 		INT32 topdelta = lengthcol-post->length-post->topdelta;
 		topscreen = sprtopscreen + spryscale*topdelta;
 		bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*post->length
@@ -725,19 +722,18 @@ void R_DrawFlippedMaskedColumn(column_t *column)
 
 		if (dc_yl <= dc_yh && dc_yh > 0)
 		{
-			dc_source = ZZ_Alloc(post->length);
-			for (s = column->pixels+post->data_offset+post->length, d = dc_source; d < dc_source+post->length; --s)
+			if (post->length > flippedcolsize)
+			{
+				flippedcolsize = post->length;
+				flippedcol = Z_Realloc(flippedcol, flippedcolsize, PU_STATIC, NULL);
+			}
+
+			for (s = column->pixels+post->data_offset+post->length, d = flippedcol; d < flippedcol+post->length; --s)
 				*d++ = *s;
+			dc_source = flippedcol;
 			dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
 
-			// Still drawn by R_DrawColumn.
-			if (ylookup[dc_yl])
-				colfunc();
-#ifdef PARANOIA
-			else
-				I_Error("R_DrawMaskedColumn: Invalid ylookup for dc_yl %d", dc_yl);
-#endif
-			Z_Free(dc_source);
+			colfunc();
 		}
 	}
 
@@ -800,13 +796,14 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
 static void R_DrawVisSprite(vissprite_t *vis)
 {
 	column_t *column;
-	void (*localcolfunc)(column_t *);
+	void (*localcolfunc)(column_t *, unsigned);
 	INT32 pwidth;
 	fixed_t frac;
 	patch_t *patch = vis->patch;
 	fixed_t this_scale = vis->thingscale;
 	INT32 x1, x2;
 	INT64 overflow_test;
+	INT32 lengthcol;
 
 	if (!patch)
 		return;
@@ -940,7 +937,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
 
 			column = &patch->columns[texturecolumn];
 
-			localcolfunc (column);
+			localcolfunc (column, lengthcol);
 		}
 	}
 	else if (vis->cut & SC_SHEAR)
@@ -954,7 +951,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
 		{
 			column = &patch->columns[frac>>FRACBITS];
 			sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
-			localcolfunc (column);
+			localcolfunc (column, lengthcol);
 		}
 	}
 	else
@@ -967,7 +964,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
 		for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
 		{
 			column = &patch->columns[frac>>FRACBITS];
-			localcolfunc (column);
+			localcolfunc (column, lengthcol);
 		}
 	}
 
@@ -1014,7 +1011,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
 	fixed_t frac = vis->startfrac;
 
 	for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
-		R_DrawMaskedColumn(&patch->columns[frac>>FRACBITS]);
+		R_DrawMaskedColumn(&patch->columns[frac>>FRACBITS], patch->height);
 
 	colfunc = colfuncs[BASEDRAWFUNC];
 }
diff --git a/src/r_things.h b/src/r_things.h
index ed2156baab4b15784360c0664352a1b8b2461d19..c98623f0d4011933e899bc5e89c974676e0a07f8 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -45,10 +45,9 @@ extern fixed_t sprtopscreen;
 extern fixed_t sprbotscreen;
 extern fixed_t windowtop;
 extern fixed_t windowbottom;
-extern INT32 lengthcol;
 
-void R_DrawMaskedColumn(column_t *column);
-void R_DrawFlippedMaskedColumn(column_t *column);
+void R_DrawMaskedColumn(column_t *column, unsigned lengthcol);
+void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol);
 
 // ----------------
 // SPRITE RENDERING