From f34bf7c509153fe2d1aafa2f3122e3a1d4552740 Mon Sep 17 00:00:00 2001
From: Hanicef <gustaf@hanicef.me>
Date: Fri, 21 Mar 2025 21:51:08 +0100
Subject: [PATCH 01/14] Optimize software drawing functions

---
 src/r_draw8.c | 77 ++++++++++++++++++++++++++-------------------------
 src/r_segs.c  |  6 ++--
 2 files changed, 42 insertions(+), 41 deletions(-)

diff --git a/src/r_draw8.c b/src/r_draw8.c
index 7ebfefa432..349139f5e4 100644
--- a/src/r_draw8.c
+++ b/src/r_draw8.c
@@ -25,9 +25,9 @@
 void R_DrawColumn_8(void)
 {
 	INT32 count;
-	register UINT8 *dest;
-	register fixed_t frac;
-	fixed_t fracstep;
+	UINT8 *restrict dest;
+	intptr_t frac;
+	intptr_t fracstep;
 
 	count = dc_yh - dc_yl;
 
@@ -51,9 +51,9 @@ void R_DrawColumn_8(void)
 	// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
 	// This is as fast as it gets.
 	{
-		register const UINT8 *source = dc_source;
-		register const lighttable_t *colormap = dc_colormap;
-		register INT32 heightmask = dc_texheight-1;
+		const UINT8 *restrict source = dc_source;
+		const lighttable_t *restrict colormap = dc_colormap;
+		intptr_t heightmask = dc_texheight-1;
 		if (dc_texheight & heightmask)   // not a power of 2 -- killough
 		{
 			heightmask++;
@@ -62,8 +62,7 @@ void R_DrawColumn_8(void)
 			if (frac < 0)
 				while ((frac += heightmask) <  0);
 			else
-				while (frac >= heightmask)
-					frac -= heightmask;
+				frac %= heightmask;
 
 			do
 			{
@@ -73,14 +72,15 @@ void R_DrawColumn_8(void)
 				*dest = colormap[source[frac>>FRACBITS]];
 				dest += vid.width;
 
+#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue
 				// Avoid overflow.
 				if (fracstep > 0x7FFFFFFF - frac)
 					frac += fracstep - heightmask;
 				else
+#endif
 					frac += fracstep;
 
-				while (frac >= heightmask)
-					frac -= heightmask;
+				frac %= heightmask;
 			} while (--count);
 		}
 		else
@@ -106,9 +106,9 @@ void R_DrawColumn_8(void)
 void R_DrawColumnClamped_8(void)
 {
 	INT32 count;
-	UINT8 *dest;
-	fixed_t frac;
-	fixed_t fracstep;
+	UINT8 *restrict dest;
+	intptr_t frac;
+	intptr_t fracstep;
 
 	count = dc_yh - dc_yl;
 
@@ -132,10 +132,10 @@ void R_DrawColumnClamped_8(void)
 	// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
 	// This is as fast as it gets.
 	{
-		const UINT8 *source = dc_source;
-		const lighttable_t *colormap = dc_colormap;
-		INT32 heightmask = dc_texheight-1;
-		INT32 idx;
+		const UINT8 *restrict source = dc_source;
+		const lighttable_t *restrict colormap = dc_colormap;
+		intptr_t heightmask = dc_texheight-1;
+		intptr_t idx;
 		if (dc_texheight & heightmask)   // not a power of 2 -- killough
 		{
 			heightmask++;
@@ -158,13 +158,14 @@ void R_DrawColumnClamped_8(void)
 				dest += vid.width;
 
 				// Avoid overflow.
+#if __SIZEOF_POINTER__ < 8
 				if (fracstep > 0x7FFFFFFF - frac)
 					frac += fracstep - heightmask;
 				else
+#endif
 					frac += fracstep;
 
-				while (frac >= heightmask)
-					frac -= heightmask;
+				frac %= heightmask;
 			} while (--count);
 		}
 		else
@@ -195,9 +196,9 @@ void R_DrawColumnClamped_8(void)
 void R_Draw2sMultiPatchColumn_8(void)
 {
 	INT32 count;
-	register UINT8 *dest;
-	register fixed_t frac;
-	fixed_t fracstep;
+	UINT8 *restrict dest;
+	intptr_t frac;
+	intptr_t fracstep;
 
 	count = dc_yh - dc_yl;
 
@@ -221,10 +222,10 @@ void R_Draw2sMultiPatchColumn_8(void)
 	// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
 	// This is as fast as it gets.
 	{
-		register const UINT8 *source = dc_source;
-		register const lighttable_t *colormap = dc_colormap;
-		register INT32 heightmask = dc_texheight-1;
-		register UINT8 val;
+		const UINT8 *restrict source = dc_source;
+		const lighttable_t *restrict colormap = dc_colormap;
+		intptr_t heightmask = dc_texheight-1;
+		UINT8 val;
 		if (dc_texheight & heightmask)   // not a power of 2 -- killough
 		{
 			heightmask++;
@@ -233,8 +234,7 @@ void R_Draw2sMultiPatchColumn_8(void)
 			if (frac < 0)
 				while ((frac += heightmask) <  0);
 			else
-				while (frac >= heightmask)
-					frac -= heightmask;
+				frac %= heightmask;
 
 			do
 			{
@@ -249,13 +249,14 @@ void R_Draw2sMultiPatchColumn_8(void)
 				dest += vid.width;
 
 				// Avoid overflow.
+#if __SIZEOF_POINTER__ < 8
 				if (fracstep > 0x7FFFFFFF - frac)
 					frac += fracstep - heightmask;
 				else
+#endif
 					frac += fracstep;
 
-				while (frac >= heightmask)
-					frac -= heightmask;
+				frac %= heightmask;
 			} while (--count);
 		}
 		else
@@ -726,14 +727,14 @@ void R_DrawTranslatedColumn_8(void)
 */
 void R_DrawSpan_8 (void)
 {
-	fixed_t xposition;
-	fixed_t yposition;
-	fixed_t xstep, ystep;
-
-	UINT8 *source;
-	UINT8 *colormap;
-	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	uintptr_t xposition;
+	uintptr_t yposition;
+	uintptr_t xstep, ystep;
+
+	UINT8 *restrict source;
+	UINT8 *restrict colormap;
+	UINT8 *restrict dest;
+	const UINT8 *restrict deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 
diff --git a/src/r_segs.c b/src/r_segs.c
index bee349492e..5fdfdf271e 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -1464,7 +1464,7 @@ static void R_RenderSegLoop (void)
 		// calculate texture offset
 		angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
 		textureoffset = rw_offset - FixedMul(FINETANGENT(angle & TANMASK), rw_distance);
-		texturecolumn = FixedDiv(textureoffset, rw_invmidtexturescalex);
+		texturecolumn = FixedMul(textureoffset, rw_midtexturescalex);
 
 		// texturecolumn and lighting are independent of wall tiers
 		if (segtextured)
@@ -1564,7 +1564,7 @@ static void R_RenderSegLoop (void)
 				if (mid >= floorclip[rw_x])
 					mid = floorclip[rw_x]-1;
 
-				toptexturecolumn = FixedDiv(textureoffset, rw_invtoptexturescalex);
+				toptexturecolumn = FixedMul(textureoffset, rw_toptexturescalex);
 
 				if (mid >= yl) // back ceiling lower than front ceiling ?
 				{
@@ -1611,7 +1611,7 @@ static void R_RenderSegLoop (void)
 				if (mid <= ceilingclip[rw_x])
 					mid = ceilingclip[rw_x]+1;
 
-				bottomtexturecolumn = FixedDiv(textureoffset, rw_invbottomtexturescalex);
+				bottomtexturecolumn = FixedMul(textureoffset, rw_bottomtexturescalex);
 
 				if (mid <= yh) // back floor higher than front floor ?
 				{
-- 
GitLab


From 65a1baac5f9b26579a305afb7184507c25293576 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Sun, 23 Mar 2025 18:47:17 +0100
Subject: [PATCH 02/14] Transpose backbuffer

Continuation of https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2228
---
 src/am_map.c       |   2 +-
 src/d_main.c       |   6 +-
 src/f_wipe.c       |   4 +-
 src/r_bbox.c       |   2 +-
 src/r_draw8.c      | 244 +++++++++++++++++++++++++--------------------
 src/r_draw8_npo2.c | 100 ++++++++++---------
 src/r_plane.c      |   6 +-
 src/r_things.c     |   2 +-
 src/sdl/i_video.c  |  37 ++++---
 src/v_video.c      | 217 +++++++++++++++++++++++-----------------
 src/y_inter.c      |  12 +--
 11 files changed, 355 insertions(+), 277 deletions(-)

diff --git a/src/am_map.c b/src/am_map.c
index 36b62f2f9b..859569d487 100644
--- a/src/am_map.c
+++ b/src/am_map.c
@@ -787,7 +787,7 @@ static void AM_drawPixel(INT32 xx, INT32 yy, INT32 cc)
 	UINT8 *dest = screens[0];
 	if (xx < 0 || yy < 0 || xx >= vid.width || yy >= vid.height)
 		return; // off the screen
-	dest[(yy*vid.width) + xx] = cc;
+	dest[(xx*vid.height) + yy] = cc;
 }
 
 //
diff --git a/src/d_main.c b/src/d_main.c
index f1d9d6e284..5bdeac7609 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -495,7 +495,7 @@ static void D_Display(void)
 				PS_START_TIMING(ps_rendercalltime);
 				if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
 				{
-					topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
+					topleft = screens[0] + viewwindowx*vid.height + viewwindowy;
 					objectsdrawn = 0;
 	#ifdef HWRENDER
 					if (rendermode != render_soft)
@@ -518,7 +518,7 @@ static void D_Display(void)
 					{
 						viewwindowy = vid.height / 2;
 
-						topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
+						topleft = screens[0] + viewwindowx*vid.height + viewwindowy;
 
 						R_RenderPlayerView(&players[secondarydisplayplayer]);
 
@@ -547,7 +547,7 @@ static void D_Display(void)
 			{
 				if (rendermode == render_soft)
 				{
-					VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
+					VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.rowbytes, vid.rowbytes);
 					Y_ConsiderScreenBuffer();
 					usebuffer = true;
 				}
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 1ea32d0ebe..349348e2a5 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -440,7 +440,7 @@ void F_WipeStartScreen(void)
 	}
 #endif
 	wipe_scr_start = screens[3];
-	I_ReadScreen(wipe_scr_start);
+	M_Memcpy(wipe_scr_start, screens[0], vid.width*vid.height);
 #endif
 }
 
@@ -457,7 +457,7 @@ void F_WipeEndScreen(void)
 	}
 #endif
 	wipe_scr_end = screens[4];
-	I_ReadScreen(wipe_scr_end);
+	M_Memcpy(wipe_scr_end, screens[0], vid.width*vid.height);
 	V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
 #endif
 }
diff --git a/src/r_bbox.c b/src/r_bbox.c
index 6d61631829..a098c2fbbd 100644
--- a/src/r_bbox.c
+++ b/src/r_bbox.c
@@ -70,7 +70,7 @@ raster_bbox_seg
 
 	while (y < h)
 	{
-		topleft[x + y * vid.width] = pixel;
+		topleft[x*vid.height + y] = pixel;
 		y++;
 	}
 }
diff --git a/src/r_draw8.c b/src/r_draw8.c
index 349139f5e4..614c6e4267 100644
--- a/src/r_draw8.c
+++ b/src/r_draw8.c
@@ -40,7 +40,7 @@ void R_DrawColumn_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	count++;
 
@@ -70,7 +70,7 @@ void R_DrawColumn_8(void)
 				//  using a lighting/special effects LUT.
 				// heightmask is the Tutti-Frutti fix
 				*dest = colormap[source[frac>>FRACBITS]];
-				dest += vid.width;
+				dest++;
 
 #if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue
 				// Avoid overflow.
@@ -88,10 +88,10 @@ void R_DrawColumn_8(void)
 			while ((count -= 2) >= 0) // texture height is a power of 2
 			{
 				*dest = colormap[source[(frac>>FRACBITS) & heightmask]];
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 				*dest = colormap[source[(frac>>FRACBITS) & heightmask]];
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -121,7 +121,7 @@ void R_DrawColumnClamped_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	count++;
 
@@ -155,7 +155,7 @@ void R_DrawColumnClamped_8(void)
 				idx = frac>>FRACBITS;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = colormap[source[idx]];
-				dest += vid.width;
+				dest++;
 
 				// Avoid overflow.
 #if __SIZEOF_POINTER__ < 8
@@ -175,12 +175,12 @@ void R_DrawColumnClamped_8(void)
 				idx = (frac>>FRACBITS) & heightmask;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = colormap[source[idx]];
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 				idx = (frac>>FRACBITS) & heightmask;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = colormap[source[idx]];
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -211,7 +211,7 @@ void R_Draw2sMultiPatchColumn_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	count++;
 
@@ -246,7 +246,7 @@ void R_Draw2sMultiPatchColumn_8(void)
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
 
-				dest += vid.width;
+				dest++;
 
 				// Avoid overflow.
 #if __SIZEOF_POINTER__ < 8
@@ -266,12 +266,12 @@ void R_Draw2sMultiPatchColumn_8(void)
 				val = source[(frac>>FRACBITS) & heightmask];
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 				val = source[(frac>>FRACBITS) & heightmask];
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -302,7 +302,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	count++;
 
@@ -339,7 +339,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void)
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(transmap + (colormap[val]<<8) + (*dest));
 
-				dest += vid.width;
+				dest++;
 
 				// Avoid overflow.
 				if (fracstep > 0x7FFFFFFF - frac)
@@ -358,12 +358,12 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void)
 				val = source[(frac>>FRACBITS) & heightmask];
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(transmap + (colormap[val]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 				val = source[(frac>>FRACBITS) & heightmask];
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(transmap + (colormap[val]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -398,7 +398,7 @@ void R_DrawShadeColumn_8(void)
 		I_Error("R_DrawShadeColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
 #endif
 
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -408,7 +408,7 @@ void R_DrawShadeColumn_8(void)
 	do
 	{
 		*dest = colormaps[(dc_source[frac>>FRACBITS] <<8) + (*dest)];
-		dest += vid.width;
+		dest++;
 		frac += fracstep;
 	} while (count--);
 }
@@ -434,7 +434,7 @@ void R_DrawTranslucentColumn_8(void)
 		I_Error("R_DrawTranslucentColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
 #endif
 
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -465,7 +465,7 @@ void R_DrawTranslucentColumn_8(void)
 				// using a lighting/special effects LUT.
 				// heightmask is the Tutti-Frutti fix
 				*dest = *(transmap + (colormap[source[frac>>FRACBITS]]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				if ((frac += fracstep) >= heightmask)
 					frac -= heightmask;
 			}
@@ -476,10 +476,10 @@ void R_DrawTranslucentColumn_8(void)
 			while ((count -= 2) >= 0) // texture height is a power of 2
 			{
 				*dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 				*dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -507,7 +507,7 @@ void R_DrawTranslucentColumnClamped_8(void)
 		I_Error("R_DrawTranslucentColumnClamped_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
 #endif
 
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -541,7 +541,7 @@ void R_DrawTranslucentColumnClamped_8(void)
 				idx = frac>>FRACBITS;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				if ((frac += fracstep) >= heightmask)
 					frac -= heightmask;
 			}
@@ -554,12 +554,12 @@ void R_DrawTranslucentColumnClamped_8(void)
 				idx = (frac>>FRACBITS)&heightmask;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 				idx = (frac>>FRACBITS)&heightmask;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -587,7 +587,7 @@ void R_DrawDropShadowColumn_8(void)
 	if (count <= 0) // Zero length, column does not exceed a pixel.
 		return;
 
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	{
 #define DSCOLOR 31 // palette index for the color of the shadow
@@ -596,9 +596,9 @@ void R_DrawDropShadowColumn_8(void)
 		while ((count -= 2) >= 0)
 		{
 			*dest = *(transmap_offset + (*dest));
-			dest += vid.width;
+			dest++;
 			*dest = *(transmap_offset + (*dest));
-			dest += vid.width;
+			dest++;
 		}
 		if (count & 1)
 			*dest = *(transmap_offset + (*dest));
@@ -620,7 +620,7 @@ void R_DrawTranslatedTranslucentColumn_8(void)
 	if (count <= 0) // Zero length, column does not exceed a pixel.
 		return;
 
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -650,7 +650,7 @@ void R_DrawTranslatedTranslucentColumn_8(void)
 
 				*dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest));
 
-				dest += vid.width;
+				dest++;
 				if ((frac += fracstep) >= heightmask)
 					frac -= heightmask;
 			}
@@ -661,10 +661,10 @@ void R_DrawTranslatedTranslucentColumn_8(void)
 			while ((count -= 2) >= 0) // texture height is a power of 2
 			{
 				*dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 				*dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest));
-				dest += vid.width;
+				dest++;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -693,7 +693,7 @@ void R_DrawTranslatedColumn_8(void)
 		I_Error("R_DrawTranslatedColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
 #endif
 
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -709,7 +709,7 @@ void R_DrawTranslatedColumn_8(void)
 		//  is mapped to gray, red, black/indigo.
 		*dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
 
-		dest += vid.width;
+		dest++;
 
 		frac += fracstep;
 	} while (count--);
@@ -734,7 +734,7 @@ void R_DrawSpan_8 (void)
 	UINT8 *restrict source;
 	UINT8 *restrict colormap;
 	UINT8 *restrict dest;
-	const UINT8 *restrict deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *restrict deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 
@@ -753,11 +753,12 @@ void R_DrawSpan_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
-	if (dest+8 > deststop)
+	if (dest > deststop)
 		return;
 
+	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -798,9 +799,11 @@ void R_DrawSpan_8 (void)
 		dest += 8;
 		count -= 8;
 	}
+	*/
 	while (count-- && dest <= deststop)
 	{
-		*dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]];
+		*dest = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]];
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -832,7 +835,7 @@ void R_DrawTiltedSpan_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -847,7 +850,7 @@ void R_DrawTiltedSpan_8(void)
 		colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 
 		*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -881,7 +884,7 @@ void R_DrawTiltedSpan_8(void)
 		{
 			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 			*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
-			dest++;
+			dest += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -918,7 +921,7 @@ void R_DrawTiltedSpan_8(void)
 			{
 				colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 				*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
-				dest++;
+				dest += vid.height;
 				u += stepu;
 				v += stepv;
 			}
@@ -953,7 +956,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -967,7 +970,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
 
 		colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 		*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1001,7 +1004,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
 		{
 			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
-			dest++;
+			dest += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -1038,7 +1041,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
 			{
 				colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 				*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
-				dest++;
+				dest += vid.height;
 				u += stepu;
 				v += stepv;
 			}
@@ -1074,8 +1077,8 @@ void R_DrawTiltedWaterSpan_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
-	dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
+	dest = &topleft[ds_y + ds_x1*vid.height];
+	dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -1089,7 +1092,7 @@ void R_DrawTiltedWaterSpan_8(void)
 
 		colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 		*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++);
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1122,8 +1125,9 @@ void R_DrawTiltedWaterSpan_8(void)
 		for (i = SPANSIZE-1; i >= 0; i--)
 		{
 			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++);
-			dest++;
+			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc);
+			dest += vid.height;
+			dsrc += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -1138,7 +1142,7 @@ void R_DrawTiltedWaterSpan_8(void)
 			u = (INT64)(startu);
 			v = (INT64)(startv);
 			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++);
+			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc);
 		}
 		else
 		{
@@ -1159,8 +1163,9 @@ void R_DrawTiltedWaterSpan_8(void)
 			for (; width != 0; width--)
 			{
 				colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-				*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++);
-				dest++;
+				*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc);
+				dest += vid.height;
+				dsrc += vid.height;
 				u += stepu;
 				v += stepv;
 			}
@@ -1194,7 +1199,7 @@ void R_DrawTiltedSplat_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -1212,7 +1217,7 @@ void R_DrawTiltedSplat_8(void)
 		if (val != TRANSPARENTPIXEL)
 			*dest = colormap[val];
 
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1248,7 +1253,7 @@ void R_DrawTiltedSplat_8(void)
 			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 			if (val != TRANSPARENTPIXEL)
 				*dest = colormap[val];
-			dest++;
+			dest += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -1289,7 +1294,7 @@ void R_DrawTiltedSplat_8(void)
 				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
-				dest++;
+				dest += vid.height;
 				u += stepu;
 				v += stepv;
 			}
@@ -1323,7 +1328,7 @@ void R_DrawTiltedTranslucentSplat_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = ds_source;
 	//colormap = ds_colormap;
 
@@ -1342,7 +1347,7 @@ void R_DrawTiltedTranslucentSplat_8(void)
 		if (val != TRANSPARENTPIXEL)
 			*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
 
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1378,7 +1383,7 @@ void R_DrawTiltedTranslucentSplat_8(void)
 			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 			if (val != TRANSPARENTPIXEL)
 				*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-			dest++;
+			dest += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -1419,7 +1424,7 @@ void R_DrawTiltedTranslucentSplat_8(void)
 				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-				dest++;
+				dest += vid.height;
 				u += stepu;
 				v += stepv;
 			}
@@ -1433,6 +1438,7 @@ void R_DrawTiltedTranslucentSplat_8(void)
 */
 void R_DrawSplat_8 (void)
 {
+	return;
 	fixed_t xposition;
 	fixed_t yposition;
 	fixed_t xstep, ystep;
@@ -1440,7 +1446,7 @@ void R_DrawSplat_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1460,8 +1466,9 @@ void R_DrawSplat_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
+	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -1537,12 +1544,13 @@ void R_DrawSplat_8 (void)
 		dest += 8;
 		count -= 8;
 	}
+	*/
 	while (count-- && dest <= deststop)
 	{
 		val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
 		if (val != TRANSPARENTPIXEL)
 			*dest = colormap[val];
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1560,7 +1568,7 @@ void R_DrawTranslucentSplat_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1580,8 +1588,9 @@ void R_DrawTranslucentSplat_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
+	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -1638,12 +1647,13 @@ void R_DrawTranslucentSplat_8 (void)
 		dest += 8;
 		count -= 8;
 	}
+	*/
 	while (count-- && dest <= deststop)
 	{
 		val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
 		if (val != TRANSPARENTPIXEL)
 			*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1662,7 +1672,7 @@ void R_DrawFloorSprite_8 (void)
 	UINT8 *colormap;
 	UINT8 *translation;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1683,8 +1693,9 @@ void R_DrawFloorSprite_8 (void)
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
+	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -1749,12 +1760,13 @@ void R_DrawFloorSprite_8 (void)
 		dest += 8;
 		count -= 8;
 	}
+	*/
 	while (count-- && dest <= deststop)
 	{
 		val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
 		if (val & 0xFF00)
 			*dest = colormap[translation[val & 0xFF]];
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1773,7 +1785,7 @@ void R_DrawTranslucentFloorSprite_8 (void)
 	UINT8 *colormap;
 	UINT8 *translation;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1794,8 +1806,9 @@ void R_DrawTranslucentFloorSprite_8 (void)
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
+	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -1852,12 +1865,13 @@ void R_DrawTranslucentFloorSprite_8 (void)
 		dest += 8;
 		count -= 8;
 	}
+	*/
 	while (count-- && dest <= deststop)
 	{
 		val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
 		if (val & 0xFF00)
 			*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1889,7 +1903,7 @@ void R_DrawTiltedFloorSprite_8(void)
 	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
 	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
@@ -1923,7 +1937,7 @@ void R_DrawTiltedFloorSprite_8(void)
 			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 			if (val & 0xFF00)
 				*dest = colormap[translation[val & 0xFF]];
-			dest++;
+			dest += vid.height;
 
 			u += stepu;
 			v += stepv;
@@ -1963,7 +1977,7 @@ void R_DrawTiltedFloorSprite_8(void)
 				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 				if (val & 0xFF00)
 					*dest = colormap[translation[val & 0xFF]];
-				dest++;
+				dest += vid.height;
 
 				u += stepu;
 				v += stepv;
@@ -1998,7 +2012,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(void)
 	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
 	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
@@ -2032,7 +2046,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(void)
 			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 			if (val & 0xFF00)
 				*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-			dest++;
+			dest += vid.height;
 
 			u += stepu;
 			v += stepv;
@@ -2072,7 +2086,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(void)
 				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 				if (val & 0xFF00)
 					*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-				dest++;
+				dest += vid.height;
 
 				u += stepu;
 				v += stepv;
@@ -2093,7 +2107,7 @@ void R_DrawTranslucentSpan_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -2113,8 +2127,9 @@ void R_DrawTranslucentSpan_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
+	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -2155,11 +2170,12 @@ void R_DrawTranslucentSpan_8 (void)
 		dest += 8;
 		count -= 8;
 	}
+	*/
 	while (count-- && dest <= deststop)
 	{
 		val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
 		*dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest);
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -2190,10 +2206,11 @@ void R_DrawWaterSpan_8(void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
-	dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
+	dest = &topleft[ds_y + ds_x1*vid.height];
+	dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
 	count = ds_x2 - ds_x1 + 1;
 
+	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -2234,9 +2251,12 @@ void R_DrawWaterSpan_8(void)
 		dest += 8;
 		count -= 8;
 	}
+	*/
 	while (count--)
 	{
-		*dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
+		*dest = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc)];
+		dest += vid.height;
+		dsrc += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -2253,10 +2273,11 @@ void R_DrawFogSpan_8(void)
 	size_t count;
 
 	colormap = ds_colormap;
-	dest = &topleft[ds_y *vid.width + ds_x1];
+	dest = &topleft[ds_y  + ds_x1*vid.height];
 
 	count = ds_x2 - ds_x1 + 1;
 
+	/*
 	while (count >= 4)
 	{
 		dest[0] = colormap[dest[0]];
@@ -2267,11 +2288,12 @@ void R_DrawFogSpan_8(void)
 		dest += 4;
 		count -= 4;
 	}
+	*/
 
 	while (count--)
 	{
 		*dest = colormap[*dest];
-		dest++;
+		dest += vid.height;
 	}
 }
 
@@ -2282,7 +2304,7 @@ void R_DrawTiltedFogSpan_8(void)
 {
 	int width = ds_x2 - ds_x1;
 
-	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
+	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
 
 	R_CalcSlopeLight();
 
@@ -2290,7 +2312,7 @@ void R_DrawTiltedFogSpan_8(void)
 	{
 		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 		*dest = colormap[*dest];
-		dest++;
+		dest += vid.height;
 	} while (--width >= 0);
 }
 
@@ -2302,7 +2324,7 @@ void R_DrawSolidColorSpan_8(void)
 	size_t count = (ds_x2 - ds_x1 + 1);
 
 	UINT8 source = ds_colormap[ds_source[0]];
-	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
+	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
 
 	memset(dest, source, count);
 }
@@ -2315,14 +2337,14 @@ void R_DrawTransSolidColorSpan_8(void)
 	size_t count = (ds_x2 - ds_x1 + 1);
 
 	UINT8 source = ds_colormap[ds_source[0]];
-	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
+	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
 
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	while (count-- && dest <= deststop)
 	{
 		*dest = *(ds_transmap + (source << 8) + *dest);
-		dest++;
+		dest += vid.height;
 	}
 }
 
@@ -2334,14 +2356,15 @@ void R_DrawTiltedSolidColorSpan_8(void)
 	int width = ds_x2 - ds_x1;
 
 	UINT8 source = ds_source[0];
-	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
+	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
 
 	R_CalcSlopeLight();
 
 	do
 	{
 		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-		*dest++ = colormap[source];
+		*dest = colormap[source];
+		dest += vid.height;
 	} while (--width >= 0);
 }
 
@@ -2353,7 +2376,7 @@ void R_DrawTiltedTransSolidColorSpan_8(void)
 	int width = ds_x2 - ds_x1;
 
 	UINT8 source = ds_source[0];
-	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
+	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
 
 	R_CalcSlopeLight();
 
@@ -2361,7 +2384,7 @@ void R_DrawTiltedTransSolidColorSpan_8(void)
 	{
 		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 		*dest = *(ds_transmap + (colormap[source] << 8) + *dest);
-		dest++;
+		dest += vid.height;
 	} while (--width >= 0);
 }
 
@@ -2372,16 +2395,17 @@ void R_DrawWaterSolidColorSpan_8(void)
 {
 	UINT8 source = ds_source[0];
 	UINT8 *colormap = ds_colormap;
-	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
-	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
+	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
+	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	while (count-- && dest <= deststop)
 	{
-		*dest = colormap[*(ds_transmap + (source << 8) + *dsrc++)];
-		dest++;
+		*dest = colormap[*(ds_transmap + (source << 8) + *dsrc)];
+		dest += vid.height;
+		dsrc += vid.height;
 	}
 }
 
@@ -2393,15 +2417,17 @@ void R_DrawTiltedWaterSolidColorSpan_8(void)
 	int width = ds_x2 - ds_x1;
 
 	UINT8 source = ds_source[0];
-	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
-	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
+	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
+	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
 
 	R_CalcSlopeLight();
 
 	do
 	{
 		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-		*dest++ = *(ds_transmap + (colormap[source] << 8) + *dsrc++);
+		*dest = *(ds_transmap + (colormap[source] << 8) + *dsrc);
+		dest += vid.height;
+		dsrc += vid.height;
 	} while (--width >= 0);
 }
 
@@ -2425,14 +2451,14 @@ void R_DrawFogColumn_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl*vid.width + dc_x];
+	dest = &topleft[dc_yl + dc_x*vid.height];
 
 	// Determine scaling, which is the only mapping to be done.
 	do
 	{
 		// Simple. Apply the colormap to what's already on the screen.
 		*dest = dc_colormap[*dest];
-		dest += vid.width;
+		dest += vid.height;
 	} while (count--);
 }
 
diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c
index f3f2254f5e..873d03186d 100644
--- a/src/r_draw8_npo2.c
+++ b/src/r_draw8_npo2.c
@@ -37,7 +37,7 @@ void R_DrawSpan_NPO2_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 
@@ -46,7 +46,7 @@ void R_DrawSpan_NPO2_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
 	if (dest+8 > deststop)
 		return;
@@ -85,7 +85,8 @@ void R_DrawSpan_NPO2_8 (void)
 		x = (xposition >> FRACBITS);
 		y = (yposition >> FRACBITS);
 
-		*dest++ = colormap[source[((y * ds_flatwidth) + x)]];
+		*dest = colormap[source[((y * ds_flatwidth) + x)]];
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -120,7 +121,7 @@ void R_DrawTiltedSpan_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -151,7 +152,7 @@ void R_DrawTiltedSpan_NPO2_8(void)
 
 			*dest = colormap[source[((y * ds_flatwidth) + x)]];
 		}
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -201,7 +202,7 @@ void R_DrawTiltedSpan_NPO2_8(void)
 
 				*dest = colormap[source[((y * ds_flatwidth) + x)]];
 			}
-			dest++;
+			dest += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -270,7 +271,7 @@ void R_DrawTiltedSpan_NPO2_8(void)
 
 					*dest = colormap[source[((y * ds_flatwidth) + x)]];
 				}
-				dest++;
+				dest += vid.height;
 				u += stepu;
 				v += stepv;
 			}
@@ -308,7 +309,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -338,7 +339,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
 
 			*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest);
 		}
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -388,7 +389,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
 
 				*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest);
 			}
-			dest++;
+			dest += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -457,7 +458,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
 
 					*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest);
 				}
-				dest++;
+				dest += vid.height;
 				u += stepu;
 				v += stepv;
 			}
@@ -494,7 +495,7 @@ void R_DrawTiltedSplat_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -529,7 +530,7 @@ void R_DrawTiltedSplat_NPO2_8(void)
 		if (val != TRANSPARENTPIXEL)
 			*dest = colormap[val];
 
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -581,7 +582,7 @@ void R_DrawTiltedSplat_NPO2_8(void)
 			}
 			if (val != TRANSPARENTPIXEL)
 				*dest = colormap[val];
-			dest++;
+			dest += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -654,7 +655,7 @@ void R_DrawTiltedSplat_NPO2_8(void)
 				}
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
-				dest++;
+				dest += vid.height;
 				u += stepu;
 				v += stepv;
 			}
@@ -691,7 +692,7 @@ void R_DrawTiltedTranslucentSplat_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = ds_source;
 	//colormap = ds_colormap;
 
@@ -727,7 +728,7 @@ void R_DrawTiltedTranslucentSplat_NPO2_8(void)
 		if (val != TRANSPARENTPIXEL)
 			*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
 
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -779,7 +780,7 @@ void R_DrawTiltedTranslucentSplat_NPO2_8(void)
 			}
 			if (val != TRANSPARENTPIXEL)
 				*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-			dest++;
+			dest += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -852,7 +853,7 @@ void R_DrawTiltedTranslucentSplat_NPO2_8(void)
 				}
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-				dest++;
+				dest += vid.height;
 				u += stepu;
 				v += stepv;
 			}
@@ -875,7 +876,7 @@ void R_DrawSplat_NPO2_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -885,7 +886,7 @@ void R_DrawSplat_NPO2_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -923,7 +924,7 @@ void R_DrawSplat_NPO2_8 (void)
 		val = source[((y * ds_flatwidth) + x)];
 		if (val != TRANSPARENTPIXEL)
 			*dest = colormap[val];
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -943,7 +944,7 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -953,7 +954,7 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -991,7 +992,7 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
 		val = source[((y * ds_flatwidth) + x)];
 		if (val != TRANSPARENTPIXEL)
 			*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1012,7 +1013,7 @@ void R_DrawFloorSprite_NPO2_8 (void)
 	UINT8 *translation;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1023,7 +1024,7 @@ void R_DrawFloorSprite_NPO2_8 (void)
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -1061,7 +1062,7 @@ void R_DrawFloorSprite_NPO2_8 (void)
 		val = source[((y * ds_flatwidth) + x)];
 		if (val & 0xFF00)
 			*dest = colormap[translation[val & 0xFF]];
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1082,7 +1083,7 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void)
 	UINT8 *translation;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1093,7 +1094,7 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void)
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -1131,7 +1132,7 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void)
 		val = source[((y * ds_flatwidth) + x)];
 		if (val & 0xFF00)
 			*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1166,7 +1167,7 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
 	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
 	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
@@ -1214,7 +1215,7 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
 			val = source[((y * ds_flatwidth) + x)];
 			if (val & 0xFF00)
 				*dest = colormap[translation[val & 0xFF]];
-			dest++;
+			dest += vid.height;
 
 			u += stepu;
 			v += stepv;
@@ -1284,7 +1285,7 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
 				val = source[((y * ds_flatwidth) + x)];
 				if (val & 0xFF00)
 					*dest = colormap[translation[val & 0xFF]];
-				dest++;
+				dest += vid.height;
 
 				u += stepu;
 				v += stepv;
@@ -1322,7 +1323,7 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
 	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
 	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
@@ -1370,7 +1371,7 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
 			val = source[((y * ds_flatwidth) + x)];
 			if (val & 0xFF00)
 				*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-			dest++;
+			dest += vid.height;
 
 			u += stepu;
 			v += stepv;
@@ -1440,7 +1441,7 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
 				val = source[((y * ds_flatwidth) + x)];
 				if (val & 0xFF00)
 					*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-				dest++;
+				dest += vid.height;
 
 				u += stepu;
 				v += stepv;
@@ -1463,7 +1464,7 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1473,7 +1474,7 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
+	dest = &topleft[ds_y + ds_x1*vid.height];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -1510,7 +1511,7 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
 		y = (yposition >> FRACBITS);
 		val = ((y * ds_flatwidth) + x);
 		*dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest);
-		dest++;
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1528,7 +1529,7 @@ void R_DrawWaterSpan_NPO2_8(void)
 	UINT8 *colormap;
 	UINT8 *dest;
 	UINT8 *dsrc;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 
@@ -1537,8 +1538,8 @@ void R_DrawWaterSpan_NPO2_8(void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y*vid.width + ds_x1];
-	dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
+	dest = &topleft[ds_y + ds_x1*vid.height];
+	dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -1573,7 +1574,8 @@ void R_DrawWaterSpan_NPO2_8(void)
 
 		x = (xposition >> FRACBITS);
 		y = (yposition >> FRACBITS);
-		*dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)];
+		*dest = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)];
+		dest += vid.height;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1609,8 +1611,8 @@ void R_DrawTiltedWaterSpan_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y*vid.width + ds_x1];
-	dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
+	dest = &topleft[ds_y + ds_x1*vid.height];
+	dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -1640,7 +1642,7 @@ void R_DrawTiltedWaterSpan_NPO2_8(void)
 
 			*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++);
 		}
-		dest++;
+		dest += vid.height;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1690,7 +1692,7 @@ void R_DrawTiltedWaterSpan_NPO2_8(void)
 
 				*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++);
 			}
-			dest++;
+			dest += vid.height;
 			u += stepu;
 			v += stepv;
 		}
@@ -1759,7 +1761,7 @@ void R_DrawTiltedWaterSpan_NPO2_8(void)
 
 					*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++);
 				}
-				dest++;
+				dest += vid.height;
 				u += stepu;
 				v += stepv;
 			}
diff --git a/src/r_plane.c b/src/r_plane.c
index bfc7614006..3a0c74d618 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -1046,9 +1046,9 @@ void R_DrawSinglePlane(visplane_t *pl)
 					spanfunctype = SPANDRAWFUNC_WATER;
 
 					// Only copy the part of the screen we need
-					VID_BlitLinearScreen((splitscreen && viewplayer == &players[secondarydisplayplayer]) ? screens[0] + (top+(vid.height>>1))*vid.width : screens[0]+((top)*vid.width), screens[1]+((top)*vid.width),
-										 vid.width, bottom-top,
-										 vid.width, vid.width);
+					VID_BlitLinearScreen(topleft+top, screens[1]+top,
+										 vid.width, vid.width,
+										 vid.rowbytes, vid.rowbytes);
 				}
 			}
 		}
diff --git a/src/r_things.c b/src/r_things.c
index 6fffa4f5c4..03cfe02ba8 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -979,7 +979,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol)
 		{
 			dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
 
-	R_DrawFlippedPost(column->pixels + post->data_offset, post->length, colfunc);
+			R_DrawFlippedPost(column->pixels + post->data_offset, post->length, colfunc);
 		}
 	}
 
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 684962a332..fd0ebfc72b 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -274,7 +274,7 @@ static void Impl_VideoSetupSurfaces(int width, int height)
 	}
 
 	if (texture == NULL)
-		texture = SDL_CreateTexture(renderer, sw_texture_format, SDL_TEXTUREACCESS_STREAMING, width, height);
+		texture = SDL_CreateTexture(renderer, sw_texture_format, SDL_TEXTUREACCESS_STREAMING, height, width);
 
 	// Set up SW surface
 	if (vidSurface == NULL)
@@ -285,7 +285,7 @@ static void Impl_VideoSetupSurfaces(int width, int height)
 		Uint32 amask;
 
 		SDL_PixelFormatEnumToMasks(sw_texture_format, &bpp, &rmask, &gmask, &bmask, &amask);
-		vidSurface = SDL_CreateRGBSurface(0, width, height, bpp, rmask, gmask, bmask, amask);
+		vidSurface = SDL_CreateRGBSurface(0, height, width, bpp, rmask, gmask, bmask, amask);
 	}
 }
 
@@ -294,11 +294,11 @@ static void Impl_SetupSoftwareBuffer(void)
 	// Set up game's software render buffer
 	size_t size;
 
-	vid.rowbytes = vid.width * vid.bpp;
+	vid.rowbytes = vid.height * vid.bpp;
 
 	free(vid.buffer);
 
-	size = vid.rowbytes*vid.height * NUMSCREENS;
+	size = vid.rowbytes*vid.width * NUMSCREENS;
 	vid.buffer = malloc(size);
 
 	if (vid.buffer)
@@ -312,6 +312,7 @@ static void Impl_SetupSoftwareBuffer(void)
 }
 
 static SDL_Rect src_rect = { 0, 0, 0, 0 };
+static SDL_Rect dst_rect = { 0, 0, 0, 0 };
 
 static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition)
 {
@@ -320,8 +321,15 @@ static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_b
 
 	boolean should_set_window_size = realwidth != width || realheight != height;
 
-	src_rect.w = realwidth = width;
-	src_rect.h = realheight = height;
+	realwidth = width;
+	realheight = height;
+	src_rect.w = height;
+	src_rect.h = width;
+
+	dst_rect.x = (vid.width - vid.height) / 2;
+	dst_rect.y = (vid.height - vid.width) / 2;
+	dst_rect.w = vid.height;
+	dst_rect.h = vid.width;
 
 	if (window)
 	{
@@ -1370,7 +1378,7 @@ void I_FinishUpdate(void)
 		SDL_UnlockSurface(vidSurface);
 
 		SDL_RenderClear(renderer);
-		SDL_RenderCopy(renderer, texture, &src_rect, NULL);
+		SDL_RenderCopyEx(renderer, texture, NULL, &dst_rect, 90.0, NULL, SDL_FLIP_VERTICAL);
 		SDL_RenderPresent(renderer);
 	}
 #ifdef HWRENDER
@@ -1407,10 +1415,13 @@ void I_ReadScreen(UINT8 *scr)
 {
 	if (rendermode != render_soft)
 		I_Error ("I_ReadScreen: called while in non-software mode");
-	else
-		VID_BlitLinearScreen(screens[0], scr,
-			vid.width*vid.bpp, vid.height,
-			vid.rowbytes, vid.rowbytes);
+
+	UINT8 *buffer = screens[0];
+	size_t dest_rowbytes = vid.width * vid.bpp;
+
+	for (int y = 0; y < vid.height; y++)
+		for (int x = 0; x < vid.width; x++)
+			scr[(y * dest_rowbytes) + x] = buffer[(x * vid.rowbytes) + y];
 }
 
 //
@@ -1640,12 +1651,12 @@ static void Impl_VideoSetupBuffer(void)
 	// Set up the SDL palletized buffer (copied to vidbuffer before being rendered to texture)
 	if (vid.bpp == 1)
 	{
-		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,8,
+		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.height,vid.width,8,
 			(int)vid.rowbytes,0x00000000,0x00000000,0x00000000,0x00000000); // 256 mode
 	}
 	else if (vid.bpp == 2) // Fury -- don't think this is used at all anymore
 	{
-		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,15,
+		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.height,vid.width,15,
 			(int)vid.rowbytes,0x00007C00,0x000003E0,0x0000001F,0x00000000); // 555 mode
 	}
 	if (bufSurface)
diff --git a/src/v_video.c b/src/v_video.c
index 3e2a59a3a7..7875fa8ef6 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -463,12 +463,12 @@ void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT3
 	size_t destrowbytes)
 {
 	if (srcrowbytes == destrowbytes)
-		M_Memcpy(destptr, srcptr, srcrowbytes * height);
+		M_Memcpy(destptr, srcptr, srcrowbytes * width);
 	else
 	{
-		while (height--)
+		while (width--)
 		{
-			M_Memcpy(destptr, srcptr, width);
+			M_Memcpy(destptr, srcptr, height);
 
 			destptr += destrowbytes;
 			srcptr += srcrowbytes;
@@ -669,13 +669,10 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
 	if (!desttop)
 		return;
 
-	deststop = desttop + vid.rowbytes * vid.height;
-
 	if (scrn & V_NOSCALESTART)
 	{
 		x >>= FRACBITS;
 		y >>= FRACBITS;
-		desttop += (y*vid.width) + x;
 	}
 	else
 	{
@@ -725,8 +722,8 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
 			}
 		}
 
-		desttop += (y*vid.width) + x;
 	}
+	desttop += (x*vid.height) + y;
 
 	if (pscale != FRACUNIT) // scale width properly
 	{
@@ -739,9 +736,9 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
 		pwidth = patch->width * dup;
 
 	deststart = desttop;
-	destend = desttop + pwidth;
+	destend = desttop + pwidth*vid.height;
 
-	for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop++)
+	for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop += vid.height)
 	{
 		if (scrn & V_FLIP) // offx is measured from right edge instead of left
 		{
@@ -767,13 +764,16 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
 			dest = desttop;
 			if (scrn & V_FLIP)
 				dest = deststart + (destend - desttop);
-			dest += FixedInt(FixedMul(post->topdelta<<FRACBITS,vdup))*vid.width;
+			dest += FixedInt(FixedMul(post->topdelta<<FRACBITS,vdup));
+
+			UINT8 *col_start = screens[0] + ((x + offx)*vid.height);
+			deststop = col_start + vid.height;
 
 			for (ofs = 0; dest < deststop && (size_t)(ofs>>FRACBITS) < post->length; ofs += rowfrac)
 			{
-				if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
+				if (dest >= col_start) // don't draw off the top of the screen (CRASH PREVENTION)
 					*dest = patchdrawfunc(dest, source, ofs);
-				dest += vid.width;
+				dest++;
 			}
 		}
 	}
@@ -934,13 +934,12 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 	if (!desttop)
 		return;
 
-	deststop = desttop + vid.rowbytes * vid.height;
+	int stop_pos = vid.height;
 
 	if (scrn & V_NOSCALESTART)
 	{
 		x >>= FRACBITS;
 		y >>= FRACBITS;
-		desttop += (y*vid.width) + x;
 	}
 	else
 	{
@@ -981,10 +980,10 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 					y += (vid.height - (BASEVIDHEIGHT * dup)) / 4;
 			}
 		}
-
-		desttop += (y*vid.width) + x;
 	}
 
+	desttop += (y*vid.width) + x;
+
 	// Auto-crop at splitscreen borders!
 	if (splitscreen && (scrn & V_PERPLAYER))
 	{
@@ -1002,7 +1001,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 			if (stplyr == &players[displayplayer]) // Player 1's screen, crop at the bottom
 			{
 				// Just put a big old stop sign halfway through the screen
-				deststop -= vid.rowbytes * (vid.height>>1);
+				stop_pos -= vid.height>>1;
 			}
 			else //if (stplyr == &players[secondarydisplayplayer]) // Player 2's screen, crop at the top
 			{
@@ -1010,13 +1009,13 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 				{
 					sy += ((vid.height>>1) - y) * rowfrac; // Start further down on the patch
 					h -= ((vid.height>>1) - y) * rowfrac; // Draw less downwards from the start
-					desttop += ((vid.height>>1) - y) * vid.width; // Start drawing at the border
+					desttop += (vid.height>>1) - y; // Start drawing at the border
 				}
 			}
 		}
 	}
 
-	for (col = sx; (col>>FRACBITS) < patch->width && (col - sx) < w; col += colfrac, ++x, desttop++)
+	for (col = sx; (col>>FRACBITS) < patch->width && (col - sx) < w; col += colfrac, ++x, desttop += vid.height)
 	{
 		if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION)
 			continue;
@@ -1033,17 +1032,20 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 			dest = desttop;
 			if ((topdelta<<FRACBITS)-sy > 0)
 			{
-				dest += FixedInt(FixedMul((topdelta<<FRACBITS)-sy,vdup))*vid.width;
+				dest += FixedInt(FixedMul((topdelta<<FRACBITS)-sy,vdup));
 				ofs = 0;
 			}
 			else
 				ofs = sy-(topdelta<<FRACBITS);
 
+			UINT8 *col_start = screens[0] + (x*vid.height);
+			deststop = col_start + stop_pos;
+
 			for (; dest < deststop && (size_t)(ofs>>FRACBITS) < post->length && ((ofs - sy) + (topdelta<<FRACBITS)) < h; ofs += rowfrac)
 			{
-				if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
+				if (dest >= col_start) // don't draw off the top of the screen (CRASH PREVENTION)
 					*dest = patchdrawfunc(dest, source, ofs);
-				dest += vid.width;
+				dest++;
 			}
 		}
 	}
@@ -1082,8 +1084,8 @@ void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const
 		I_Error("Bad V_DrawBlock");
 #endif
 
-	dest = screens[scrn] + y*vid.width + x;
-	deststop = screens[scrn] + vid.rowbytes * vid.height;
+	dest = screens[scrn] + x*vid.height + y;
+	deststop = screens[scrn] + vid.rowbytes * vid.width;
 
 	while (height--)
 	{
@@ -1101,7 +1103,7 @@ void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const
 //
 void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 {
-	UINT8 *dest;
+	UINT8 *dest, *desttop;
 	const UINT8 *deststop;
 	UINT32 alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT);
 	UINT32 blendmode = ((c & V_BLENDMASK) >> V_BLENDSHIFT);
@@ -1269,8 +1271,8 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 	if (y + h > vid.height)
 		h = vid.height - y;
 
-	dest = screens[0] + y*vid.width + x;
-	deststop = screens[0] + vid.rowbytes * vid.height;
+	dest = desttop = screens[0] + x*vid.height + y;
+	deststop = screens[0] + vid.rowbytes * vid.width;
 
 	c &= 255;
 
@@ -1278,16 +1280,31 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 	if (alphalevel)
 	{
 		v_translevel += c<<8;
-		for (;(--h >= 0) && dest < deststop; dest += vid.width)
+		for (;(--h >= 0) && desttop < deststop; desttop++)
 		{
-			for (x = 0; x < w; x++)
-				dest[x] = v_translevel[dest[x]];
+			dest = desttop;
+
+			UINT8 *row_end = dest + (w * vid.height);
+			while (dest < row_end)
+			{
+				*dest = v_translevel[*dest];
+				dest += vid.height;
+			}
 		}
 	}
 	else
 	{
-		for (;(--h >= 0) && dest < deststop; dest += vid.width)
-			memset(dest, c, w * vid.bpp);
+		for (;(--h >= 0) && desttop < deststop; desttop++)
+		{
+			dest = desttop;
+
+			UINT8 *row_end = dest + (w * vid.height);
+			while (dest < row_end)
+			{
+				*dest = c;
+				dest += vid.height;
+			}
+		}
 	}
 }
 
@@ -1331,9 +1348,8 @@ static UINT32 V_GetHWConsBackColor(void)
 
 void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 {
-	UINT8 *dest;
+	UINT8 *dest, *desttop;
 	const UINT8 *deststop;
-	INT32 u;
 	UINT8 *fadetable;
 	UINT32 alphalevel = 0;
 	UINT8 perplayershuffle = 0;
@@ -1484,7 +1500,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 	if (y + h > vid.height)
 		h = vid.height-y;
 
-	dest = screens[0] + y*vid.width + x;
+	dest = desttop = screens[0] + x*vid.height + y;
 	deststop = screens[0] + vid.rowbytes * vid.height;
 
 	c &= 255;
@@ -1493,25 +1509,27 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 	if (alphalevel)
 	{
 		fadetable = R_GetTranslucencyTable(alphalevel) + (c*256);
-		for (;(--h >= 0) && dest < deststop; dest += vid.width)
+		for (;(--h >= 0) && desttop < deststop; desttop++)
 		{
-			u = 0;
-			while (u < w)
+			dest = desttop;
+			UINT8 *row_end = dest + w*vid.height;
+			while (dest < row_end)
 			{
-				dest[u] = fadetable[consolebgmap[dest[u]]];
-				u++;
+				*dest = fadetable[consolebgmap[*dest]];
+				dest += vid.height;
 			}
 		}
 	}
 	else
 	{
-		for (;(--h >= 0) && dest < deststop; dest += vid.width)
+		for (;(--h >= 0) && desttop < deststop; desttop++)
 		{
-			u = 0;
-			while (u < w)
+			dest = desttop;
+			UINT8 *row_end = dest + w*vid.height;
+			while (dest < row_end)
 			{
-				dest[u] = consolebgmap[dest[u]];
-				u++;
+				*dest = consolebgmap[*dest];
+				dest += vid.height;
 			}
 		}
 	}
@@ -1527,9 +1545,8 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 //
 void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, UINT8 strength)
 {
-	UINT8 *dest;
+	UINT8 *dest, *desttop;
 	const UINT8 *deststop;
-	INT32 u;
 	UINT8 *fadetable;
 	UINT8 perplayershuffle = 0;
 
@@ -1666,7 +1683,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
 	if (y + h > vid.height)
 		h = vid.height-y;
 
-	dest = screens[0] + y*vid.width + x;
+	dest = desttop = screens[0] + y*vid.width + x;
 	deststop = screens[0] + vid.rowbytes * vid.height;
 
 	c &= 255;
@@ -1674,13 +1691,14 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
 	fadetable = ((color & 0xFF00) // Color is not palette index?
 		? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade.
 		: ((UINT8 *)R_GetTranslucencyTable((9-strength)+1) + color*256)); // Else, do TRANSMAP** fade.
-	for (;(--h >= 0) && dest < deststop; dest += vid.width)
+	for (;(--h >= 0) && desttop < deststop; desttop++)
 	{
-		u = 0;
-		while (u < w)
+		dest = desttop;
+		UINT8 *row_end = dest + w*vid.height;
+		while (dest < row_end)
 		{
-			dest[u] = fadetable[dest[u]];
-			u++;
+			*dest = fadetable[*dest];
+			dest += vid.height;
 		}
 	}
 }
@@ -1693,7 +1711,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
 	INT32 u, v;
 	fixed_t dx, dy, xfrac, yfrac;
 	const UINT8 *src, *deststop;
-	UINT8 *flat, *dest;
+	UINT8 *flat, *dest, *desttop;
 	size_t lflatsize, flatshift;
 
 #ifdef HWRENDER
@@ -1709,7 +1727,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
 
 	flat = W_CacheLumpNum(flatnum, PU_CACHE);
 
-	dest = screens[0] + y*vid.dup*vid.width + x*vid.dup;
+	dest = desttop = screens[0] + y*vid.dup*vid.width + x*vid.dup;
 	deststop = screens[0] + vid.rowbytes * vid.height;
 
 	// from V_DrawScaledPatch
@@ -1732,15 +1750,17 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
 	dy = FixedDiv(FRACUNIT, vid.dup<<(FRACBITS-2));
 
 	yfrac = 0;
-	for (v = 0; v < h; v++, dest += vid.width)
+	for (v = 0; v < h; v++, desttop++)
 	{
 		xfrac = 0;
 		src = flat + (((yfrac>>FRACBITS) & (lflatsize - 1)) << flatshift);
+		dest = desttop;
 		for (u = 0; u < w; u++)
 		{
-			if (&dest[u] > deststop)
+			if (dest > deststop)
 				return;
-			dest[u] = src[(xfrac>>FRACBITS)&(lflatsize-1)];
+			*dest = src[(xfrac>>FRACBITS)&(lflatsize-1)];
+			dest += vid.height;
 			xfrac += dx;
 		}
 		yfrac += dy;
@@ -1786,7 +1806,7 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength)
 		: (((color & 0x0F00) == 0x0B00) ? fadecolormap + (256 * FADECOLORMAPROWS) // Do white fadecolormap fade.
 		: colormaps)) + strength*256) // Do COLORMAP fade.
 		: ((UINT8 *)R_GetTranslucencyTable((9-strength)+1) + color*256)); // Else, do TRANSMAP** fade.
-		const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
+		const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
 		UINT8 *buf = screens[0];
 
 		// heavily simplified -- we don't need to know x or y
@@ -1799,7 +1819,7 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength)
 // Simple translucency with one color, over a set number of lines starting from the top.
 void V_DrawFadeConsBack(INT32 plines)
 {
-	UINT8 *deststop, *buf;
+	UINT8 *deststop, *dest, *desttop;
 
 #ifdef HWRENDER // not win32 only 19990829 by Kin
 	if (rendermode == render_opengl)
@@ -1812,15 +1832,24 @@ void V_DrawFadeConsBack(INT32 plines)
 
 	// heavily simplified -- we don't need to know x or y position,
 	// just the stop position
-	deststop = screens[0] + vid.rowbytes * min(plines, vid.height);
-	for (buf = screens[0]; buf < deststop; ++buf)
-		*buf = consolebgmap[*buf];
+	dest = desttop = screens[0];
+	deststop = screens[0] + min(plines, vid.height);
+	for (; desttop < deststop; desttop++)
+	{
+		dest = desttop;
+		UINT8 *row_end = dest + (vid.width * vid.height);
+		while (dest < row_end)
+		{
+			*dest = consolebgmap[*dest];
+			dest += vid.height;
+		}
+	}
 }
 
 // Very similar to F_DrawFadeConsBack, except we draw from the middle(-ish) of the screen to the bottom.
 void V_DrawPromptBack(INT32 boxheight, INT32 color)
 {
-	UINT8 *deststop, *buf;
+	UINT8 *deststop, *dest, *desttop;
 
 	if (color >= 256 && color < 512)
 	{
@@ -1874,13 +1903,25 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color)
 
 	// heavily simplified -- we don't need to know x or y position,
 	// just the start and stop positions
-	buf = deststop = screens[0] + vid.rowbytes * vid.height;
+	int height;
 	if (boxheight < 0)
-		buf += vid.rowbytes * boxheight;
+		height = -boxheight;
 	else // 4 lines of space plus gaps between and some leeway
-		buf -= vid.rowbytes * ((boxheight * 4) + (boxheight/2)*5);
-	for (; buf < deststop; ++buf)
-		*buf = promptbgmap[*buf];
+		height = boxheight*4 + boxheight/2*5;
+
+	dest = desttop = screens[0] + (vid.height - height);
+	deststop = screens[0] + vid.rowbytes * vid.width;
+	for (;(--height >= 0) && desttop < deststop; desttop++)
+	{
+		dest = desttop;
+
+		UINT8 *row_end = dest + (vid.width * vid.height);
+		while (dest < row_end)
+		{
+			*dest = promptbgmap[*dest];
+			dest += vid.height;
+		}
+	}
 }
 
 // Gets string colormap, used for 0x80 color codes
@@ -2509,7 +2550,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 	{
 		UINT8 *tmpscr = screens[4];
 		UINT8 *srcscr = screens[0];
-		INT32 y;
+		INT32 y, x;
 		// Set disStart to a range from 0 to FINEANGLE, incrementing by 128 per tic
 		angle_t disStart = (((leveltime-1)*128) + (rendertimefrac / (FRACUNIT/128))) & FINEMASK;
 		INT32 newpix;
@@ -2519,6 +2560,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 		for (y = yoffset; y < yoffset+height; y++)
 		{
 			sine = (FINESINE(disStart)*5)>>FRACBITS;
+			/*
 			newpix = abs(sine);
 
 			if (sine < 0)
@@ -2543,9 +2585,8 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 					newpix--;
 				}
 			}
+			*/
 
-/*
-Unoptimized version
 			for (x = 0; x < vid.width*vid.bpp; x++)
 			{
 				newpix = (x + sine);
@@ -2555,8 +2596,8 @@ Unoptimized version
 				else if (newpix >= vid.width)
 					newpix = vid.width-1;
 
-				tmpscr[y*vid.width + x] = srcscr[y*vid.width+newpix]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
-			}*/
+				tmpscr[y + x*vid.height] = srcscr[y+newpix*vid.height]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
+			}
 			disStart += 22;//the offset into the displacement map, increment each game loop
 			disStart &= FINEMASK; //clip it to FINEMASK
 		}
@@ -2577,8 +2618,8 @@ Unoptimized version
 		{
 			for (x = 0; x < vid.width; x++)
 			{
-				tmpscr[y*vid.width + x]
-					=     colormaps[*(transme     + (srcscr   [y*vid.width+x ] <<8) + (tmpscr[y*vid.width+x]))];
+				tmpscr[y + x*vid.height]
+					=     colormaps[*(transme     + (srcscr   [y+x*vid.height] <<8) + (tmpscr[y+x*vid.height]))];
 			}
 		}
 		VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
@@ -2588,10 +2629,11 @@ Unoptimized version
 	{
 		UINT8 *tmpscr = screens[4];
 		UINT8 *srcscr = screens[0];
-		INT32 y, y2;
+		INT32 y, y2, x;
 
 		for (y = yoffset, y2 = yoffset+height - 1; y < yoffset+height; y++, y2--)
-			M_Memcpy(&tmpscr[y2*vid.width], &srcscr[y*vid.width], vid.width);
+			for (x = 0; x < vid.width; x++)
+				tmpscr[y2+x*vid.height] = srcscr[y+x*vid.height];
 
 		VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
 				vid.width*vid.bpp, height, vid.width*vid.bpp, vid.width);
@@ -2600,16 +2642,12 @@ Unoptimized version
 	{
 		UINT8 *tmpscr = screens[4];
 		UINT8 *srcscr = screens[0];
-		INT32 y;
+		INT32 y, x;
 
 		// Make sure table is built
 		if (heatshifter == NULL || lastheight != height)
 		{
-			if (heatshifter)
-				Z_Free(heatshifter);
-
-			heatshifter = Z_Calloc(height * sizeof(boolean), PU_STATIC, NULL);
-
+			heatshifter = Z_Realloc(heatshifter, height * sizeof(boolean), PU_STATIC, NULL);
 			for (y = 0; y < height; y++)
 			{
 				if (M_RandomChance(FRACUNIT/8)) // 12.5%
@@ -2625,11 +2663,12 @@ Unoptimized version
 			if (heatshifter[heatindex[view]++])
 			{
 				// Shift this row of pixels to the right by 2
-				tmpscr[y*vid.width] = srcscr[y*vid.width];
-				M_Memcpy(&tmpscr[y*vid.width+vid.dup], &srcscr[y*vid.width], vid.width-vid.dup);
+				tmpscr[y] = srcscr[y];
+				for (x = vid.dup; x < vid.width; x++)
+					tmpscr[y+x*vid.height] = srcscr[y+(x-vid.dup)*vid.height];
 			}
-			else
-				M_Memcpy(&tmpscr[y*vid.width], &srcscr[y*vid.width], vid.width);
+			else for (x = 0; x < vid.width; x++)
+				tmpscr[y+x*vid.height] = srcscr[y+x*vid.height];
 
 			heatindex[view] %= height;
 		}
@@ -2699,7 +2738,7 @@ void V_Init(void)
 {
 	INT32 i;
 	UINT8 *base = vid.buffer;
-	const INT32 screensize = vid.rowbytes * vid.height;
+	const INT32 screensize = vid.rowbytes * vid.width;
 
 	LoadMapPalette();
 
diff --git a/src/y_inter.c b/src/y_inter.c
index d7e644567e..f6eb93fc51 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -325,7 +325,7 @@ void Y_ConsiderScreenBuffer(void)
 	y_buffer->source_bpp = vid.bpp;
 	y_buffer->source_rowbytes = vid.rowbytes;
 	y_buffer->source_picture = ZZ_Alloc(y_buffer->source_width*vid.bpp * y_buffer->source_height);
-	VID_BlitLinearScreen(screens[1], y_buffer->source_picture, vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
+	VID_BlitLinearScreen(screens[1], y_buffer->source_picture, vid.width*vid.bpp, vid.height, vid.rowbytes, vid.rowbytes);
 
 	// Make the rescaled screen buffer
 	Y_RescaleScreenBuffer();
@@ -364,9 +364,9 @@ static void Y_RescaleScreenBuffer(void)
 	rowfrac = FixedDiv(FRACUNIT, yscalefac);
 	colfrac = FixedDiv(FRACUNIT, scalefac);
 
-	for (sy = 0, dy = 0; sy < (y_buffer->source_height << FRACBITS) && dy < y_buffer->target_height; sy += rowfrac, dy++)
-		for (sx = 0, dx = 0; sx < (y_buffer->source_width << FRACBITS) && dx < y_buffer->target_width; sx += colfrac, dx += y_buffer->target_bpp)
-			dest[(dy * y_buffer->target_rowbytes) + dx] = y_buffer->source_picture[((sy>>FRACBITS) * y_buffer->source_width) + (sx>>FRACBITS)];
+	for (sx = 0, dx = 0; sx < (y_buffer->source_width << FRACBITS) && dx < y_buffer->target_width; sx += colfrac, dx += y_buffer->target_bpp)
+		for (sy = 0, dy = 0; sy < (y_buffer->source_height << FRACBITS) && dy < y_buffer->target_height; sy += rowfrac, dy++)
+			dest[(dx * y_buffer->target_rowbytes) + dy] = y_buffer->source_picture[((sx>>FRACBITS) * y_buffer->source_height) + (sy>>FRACBITS)];
 }
 
 //
@@ -412,7 +412,7 @@ void Y_IntermissionDrawer(void)
 		{
 			// no y_buffer
 			if (y_buffer == NULL)
-				VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
+				VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.rowbytes, vid.rowbytes);
 			else
 			{
 				// Maybe the resolution changed?
@@ -420,7 +420,7 @@ void Y_IntermissionDrawer(void)
 					Y_RescaleScreenBuffer();
 
 				// Blit the already-scaled screen buffer to the current screen
-				VID_BlitLinearScreen(y_buffer->target_picture, screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
+				VID_BlitLinearScreen(y_buffer->target_picture, screens[0], vid.width*vid.bpp, vid.height, vid.rowbytes, vid.rowbytes);
 			}
 		}
 #ifdef HWRENDER
-- 
GitLab


From f7137bccaa260d514a5c4d0ab8f3f6eed4eeece8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Sat, 29 Mar 2025 17:37:00 +0100
Subject: [PATCH 03/14] Revert "Transpose backbuffer"

This reverts commit 65a1baac5f9b26579a305afb7184507c25293576.
---
 src/am_map.c       |   2 +-
 src/d_main.c       |   6 +-
 src/f_wipe.c       |   4 +-
 src/r_bbox.c       |   2 +-
 src/r_draw8.c      | 244 ++++++++++++++++++++-------------------------
 src/r_draw8_npo2.c | 100 +++++++++----------
 src/r_plane.c      |   6 +-
 src/r_things.c     |   2 +-
 src/sdl/i_video.c  |  37 +++----
 src/v_video.c      | 217 +++++++++++++++++-----------------------
 src/y_inter.c      |  12 +--
 11 files changed, 277 insertions(+), 355 deletions(-)

diff --git a/src/am_map.c b/src/am_map.c
index 859569d487..36b62f2f9b 100644
--- a/src/am_map.c
+++ b/src/am_map.c
@@ -787,7 +787,7 @@ static void AM_drawPixel(INT32 xx, INT32 yy, INT32 cc)
 	UINT8 *dest = screens[0];
 	if (xx < 0 || yy < 0 || xx >= vid.width || yy >= vid.height)
 		return; // off the screen
-	dest[(xx*vid.height) + yy] = cc;
+	dest[(yy*vid.width) + xx] = cc;
 }
 
 //
diff --git a/src/d_main.c b/src/d_main.c
index 5bdeac7609..f1d9d6e284 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -495,7 +495,7 @@ static void D_Display(void)
 				PS_START_TIMING(ps_rendercalltime);
 				if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
 				{
-					topleft = screens[0] + viewwindowx*vid.height + viewwindowy;
+					topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
 					objectsdrawn = 0;
 	#ifdef HWRENDER
 					if (rendermode != render_soft)
@@ -518,7 +518,7 @@ static void D_Display(void)
 					{
 						viewwindowy = vid.height / 2;
 
-						topleft = screens[0] + viewwindowx*vid.height + viewwindowy;
+						topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
 
 						R_RenderPlayerView(&players[secondarydisplayplayer]);
 
@@ -547,7 +547,7 @@ static void D_Display(void)
 			{
 				if (rendermode == render_soft)
 				{
-					VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.rowbytes, vid.rowbytes);
+					VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
 					Y_ConsiderScreenBuffer();
 					usebuffer = true;
 				}
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 349348e2a5..1ea32d0ebe 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -440,7 +440,7 @@ void F_WipeStartScreen(void)
 	}
 #endif
 	wipe_scr_start = screens[3];
-	M_Memcpy(wipe_scr_start, screens[0], vid.width*vid.height);
+	I_ReadScreen(wipe_scr_start);
 #endif
 }
 
@@ -457,7 +457,7 @@ void F_WipeEndScreen(void)
 	}
 #endif
 	wipe_scr_end = screens[4];
-	M_Memcpy(wipe_scr_end, screens[0], vid.width*vid.height);
+	I_ReadScreen(wipe_scr_end);
 	V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
 #endif
 }
diff --git a/src/r_bbox.c b/src/r_bbox.c
index a098c2fbbd..6d61631829 100644
--- a/src/r_bbox.c
+++ b/src/r_bbox.c
@@ -70,7 +70,7 @@ raster_bbox_seg
 
 	while (y < h)
 	{
-		topleft[x*vid.height + y] = pixel;
+		topleft[x + y * vid.width] = pixel;
 		y++;
 	}
 }
diff --git a/src/r_draw8.c b/src/r_draw8.c
index 614c6e4267..349139f5e4 100644
--- a/src/r_draw8.c
+++ b/src/r_draw8.c
@@ -40,7 +40,7 @@ void R_DrawColumn_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	count++;
 
@@ -70,7 +70,7 @@ void R_DrawColumn_8(void)
 				//  using a lighting/special effects LUT.
 				// heightmask is the Tutti-Frutti fix
 				*dest = colormap[source[frac>>FRACBITS]];
-				dest++;
+				dest += vid.width;
 
 #if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue
 				// Avoid overflow.
@@ -88,10 +88,10 @@ void R_DrawColumn_8(void)
 			while ((count -= 2) >= 0) // texture height is a power of 2
 			{
 				*dest = colormap[source[(frac>>FRACBITS) & heightmask]];
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 				*dest = colormap[source[(frac>>FRACBITS) & heightmask]];
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -121,7 +121,7 @@ void R_DrawColumnClamped_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	count++;
 
@@ -155,7 +155,7 @@ void R_DrawColumnClamped_8(void)
 				idx = frac>>FRACBITS;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = colormap[source[idx]];
-				dest++;
+				dest += vid.width;
 
 				// Avoid overflow.
 #if __SIZEOF_POINTER__ < 8
@@ -175,12 +175,12 @@ void R_DrawColumnClamped_8(void)
 				idx = (frac>>FRACBITS) & heightmask;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = colormap[source[idx]];
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 				idx = (frac>>FRACBITS) & heightmask;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = colormap[source[idx]];
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -211,7 +211,7 @@ void R_Draw2sMultiPatchColumn_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	count++;
 
@@ -246,7 +246,7 @@ void R_Draw2sMultiPatchColumn_8(void)
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
 
-				dest++;
+				dest += vid.width;
 
 				// Avoid overflow.
 #if __SIZEOF_POINTER__ < 8
@@ -266,12 +266,12 @@ void R_Draw2sMultiPatchColumn_8(void)
 				val = source[(frac>>FRACBITS) & heightmask];
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 				val = source[(frac>>FRACBITS) & heightmask];
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -302,7 +302,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	count++;
 
@@ -339,7 +339,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void)
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(transmap + (colormap[val]<<8) + (*dest));
 
-				dest++;
+				dest += vid.width;
 
 				// Avoid overflow.
 				if (fracstep > 0x7FFFFFFF - frac)
@@ -358,12 +358,12 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void)
 				val = source[(frac>>FRACBITS) & heightmask];
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(transmap + (colormap[val]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 				val = source[(frac>>FRACBITS) & heightmask];
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(transmap + (colormap[val]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -398,7 +398,7 @@ void R_DrawShadeColumn_8(void)
 		I_Error("R_DrawShadeColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
 #endif
 
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -408,7 +408,7 @@ void R_DrawShadeColumn_8(void)
 	do
 	{
 		*dest = colormaps[(dc_source[frac>>FRACBITS] <<8) + (*dest)];
-		dest++;
+		dest += vid.width;
 		frac += fracstep;
 	} while (count--);
 }
@@ -434,7 +434,7 @@ void R_DrawTranslucentColumn_8(void)
 		I_Error("R_DrawTranslucentColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
 #endif
 
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -465,7 +465,7 @@ void R_DrawTranslucentColumn_8(void)
 				// using a lighting/special effects LUT.
 				// heightmask is the Tutti-Frutti fix
 				*dest = *(transmap + (colormap[source[frac>>FRACBITS]]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				if ((frac += fracstep) >= heightmask)
 					frac -= heightmask;
 			}
@@ -476,10 +476,10 @@ void R_DrawTranslucentColumn_8(void)
 			while ((count -= 2) >= 0) // texture height is a power of 2
 			{
 				*dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 				*dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -507,7 +507,7 @@ void R_DrawTranslucentColumnClamped_8(void)
 		I_Error("R_DrawTranslucentColumnClamped_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
 #endif
 
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -541,7 +541,7 @@ void R_DrawTranslucentColumnClamped_8(void)
 				idx = frac>>FRACBITS;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				if ((frac += fracstep) >= heightmask)
 					frac -= heightmask;
 			}
@@ -554,12 +554,12 @@ void R_DrawTranslucentColumnClamped_8(void)
 				idx = (frac>>FRACBITS)&heightmask;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 				idx = (frac>>FRACBITS)&heightmask;
 				if (idx >= 0 && idx < dc_postlength)
 					*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -587,7 +587,7 @@ void R_DrawDropShadowColumn_8(void)
 	if (count <= 0) // Zero length, column does not exceed a pixel.
 		return;
 
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	{
 #define DSCOLOR 31 // palette index for the color of the shadow
@@ -596,9 +596,9 @@ void R_DrawDropShadowColumn_8(void)
 		while ((count -= 2) >= 0)
 		{
 			*dest = *(transmap_offset + (*dest));
-			dest++;
+			dest += vid.width;
 			*dest = *(transmap_offset + (*dest));
-			dest++;
+			dest += vid.width;
 		}
 		if (count & 1)
 			*dest = *(transmap_offset + (*dest));
@@ -620,7 +620,7 @@ void R_DrawTranslatedTranslucentColumn_8(void)
 	if (count <= 0) // Zero length, column does not exceed a pixel.
 		return;
 
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -650,7 +650,7 @@ void R_DrawTranslatedTranslucentColumn_8(void)
 
 				*dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest));
 
-				dest++;
+				dest += vid.width;
 				if ((frac += fracstep) >= heightmask)
 					frac -= heightmask;
 			}
@@ -661,10 +661,10 @@ void R_DrawTranslatedTranslucentColumn_8(void)
 			while ((count -= 2) >= 0) // texture height is a power of 2
 			{
 				*dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 				*dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest));
-				dest++;
+				dest += vid.width;
 				frac += fracstep;
 			}
 			if (count & 1)
@@ -693,7 +693,7 @@ void R_DrawTranslatedColumn_8(void)
 		I_Error("R_DrawTranslatedColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
 #endif
 
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	// Looks familiar.
 	fracstep = dc_iscale;
@@ -709,7 +709,7 @@ void R_DrawTranslatedColumn_8(void)
 		//  is mapped to gray, red, black/indigo.
 		*dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
 
-		dest++;
+		dest += vid.width;
 
 		frac += fracstep;
 	} while (count--);
@@ -734,7 +734,7 @@ void R_DrawSpan_8 (void)
 	UINT8 *restrict source;
 	UINT8 *restrict colormap;
 	UINT8 *restrict dest;
-	const UINT8 *restrict deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *restrict deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 
@@ -753,12 +753,11 @@ void R_DrawSpan_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
-	if (dest > deststop)
+	if (dest+8 > deststop)
 		return;
 
-	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -799,11 +798,9 @@ void R_DrawSpan_8 (void)
 		dest += 8;
 		count -= 8;
 	}
-	*/
 	while (count-- && dest <= deststop)
 	{
-		*dest = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]];
-		dest += vid.height;
+		*dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]];
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -835,7 +832,7 @@ void R_DrawTiltedSpan_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -850,7 +847,7 @@ void R_DrawTiltedSpan_8(void)
 		colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 
 		*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -884,7 +881,7 @@ void R_DrawTiltedSpan_8(void)
 		{
 			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 			*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
-			dest += vid.height;
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -921,7 +918,7 @@ void R_DrawTiltedSpan_8(void)
 			{
 				colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 				*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
-				dest += vid.height;
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
@@ -956,7 +953,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -970,7 +967,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
 
 		colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 		*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1004,7 +1001,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
 		{
 			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
-			dest += vid.height;
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -1041,7 +1038,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
 			{
 				colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 				*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
-				dest += vid.height;
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
@@ -1077,8 +1074,8 @@ void R_DrawTiltedWaterSpan_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
-	dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
+	dest = &topleft[ds_y*vid.width + ds_x1];
+	dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -1092,7 +1089,7 @@ void R_DrawTiltedWaterSpan_8(void)
 
 		colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 		*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++);
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1125,9 +1122,8 @@ void R_DrawTiltedWaterSpan_8(void)
 		for (i = SPANSIZE-1; i >= 0; i--)
 		{
 			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc);
-			dest += vid.height;
-			dsrc += vid.height;
+			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++);
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -1142,7 +1138,7 @@ void R_DrawTiltedWaterSpan_8(void)
 			u = (INT64)(startu);
 			v = (INT64)(startv);
 			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc);
+			*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++);
 		}
 		else
 		{
@@ -1163,9 +1159,8 @@ void R_DrawTiltedWaterSpan_8(void)
 			for (; width != 0; width--)
 			{
 				colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-				*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc);
-				dest += vid.height;
-				dsrc += vid.height;
+				*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++);
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
@@ -1199,7 +1194,7 @@ void R_DrawTiltedSplat_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -1217,7 +1212,7 @@ void R_DrawTiltedSplat_8(void)
 		if (val != TRANSPARENTPIXEL)
 			*dest = colormap[val];
 
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1253,7 +1248,7 @@ void R_DrawTiltedSplat_8(void)
 			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 			if (val != TRANSPARENTPIXEL)
 				*dest = colormap[val];
-			dest += vid.height;
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -1294,7 +1289,7 @@ void R_DrawTiltedSplat_8(void)
 				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
-				dest += vid.height;
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
@@ -1328,7 +1323,7 @@ void R_DrawTiltedTranslucentSplat_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = ds_source;
 	//colormap = ds_colormap;
 
@@ -1347,7 +1342,7 @@ void R_DrawTiltedTranslucentSplat_8(void)
 		if (val != TRANSPARENTPIXEL)
 			*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
 
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1383,7 +1378,7 @@ void R_DrawTiltedTranslucentSplat_8(void)
 			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 			if (val != TRANSPARENTPIXEL)
 				*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-			dest += vid.height;
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -1424,7 +1419,7 @@ void R_DrawTiltedTranslucentSplat_8(void)
 				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-				dest += vid.height;
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
@@ -1438,7 +1433,6 @@ void R_DrawTiltedTranslucentSplat_8(void)
 */
 void R_DrawSplat_8 (void)
 {
-	return;
 	fixed_t xposition;
 	fixed_t yposition;
 	fixed_t xstep, ystep;
@@ -1446,7 +1440,7 @@ void R_DrawSplat_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1466,9 +1460,8 @@ void R_DrawSplat_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
-	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -1544,13 +1537,12 @@ void R_DrawSplat_8 (void)
 		dest += 8;
 		count -= 8;
 	}
-	*/
 	while (count-- && dest <= deststop)
 	{
 		val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
 		if (val != TRANSPARENTPIXEL)
 			*dest = colormap[val];
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1568,7 +1560,7 @@ void R_DrawTranslucentSplat_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1588,9 +1580,8 @@ void R_DrawTranslucentSplat_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
-	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -1647,13 +1638,12 @@ void R_DrawTranslucentSplat_8 (void)
 		dest += 8;
 		count -= 8;
 	}
-	*/
 	while (count-- && dest <= deststop)
 	{
 		val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
 		if (val != TRANSPARENTPIXEL)
 			*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1672,7 +1662,7 @@ void R_DrawFloorSprite_8 (void)
 	UINT8 *colormap;
 	UINT8 *translation;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1693,9 +1683,8 @@ void R_DrawFloorSprite_8 (void)
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
-	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -1760,13 +1749,12 @@ void R_DrawFloorSprite_8 (void)
 		dest += 8;
 		count -= 8;
 	}
-	*/
 	while (count-- && dest <= deststop)
 	{
 		val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
 		if (val & 0xFF00)
 			*dest = colormap[translation[val & 0xFF]];
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1785,7 +1773,7 @@ void R_DrawTranslucentFloorSprite_8 (void)
 	UINT8 *colormap;
 	UINT8 *translation;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1806,9 +1794,8 @@ void R_DrawTranslucentFloorSprite_8 (void)
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
-	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -1865,13 +1852,12 @@ void R_DrawTranslucentFloorSprite_8 (void)
 		dest += 8;
 		count -= 8;
 	}
-	*/
 	while (count-- && dest <= deststop)
 	{
 		val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
 		if (val & 0xFF00)
 			*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1903,7 +1889,7 @@ void R_DrawTiltedFloorSprite_8(void)
 	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
 	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
@@ -1937,7 +1923,7 @@ void R_DrawTiltedFloorSprite_8(void)
 			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 			if (val & 0xFF00)
 				*dest = colormap[translation[val & 0xFF]];
-			dest += vid.height;
+			dest++;
 
 			u += stepu;
 			v += stepv;
@@ -1977,7 +1963,7 @@ void R_DrawTiltedFloorSprite_8(void)
 				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 				if (val & 0xFF00)
 					*dest = colormap[translation[val & 0xFF]];
-				dest += vid.height;
+				dest++;
 
 				u += stepu;
 				v += stepv;
@@ -2012,7 +1998,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(void)
 	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
 	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
@@ -2046,7 +2032,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(void)
 			val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 			if (val & 0xFF00)
 				*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-			dest += vid.height;
+			dest++;
 
 			u += stepu;
 			v += stepv;
@@ -2086,7 +2072,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(void)
 				val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
 				if (val & 0xFF00)
 					*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-				dest += vid.height;
+				dest++;
 
 				u += stepu;
 				v += stepv;
@@ -2107,7 +2093,7 @@ void R_DrawTranslucentSpan_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -2127,9 +2113,8 @@ void R_DrawTranslucentSpan_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
-	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -2170,12 +2155,11 @@ void R_DrawTranslucentSpan_8 (void)
 		dest += 8;
 		count -= 8;
 	}
-	*/
 	while (count-- && dest <= deststop)
 	{
 		val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
 		*dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest);
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -2206,11 +2190,10 @@ void R_DrawWaterSpan_8(void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
-	dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
+	dest = &topleft[ds_y*vid.width + ds_x1];
+	dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
 	count = ds_x2 - ds_x1 + 1;
 
-	/*
 	while (count >= 8)
 	{
 		// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
@@ -2251,12 +2234,9 @@ void R_DrawWaterSpan_8(void)
 		dest += 8;
 		count -= 8;
 	}
-	*/
 	while (count--)
 	{
-		*dest = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc)];
-		dest += vid.height;
-		dsrc += vid.height;
+		*dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)];
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -2273,11 +2253,10 @@ void R_DrawFogSpan_8(void)
 	size_t count;
 
 	colormap = ds_colormap;
-	dest = &topleft[ds_y  + ds_x1*vid.height];
+	dest = &topleft[ds_y *vid.width + ds_x1];
 
 	count = ds_x2 - ds_x1 + 1;
 
-	/*
 	while (count >= 4)
 	{
 		dest[0] = colormap[dest[0]];
@@ -2288,12 +2267,11 @@ void R_DrawFogSpan_8(void)
 		dest += 4;
 		count -= 4;
 	}
-	*/
 
 	while (count--)
 	{
 		*dest = colormap[*dest];
-		dest += vid.height;
+		dest++;
 	}
 }
 
@@ -2304,7 +2282,7 @@ void R_DrawTiltedFogSpan_8(void)
 {
 	int width = ds_x2 - ds_x1;
 
-	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
+	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
 
 	R_CalcSlopeLight();
 
@@ -2312,7 +2290,7 @@ void R_DrawTiltedFogSpan_8(void)
 	{
 		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 		*dest = colormap[*dest];
-		dest += vid.height;
+		dest++;
 	} while (--width >= 0);
 }
 
@@ -2324,7 +2302,7 @@ void R_DrawSolidColorSpan_8(void)
 	size_t count = (ds_x2 - ds_x1 + 1);
 
 	UINT8 source = ds_colormap[ds_source[0]];
-	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
+	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
 
 	memset(dest, source, count);
 }
@@ -2337,14 +2315,14 @@ void R_DrawTransSolidColorSpan_8(void)
 	size_t count = (ds_x2 - ds_x1 + 1);
 
 	UINT8 source = ds_colormap[ds_source[0]];
-	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
+	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
 
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	while (count-- && dest <= deststop)
 	{
 		*dest = *(ds_transmap + (source << 8) + *dest);
-		dest += vid.height;
+		dest++;
 	}
 }
 
@@ -2356,15 +2334,14 @@ void R_DrawTiltedSolidColorSpan_8(void)
 	int width = ds_x2 - ds_x1;
 
 	UINT8 source = ds_source[0];
-	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
+	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
 
 	R_CalcSlopeLight();
 
 	do
 	{
 		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-		*dest = colormap[source];
-		dest += vid.height;
+		*dest++ = colormap[source];
 	} while (--width >= 0);
 }
 
@@ -2376,7 +2353,7 @@ void R_DrawTiltedTransSolidColorSpan_8(void)
 	int width = ds_x2 - ds_x1;
 
 	UINT8 source = ds_source[0];
-	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
+	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
 
 	R_CalcSlopeLight();
 
@@ -2384,7 +2361,7 @@ void R_DrawTiltedTransSolidColorSpan_8(void)
 	{
 		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
 		*dest = *(ds_transmap + (colormap[source] << 8) + *dest);
-		dest += vid.height;
+		dest++;
 	} while (--width >= 0);
 }
 
@@ -2395,17 +2372,16 @@ void R_DrawWaterSolidColorSpan_8(void)
 {
 	UINT8 source = ds_source[0];
 	UINT8 *colormap = ds_colormap;
-	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
-	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
+	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
+	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	while (count-- && dest <= deststop)
 	{
-		*dest = colormap[*(ds_transmap + (source << 8) + *dsrc)];
-		dest += vid.height;
-		dsrc += vid.height;
+		*dest = colormap[*(ds_transmap + (source << 8) + *dsrc++)];
+		dest++;
 	}
 }
 
@@ -2417,17 +2393,15 @@ void R_DrawTiltedWaterSolidColorSpan_8(void)
 	int width = ds_x2 - ds_x1;
 
 	UINT8 source = ds_source[0];
-	UINT8 *dest = &topleft[ds_y + ds_x1*vid.height];
-	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
+	UINT8 *dest = &topleft[ds_y*vid.width + ds_x1];
+	UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
 
 	R_CalcSlopeLight();
 
 	do
 	{
 		UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
-		*dest = *(ds_transmap + (colormap[source] << 8) + *dsrc);
-		dest += vid.height;
-		dsrc += vid.height;
+		*dest++ = *(ds_transmap + (colormap[source] << 8) + *dsrc++);
 	} while (--width >= 0);
 }
 
@@ -2451,14 +2425,14 @@ void R_DrawFogColumn_8(void)
 #endif
 
 	// Framebuffer destination address.
-	dest = &topleft[dc_yl + dc_x*vid.height];
+	dest = &topleft[dc_yl*vid.width + dc_x];
 
 	// Determine scaling, which is the only mapping to be done.
 	do
 	{
 		// Simple. Apply the colormap to what's already on the screen.
 		*dest = dc_colormap[*dest];
-		dest += vid.height;
+		dest += vid.width;
 	} while (count--);
 }
 
diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c
index 873d03186d..f3f2254f5e 100644
--- a/src/r_draw8_npo2.c
+++ b/src/r_draw8_npo2.c
@@ -37,7 +37,7 @@ void R_DrawSpan_NPO2_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 
@@ -46,7 +46,7 @@ void R_DrawSpan_NPO2_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
 	if (dest+8 > deststop)
 		return;
@@ -85,8 +85,7 @@ void R_DrawSpan_NPO2_8 (void)
 		x = (xposition >> FRACBITS);
 		y = (yposition >> FRACBITS);
 
-		*dest = colormap[source[((y * ds_flatwidth) + x)]];
-		dest += vid.height;
+		*dest++ = colormap[source[((y * ds_flatwidth) + x)]];
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -121,7 +120,7 @@ void R_DrawTiltedSpan_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -152,7 +151,7 @@ void R_DrawTiltedSpan_NPO2_8(void)
 
 			*dest = colormap[source[((y * ds_flatwidth) + x)]];
 		}
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -202,7 +201,7 @@ void R_DrawTiltedSpan_NPO2_8(void)
 
 				*dest = colormap[source[((y * ds_flatwidth) + x)]];
 			}
-			dest += vid.height;
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -271,7 +270,7 @@ void R_DrawTiltedSpan_NPO2_8(void)
 
 					*dest = colormap[source[((y * ds_flatwidth) + x)]];
 				}
-				dest += vid.height;
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
@@ -309,7 +308,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -339,7 +338,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
 
 			*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest);
 		}
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -389,7 +388,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
 
 				*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest);
 			}
-			dest += vid.height;
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -458,7 +457,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
 
 					*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest);
 				}
-				dest += vid.height;
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
@@ -495,7 +494,7 @@ void R_DrawTiltedSplat_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -530,7 +529,7 @@ void R_DrawTiltedSplat_NPO2_8(void)
 		if (val != TRANSPARENTPIXEL)
 			*dest = colormap[val];
 
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -582,7 +581,7 @@ void R_DrawTiltedSplat_NPO2_8(void)
 			}
 			if (val != TRANSPARENTPIXEL)
 				*dest = colormap[val];
-			dest += vid.height;
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -655,7 +654,7 @@ void R_DrawTiltedSplat_NPO2_8(void)
 				}
 				if (val != TRANSPARENTPIXEL)
 					*dest = colormap[val];
-				dest += vid.height;
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
@@ -692,7 +691,7 @@ void R_DrawTiltedTranslucentSplat_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = ds_source;
 	//colormap = ds_colormap;
 
@@ -728,7 +727,7 @@ void R_DrawTiltedTranslucentSplat_NPO2_8(void)
 		if (val != TRANSPARENTPIXEL)
 			*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
 
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -780,7 +779,7 @@ void R_DrawTiltedTranslucentSplat_NPO2_8(void)
 			}
 			if (val != TRANSPARENTPIXEL)
 				*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-			dest += vid.height;
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -853,7 +852,7 @@ void R_DrawTiltedTranslucentSplat_NPO2_8(void)
 				}
 				if (val != TRANSPARENTPIXEL)
 					*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-				dest += vid.height;
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
@@ -876,7 +875,7 @@ void R_DrawSplat_NPO2_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -886,7 +885,7 @@ void R_DrawSplat_NPO2_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -924,7 +923,7 @@ void R_DrawSplat_NPO2_8 (void)
 		val = source[((y * ds_flatwidth) + x)];
 		if (val != TRANSPARENTPIXEL)
 			*dest = colormap[val];
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -944,7 +943,7 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -954,7 +953,7 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -992,7 +991,7 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
 		val = source[((y * ds_flatwidth) + x)];
 		if (val != TRANSPARENTPIXEL)
 			*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1013,7 +1012,7 @@ void R_DrawFloorSprite_NPO2_8 (void)
 	UINT8 *translation;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1024,7 +1023,7 @@ void R_DrawFloorSprite_NPO2_8 (void)
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -1062,7 +1061,7 @@ void R_DrawFloorSprite_NPO2_8 (void)
 		val = source[((y * ds_flatwidth) + x)];
 		if (val & 0xFF00)
 			*dest = colormap[translation[val & 0xFF]];
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1083,7 +1082,7 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void)
 	UINT8 *translation;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1094,7 +1093,7 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void)
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -1132,7 +1131,7 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void)
 		val = source[((y * ds_flatwidth) + x)];
 		if (val & 0xFF00)
 			*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1167,7 +1166,7 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
 	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
 	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
@@ -1215,7 +1214,7 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
 			val = source[((y * ds_flatwidth) + x)];
 			if (val & 0xFF00)
 				*dest = colormap[translation[val & 0xFF]];
-			dest += vid.height;
+			dest++;
 
 			u += stepu;
 			v += stepv;
@@ -1285,7 +1284,7 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
 				val = source[((y * ds_flatwidth) + x)];
 				if (val & 0xFF00)
 					*dest = colormap[translation[val & 0xFF]];
-				dest += vid.height;
+				dest++;
 
 				u += stepu;
 				v += stepv;
@@ -1323,7 +1322,7 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
 	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
 	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 	source = (UINT16 *)ds_source;
 	colormap = ds_colormap;
 	translation = ds_translation;
@@ -1371,7 +1370,7 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
 			val = source[((y * ds_flatwidth) + x)];
 			if (val & 0xFF00)
 				*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-			dest += vid.height;
+			dest++;
 
 			u += stepu;
 			v += stepv;
@@ -1441,7 +1440,7 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
 				val = source[((y * ds_flatwidth) + x)];
 				if (val & 0xFF00)
 					*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
-				dest += vid.height;
+				dest++;
 
 				u += stepu;
 				v += stepv;
@@ -1464,7 +1463,7 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
 	UINT8 *source;
 	UINT8 *colormap;
 	UINT8 *dest;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 	UINT32 val;
@@ -1474,7 +1473,7 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
+	dest = &topleft[ds_y*vid.width + ds_x1];
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -1511,7 +1510,7 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
 		y = (yposition >> FRACBITS);
 		val = ((y * ds_flatwidth) + x);
 		*dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest);
-		dest += vid.height;
+		dest++;
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1529,7 +1528,7 @@ void R_DrawWaterSpan_NPO2_8(void)
 	UINT8 *colormap;
 	UINT8 *dest;
 	UINT8 *dsrc;
-	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+	const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 
 	size_t count = (ds_x2 - ds_x1 + 1);
 
@@ -1538,8 +1537,8 @@ void R_DrawWaterSpan_NPO2_8(void)
 
 	source = ds_source;
 	colormap = ds_colormap;
-	dest = &topleft[ds_y + ds_x1*vid.height];
-	dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
+	dest = &topleft[ds_y*vid.width + ds_x1];
+	dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
 
 	fixedwidth = ds_flatwidth << FRACBITS;
 	fixedheight = ds_flatheight << FRACBITS;
@@ -1574,8 +1573,7 @@ void R_DrawWaterSpan_NPO2_8(void)
 
 		x = (xposition >> FRACBITS);
 		y = (yposition >> FRACBITS);
-		*dest = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)];
-		dest += vid.height;
+		*dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)];
 		xposition += xstep;
 		yposition += ystep;
 	}
@@ -1611,8 +1609,8 @@ void R_DrawTiltedWaterSpan_NPO2_8(void)
 
 	R_CalcSlopeLight();
 
-	dest = &topleft[ds_y + ds_x1*vid.height];
-	dsrc = screens[1] + (ds_y+ds_bgofs) + ds_x1*vid.height;
+	dest = &topleft[ds_y*vid.width + ds_x1];
+	dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
 	source = ds_source;
 
 #if 0	// The "perfect" reference version of this routine. Pretty slow.
@@ -1642,7 +1640,7 @@ void R_DrawTiltedWaterSpan_NPO2_8(void)
 
 			*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++);
 		}
-		dest += vid.height;
+		dest++;
 		iz += ds_sz.x;
 		uz += ds_su.x;
 		vz += ds_sv.x;
@@ -1692,7 +1690,7 @@ void R_DrawTiltedWaterSpan_NPO2_8(void)
 
 				*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++);
 			}
-			dest += vid.height;
+			dest++;
 			u += stepu;
 			v += stepv;
 		}
@@ -1761,7 +1759,7 @@ void R_DrawTiltedWaterSpan_NPO2_8(void)
 
 					*dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++);
 				}
-				dest += vid.height;
+				dest++;
 				u += stepu;
 				v += stepv;
 			}
diff --git a/src/r_plane.c b/src/r_plane.c
index 3a0c74d618..bfc7614006 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -1046,9 +1046,9 @@ void R_DrawSinglePlane(visplane_t *pl)
 					spanfunctype = SPANDRAWFUNC_WATER;
 
 					// Only copy the part of the screen we need
-					VID_BlitLinearScreen(topleft+top, screens[1]+top,
-										 vid.width, vid.width,
-										 vid.rowbytes, vid.rowbytes);
+					VID_BlitLinearScreen((splitscreen && viewplayer == &players[secondarydisplayplayer]) ? screens[0] + (top+(vid.height>>1))*vid.width : screens[0]+((top)*vid.width), screens[1]+((top)*vid.width),
+										 vid.width, bottom-top,
+										 vid.width, vid.width);
 				}
 			}
 		}
diff --git a/src/r_things.c b/src/r_things.c
index 03cfe02ba8..6fffa4f5c4 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -979,7 +979,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol)
 		{
 			dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
 
-			R_DrawFlippedPost(column->pixels + post->data_offset, post->length, colfunc);
+	R_DrawFlippedPost(column->pixels + post->data_offset, post->length, colfunc);
 		}
 	}
 
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index fd0ebfc72b..684962a332 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -274,7 +274,7 @@ static void Impl_VideoSetupSurfaces(int width, int height)
 	}
 
 	if (texture == NULL)
-		texture = SDL_CreateTexture(renderer, sw_texture_format, SDL_TEXTUREACCESS_STREAMING, height, width);
+		texture = SDL_CreateTexture(renderer, sw_texture_format, SDL_TEXTUREACCESS_STREAMING, width, height);
 
 	// Set up SW surface
 	if (vidSurface == NULL)
@@ -285,7 +285,7 @@ static void Impl_VideoSetupSurfaces(int width, int height)
 		Uint32 amask;
 
 		SDL_PixelFormatEnumToMasks(sw_texture_format, &bpp, &rmask, &gmask, &bmask, &amask);
-		vidSurface = SDL_CreateRGBSurface(0, height, width, bpp, rmask, gmask, bmask, amask);
+		vidSurface = SDL_CreateRGBSurface(0, width, height, bpp, rmask, gmask, bmask, amask);
 	}
 }
 
@@ -294,11 +294,11 @@ static void Impl_SetupSoftwareBuffer(void)
 	// Set up game's software render buffer
 	size_t size;
 
-	vid.rowbytes = vid.height * vid.bpp;
+	vid.rowbytes = vid.width * vid.bpp;
 
 	free(vid.buffer);
 
-	size = vid.rowbytes*vid.width * NUMSCREENS;
+	size = vid.rowbytes*vid.height * NUMSCREENS;
 	vid.buffer = malloc(size);
 
 	if (vid.buffer)
@@ -312,7 +312,6 @@ static void Impl_SetupSoftwareBuffer(void)
 }
 
 static SDL_Rect src_rect = { 0, 0, 0, 0 };
-static SDL_Rect dst_rect = { 0, 0, 0, 0 };
 
 static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition)
 {
@@ -321,15 +320,8 @@ static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_b
 
 	boolean should_set_window_size = realwidth != width || realheight != height;
 
-	realwidth = width;
-	realheight = height;
-	src_rect.w = height;
-	src_rect.h = width;
-
-	dst_rect.x = (vid.width - vid.height) / 2;
-	dst_rect.y = (vid.height - vid.width) / 2;
-	dst_rect.w = vid.height;
-	dst_rect.h = vid.width;
+	src_rect.w = realwidth = width;
+	src_rect.h = realheight = height;
 
 	if (window)
 	{
@@ -1378,7 +1370,7 @@ void I_FinishUpdate(void)
 		SDL_UnlockSurface(vidSurface);
 
 		SDL_RenderClear(renderer);
-		SDL_RenderCopyEx(renderer, texture, NULL, &dst_rect, 90.0, NULL, SDL_FLIP_VERTICAL);
+		SDL_RenderCopy(renderer, texture, &src_rect, NULL);
 		SDL_RenderPresent(renderer);
 	}
 #ifdef HWRENDER
@@ -1415,13 +1407,10 @@ void I_ReadScreen(UINT8 *scr)
 {
 	if (rendermode != render_soft)
 		I_Error ("I_ReadScreen: called while in non-software mode");
-
-	UINT8 *buffer = screens[0];
-	size_t dest_rowbytes = vid.width * vid.bpp;
-
-	for (int y = 0; y < vid.height; y++)
-		for (int x = 0; x < vid.width; x++)
-			scr[(y * dest_rowbytes) + x] = buffer[(x * vid.rowbytes) + y];
+	else
+		VID_BlitLinearScreen(screens[0], scr,
+			vid.width*vid.bpp, vid.height,
+			vid.rowbytes, vid.rowbytes);
 }
 
 //
@@ -1651,12 +1640,12 @@ static void Impl_VideoSetupBuffer(void)
 	// Set up the SDL palletized buffer (copied to vidbuffer before being rendered to texture)
 	if (vid.bpp == 1)
 	{
-		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.height,vid.width,8,
+		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,8,
 			(int)vid.rowbytes,0x00000000,0x00000000,0x00000000,0x00000000); // 256 mode
 	}
 	else if (vid.bpp == 2) // Fury -- don't think this is used at all anymore
 	{
-		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.height,vid.width,15,
+		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,15,
 			(int)vid.rowbytes,0x00007C00,0x000003E0,0x0000001F,0x00000000); // 555 mode
 	}
 	if (bufSurface)
diff --git a/src/v_video.c b/src/v_video.c
index 7875fa8ef6..3e2a59a3a7 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -463,12 +463,12 @@ void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT3
 	size_t destrowbytes)
 {
 	if (srcrowbytes == destrowbytes)
-		M_Memcpy(destptr, srcptr, srcrowbytes * width);
+		M_Memcpy(destptr, srcptr, srcrowbytes * height);
 	else
 	{
-		while (width--)
+		while (height--)
 		{
-			M_Memcpy(destptr, srcptr, height);
+			M_Memcpy(destptr, srcptr, width);
 
 			destptr += destrowbytes;
 			srcptr += srcrowbytes;
@@ -669,10 +669,13 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
 	if (!desttop)
 		return;
 
+	deststop = desttop + vid.rowbytes * vid.height;
+
 	if (scrn & V_NOSCALESTART)
 	{
 		x >>= FRACBITS;
 		y >>= FRACBITS;
+		desttop += (y*vid.width) + x;
 	}
 	else
 	{
@@ -722,8 +725,8 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
 			}
 		}
 
+		desttop += (y*vid.width) + x;
 	}
-	desttop += (x*vid.height) + y;
 
 	if (pscale != FRACUNIT) // scale width properly
 	{
@@ -736,9 +739,9 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
 		pwidth = patch->width * dup;
 
 	deststart = desttop;
-	destend = desttop + pwidth*vid.height;
+	destend = desttop + pwidth;
 
-	for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop += vid.height)
+	for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop++)
 	{
 		if (scrn & V_FLIP) // offx is measured from right edge instead of left
 		{
@@ -764,16 +767,13 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
 			dest = desttop;
 			if (scrn & V_FLIP)
 				dest = deststart + (destend - desttop);
-			dest += FixedInt(FixedMul(post->topdelta<<FRACBITS,vdup));
-
-			UINT8 *col_start = screens[0] + ((x + offx)*vid.height);
-			deststop = col_start + vid.height;
+			dest += FixedInt(FixedMul(post->topdelta<<FRACBITS,vdup))*vid.width;
 
 			for (ofs = 0; dest < deststop && (size_t)(ofs>>FRACBITS) < post->length; ofs += rowfrac)
 			{
-				if (dest >= col_start) // don't draw off the top of the screen (CRASH PREVENTION)
+				if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
 					*dest = patchdrawfunc(dest, source, ofs);
-				dest++;
+				dest += vid.width;
 			}
 		}
 	}
@@ -934,12 +934,13 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 	if (!desttop)
 		return;
 
-	int stop_pos = vid.height;
+	deststop = desttop + vid.rowbytes * vid.height;
 
 	if (scrn & V_NOSCALESTART)
 	{
 		x >>= FRACBITS;
 		y >>= FRACBITS;
+		desttop += (y*vid.width) + x;
 	}
 	else
 	{
@@ -980,9 +981,9 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 					y += (vid.height - (BASEVIDHEIGHT * dup)) / 4;
 			}
 		}
-	}
 
-	desttop += (y*vid.width) + x;
+		desttop += (y*vid.width) + x;
+	}
 
 	// Auto-crop at splitscreen borders!
 	if (splitscreen && (scrn & V_PERPLAYER))
@@ -1001,7 +1002,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 			if (stplyr == &players[displayplayer]) // Player 1's screen, crop at the bottom
 			{
 				// Just put a big old stop sign halfway through the screen
-				stop_pos -= vid.height>>1;
+				deststop -= vid.rowbytes * (vid.height>>1);
 			}
 			else //if (stplyr == &players[secondarydisplayplayer]) // Player 2's screen, crop at the top
 			{
@@ -1009,13 +1010,13 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 				{
 					sy += ((vid.height>>1) - y) * rowfrac; // Start further down on the patch
 					h -= ((vid.height>>1) - y) * rowfrac; // Draw less downwards from the start
-					desttop += (vid.height>>1) - y; // Start drawing at the border
+					desttop += ((vid.height>>1) - y) * vid.width; // Start drawing at the border
 				}
 			}
 		}
 	}
 
-	for (col = sx; (col>>FRACBITS) < patch->width && (col - sx) < w; col += colfrac, ++x, desttop += vid.height)
+	for (col = sx; (col>>FRACBITS) < patch->width && (col - sx) < w; col += colfrac, ++x, desttop++)
 	{
 		if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION)
 			continue;
@@ -1032,20 +1033,17 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
 			dest = desttop;
 			if ((topdelta<<FRACBITS)-sy > 0)
 			{
-				dest += FixedInt(FixedMul((topdelta<<FRACBITS)-sy,vdup));
+				dest += FixedInt(FixedMul((topdelta<<FRACBITS)-sy,vdup))*vid.width;
 				ofs = 0;
 			}
 			else
 				ofs = sy-(topdelta<<FRACBITS);
 
-			UINT8 *col_start = screens[0] + (x*vid.height);
-			deststop = col_start + stop_pos;
-
 			for (; dest < deststop && (size_t)(ofs>>FRACBITS) < post->length && ((ofs - sy) + (topdelta<<FRACBITS)) < h; ofs += rowfrac)
 			{
-				if (dest >= col_start) // don't draw off the top of the screen (CRASH PREVENTION)
+				if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
 					*dest = patchdrawfunc(dest, source, ofs);
-				dest++;
+				dest += vid.width;
 			}
 		}
 	}
@@ -1084,8 +1082,8 @@ void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const
 		I_Error("Bad V_DrawBlock");
 #endif
 
-	dest = screens[scrn] + x*vid.height + y;
-	deststop = screens[scrn] + vid.rowbytes * vid.width;
+	dest = screens[scrn] + y*vid.width + x;
+	deststop = screens[scrn] + vid.rowbytes * vid.height;
 
 	while (height--)
 	{
@@ -1103,7 +1101,7 @@ void V_DrawBlock(INT32 x, INT32 y, INT32 scrn, INT32 width, INT32 height, const
 //
 void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 {
-	UINT8 *dest, *desttop;
+	UINT8 *dest;
 	const UINT8 *deststop;
 	UINT32 alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT);
 	UINT32 blendmode = ((c & V_BLENDMASK) >> V_BLENDSHIFT);
@@ -1271,8 +1269,8 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 	if (y + h > vid.height)
 		h = vid.height - y;
 
-	dest = desttop = screens[0] + x*vid.height + y;
-	deststop = screens[0] + vid.rowbytes * vid.width;
+	dest = screens[0] + y*vid.width + x;
+	deststop = screens[0] + vid.rowbytes * vid.height;
 
 	c &= 255;
 
@@ -1280,31 +1278,16 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 	if (alphalevel)
 	{
 		v_translevel += c<<8;
-		for (;(--h >= 0) && desttop < deststop; desttop++)
+		for (;(--h >= 0) && dest < deststop; dest += vid.width)
 		{
-			dest = desttop;
-
-			UINT8 *row_end = dest + (w * vid.height);
-			while (dest < row_end)
-			{
-				*dest = v_translevel[*dest];
-				dest += vid.height;
-			}
+			for (x = 0; x < w; x++)
+				dest[x] = v_translevel[dest[x]];
 		}
 	}
 	else
 	{
-		for (;(--h >= 0) && desttop < deststop; desttop++)
-		{
-			dest = desttop;
-
-			UINT8 *row_end = dest + (w * vid.height);
-			while (dest < row_end)
-			{
-				*dest = c;
-				dest += vid.height;
-			}
-		}
+		for (;(--h >= 0) && dest < deststop; dest += vid.width)
+			memset(dest, c, w * vid.bpp);
 	}
 }
 
@@ -1348,8 +1331,9 @@ static UINT32 V_GetHWConsBackColor(void)
 
 void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 {
-	UINT8 *dest, *desttop;
+	UINT8 *dest;
 	const UINT8 *deststop;
+	INT32 u;
 	UINT8 *fadetable;
 	UINT32 alphalevel = 0;
 	UINT8 perplayershuffle = 0;
@@ -1500,7 +1484,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 	if (y + h > vid.height)
 		h = vid.height-y;
 
-	dest = desttop = screens[0] + x*vid.height + y;
+	dest = screens[0] + y*vid.width + x;
 	deststop = screens[0] + vid.rowbytes * vid.height;
 
 	c &= 255;
@@ -1509,27 +1493,25 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 	if (alphalevel)
 	{
 		fadetable = R_GetTranslucencyTable(alphalevel) + (c*256);
-		for (;(--h >= 0) && desttop < deststop; desttop++)
+		for (;(--h >= 0) && dest < deststop; dest += vid.width)
 		{
-			dest = desttop;
-			UINT8 *row_end = dest + w*vid.height;
-			while (dest < row_end)
+			u = 0;
+			while (u < w)
 			{
-				*dest = fadetable[consolebgmap[*dest]];
-				dest += vid.height;
+				dest[u] = fadetable[consolebgmap[dest[u]]];
+				u++;
 			}
 		}
 	}
 	else
 	{
-		for (;(--h >= 0) && desttop < deststop; desttop++)
+		for (;(--h >= 0) && dest < deststop; dest += vid.width)
 		{
-			dest = desttop;
-			UINT8 *row_end = dest + w*vid.height;
-			while (dest < row_end)
+			u = 0;
+			while (u < w)
 			{
-				*dest = consolebgmap[*dest];
-				dest += vid.height;
+				dest[u] = consolebgmap[dest[u]];
+				u++;
 			}
 		}
 	}
@@ -1545,8 +1527,9 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 //
 void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, UINT8 strength)
 {
-	UINT8 *dest, *desttop;
+	UINT8 *dest;
 	const UINT8 *deststop;
+	INT32 u;
 	UINT8 *fadetable;
 	UINT8 perplayershuffle = 0;
 
@@ -1683,7 +1666,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
 	if (y + h > vid.height)
 		h = vid.height-y;
 
-	dest = desttop = screens[0] + y*vid.width + x;
+	dest = screens[0] + y*vid.width + x;
 	deststop = screens[0] + vid.rowbytes * vid.height;
 
 	c &= 255;
@@ -1691,14 +1674,13 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
 	fadetable = ((color & 0xFF00) // Color is not palette index?
 		? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade.
 		: ((UINT8 *)R_GetTranslucencyTable((9-strength)+1) + color*256)); // Else, do TRANSMAP** fade.
-	for (;(--h >= 0) && desttop < deststop; desttop++)
+	for (;(--h >= 0) && dest < deststop; dest += vid.width)
 	{
-		dest = desttop;
-		UINT8 *row_end = dest + w*vid.height;
-		while (dest < row_end)
+		u = 0;
+		while (u < w)
 		{
-			*dest = fadetable[*dest];
-			dest += vid.height;
+			dest[u] = fadetable[dest[u]];
+			u++;
 		}
 	}
 }
@@ -1711,7 +1693,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
 	INT32 u, v;
 	fixed_t dx, dy, xfrac, yfrac;
 	const UINT8 *src, *deststop;
-	UINT8 *flat, *dest, *desttop;
+	UINT8 *flat, *dest;
 	size_t lflatsize, flatshift;
 
 #ifdef HWRENDER
@@ -1727,7 +1709,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
 
 	flat = W_CacheLumpNum(flatnum, PU_CACHE);
 
-	dest = desttop = screens[0] + y*vid.dup*vid.width + x*vid.dup;
+	dest = screens[0] + y*vid.dup*vid.width + x*vid.dup;
 	deststop = screens[0] + vid.rowbytes * vid.height;
 
 	// from V_DrawScaledPatch
@@ -1750,17 +1732,15 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum)
 	dy = FixedDiv(FRACUNIT, vid.dup<<(FRACBITS-2));
 
 	yfrac = 0;
-	for (v = 0; v < h; v++, desttop++)
+	for (v = 0; v < h; v++, dest += vid.width)
 	{
 		xfrac = 0;
 		src = flat + (((yfrac>>FRACBITS) & (lflatsize - 1)) << flatshift);
-		dest = desttop;
 		for (u = 0; u < w; u++)
 		{
-			if (dest > deststop)
+			if (&dest[u] > deststop)
 				return;
-			*dest = src[(xfrac>>FRACBITS)&(lflatsize-1)];
-			dest += vid.height;
+			dest[u] = src[(xfrac>>FRACBITS)&(lflatsize-1)];
 			xfrac += dx;
 		}
 		yfrac += dy;
@@ -1806,7 +1786,7 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength)
 		: (((color & 0x0F00) == 0x0B00) ? fadecolormap + (256 * FADECOLORMAPROWS) // Do white fadecolormap fade.
 		: colormaps)) + strength*256) // Do COLORMAP fade.
 		: ((UINT8 *)R_GetTranslucencyTable((9-strength)+1) + color*256)); // Else, do TRANSMAP** fade.
-		const UINT8 *deststop = screens[0] + vid.rowbytes * vid.width;
+		const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
 		UINT8 *buf = screens[0];
 
 		// heavily simplified -- we don't need to know x or y
@@ -1819,7 +1799,7 @@ void V_DrawFadeScreen(UINT16 color, UINT8 strength)
 // Simple translucency with one color, over a set number of lines starting from the top.
 void V_DrawFadeConsBack(INT32 plines)
 {
-	UINT8 *deststop, *dest, *desttop;
+	UINT8 *deststop, *buf;
 
 #ifdef HWRENDER // not win32 only 19990829 by Kin
 	if (rendermode == render_opengl)
@@ -1832,24 +1812,15 @@ void V_DrawFadeConsBack(INT32 plines)
 
 	// heavily simplified -- we don't need to know x or y position,
 	// just the stop position
-	dest = desttop = screens[0];
-	deststop = screens[0] + min(plines, vid.height);
-	for (; desttop < deststop; desttop++)
-	{
-		dest = desttop;
-		UINT8 *row_end = dest + (vid.width * vid.height);
-		while (dest < row_end)
-		{
-			*dest = consolebgmap[*dest];
-			dest += vid.height;
-		}
-	}
+	deststop = screens[0] + vid.rowbytes * min(plines, vid.height);
+	for (buf = screens[0]; buf < deststop; ++buf)
+		*buf = consolebgmap[*buf];
 }
 
 // Very similar to F_DrawFadeConsBack, except we draw from the middle(-ish) of the screen to the bottom.
 void V_DrawPromptBack(INT32 boxheight, INT32 color)
 {
-	UINT8 *deststop, *dest, *desttop;
+	UINT8 *deststop, *buf;
 
 	if (color >= 256 && color < 512)
 	{
@@ -1903,25 +1874,13 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color)
 
 	// heavily simplified -- we don't need to know x or y position,
 	// just the start and stop positions
-	int height;
+	buf = deststop = screens[0] + vid.rowbytes * vid.height;
 	if (boxheight < 0)
-		height = -boxheight;
+		buf += vid.rowbytes * boxheight;
 	else // 4 lines of space plus gaps between and some leeway
-		height = boxheight*4 + boxheight/2*5;
-
-	dest = desttop = screens[0] + (vid.height - height);
-	deststop = screens[0] + vid.rowbytes * vid.width;
-	for (;(--height >= 0) && desttop < deststop; desttop++)
-	{
-		dest = desttop;
-
-		UINT8 *row_end = dest + (vid.width * vid.height);
-		while (dest < row_end)
-		{
-			*dest = promptbgmap[*dest];
-			dest += vid.height;
-		}
-	}
+		buf -= vid.rowbytes * ((boxheight * 4) + (boxheight/2)*5);
+	for (; buf < deststop; ++buf)
+		*buf = promptbgmap[*buf];
 }
 
 // Gets string colormap, used for 0x80 color codes
@@ -2550,7 +2509,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 	{
 		UINT8 *tmpscr = screens[4];
 		UINT8 *srcscr = screens[0];
-		INT32 y, x;
+		INT32 y;
 		// Set disStart to a range from 0 to FINEANGLE, incrementing by 128 per tic
 		angle_t disStart = (((leveltime-1)*128) + (rendertimefrac / (FRACUNIT/128))) & FINEMASK;
 		INT32 newpix;
@@ -2560,7 +2519,6 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 		for (y = yoffset; y < yoffset+height; y++)
 		{
 			sine = (FINESINE(disStart)*5)>>FRACBITS;
-			/*
 			newpix = abs(sine);
 
 			if (sine < 0)
@@ -2585,8 +2543,9 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 					newpix--;
 				}
 			}
-			*/
 
+/*
+Unoptimized version
 			for (x = 0; x < vid.width*vid.bpp; x++)
 			{
 				newpix = (x + sine);
@@ -2596,8 +2555,8 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 				else if (newpix >= vid.width)
 					newpix = vid.width-1;
 
-				tmpscr[y + x*vid.height] = srcscr[y+newpix*vid.height]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
-			}
+				tmpscr[y*vid.width + x] = srcscr[y*vid.width+newpix]; // *(transme + (srcscr[y*vid.width+x]<<8) + srcscr[y*vid.width+newpix]);
+			}*/
 			disStart += 22;//the offset into the displacement map, increment each game loop
 			disStart &= FINEMASK; //clip it to FINEMASK
 		}
@@ -2618,8 +2577,8 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 		{
 			for (x = 0; x < vid.width; x++)
 			{
-				tmpscr[y + x*vid.height]
-					=     colormaps[*(transme     + (srcscr   [y+x*vid.height] <<8) + (tmpscr[y+x*vid.height]))];
+				tmpscr[y*vid.width + x]
+					=     colormaps[*(transme     + (srcscr   [y*vid.width+x ] <<8) + (tmpscr[y*vid.width+x]))];
 			}
 		}
 		VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
@@ -2629,11 +2588,10 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 	{
 		UINT8 *tmpscr = screens[4];
 		UINT8 *srcscr = screens[0];
-		INT32 y, y2, x;
+		INT32 y, y2;
 
 		for (y = yoffset, y2 = yoffset+height - 1; y < yoffset+height; y++, y2--)
-			for (x = 0; x < vid.width; x++)
-				tmpscr[y2+x*vid.height] = srcscr[y+x*vid.height];
+			M_Memcpy(&tmpscr[y2*vid.width], &srcscr[y*vid.width], vid.width);
 
 		VID_BlitLinearScreen(tmpscr+vid.width*vid.bpp*yoffset, screens[0]+vid.width*vid.bpp*yoffset,
 				vid.width*vid.bpp, height, vid.width*vid.bpp, vid.width);
@@ -2642,12 +2600,16 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 	{
 		UINT8 *tmpscr = screens[4];
 		UINT8 *srcscr = screens[0];
-		INT32 y, x;
+		INT32 y;
 
 		// Make sure table is built
 		if (heatshifter == NULL || lastheight != height)
 		{
-			heatshifter = Z_Realloc(heatshifter, height * sizeof(boolean), PU_STATIC, NULL);
+			if (heatshifter)
+				Z_Free(heatshifter);
+
+			heatshifter = Z_Calloc(height * sizeof(boolean), PU_STATIC, NULL);
+
 			for (y = 0; y < height; y++)
 			{
 				if (M_RandomChance(FRACUNIT/8)) // 12.5%
@@ -2663,12 +2625,11 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 			if (heatshifter[heatindex[view]++])
 			{
 				// Shift this row of pixels to the right by 2
-				tmpscr[y] = srcscr[y];
-				for (x = vid.dup; x < vid.width; x++)
-					tmpscr[y+x*vid.height] = srcscr[y+(x-vid.dup)*vid.height];
+				tmpscr[y*vid.width] = srcscr[y*vid.width];
+				M_Memcpy(&tmpscr[y*vid.width+vid.dup], &srcscr[y*vid.width], vid.width-vid.dup);
 			}
-			else for (x = 0; x < vid.width; x++)
-				tmpscr[y+x*vid.height] = srcscr[y+x*vid.height];
+			else
+				M_Memcpy(&tmpscr[y*vid.width], &srcscr[y*vid.width], vid.width);
 
 			heatindex[view] %= height;
 		}
@@ -2738,7 +2699,7 @@ void V_Init(void)
 {
 	INT32 i;
 	UINT8 *base = vid.buffer;
-	const INT32 screensize = vid.rowbytes * vid.width;
+	const INT32 screensize = vid.rowbytes * vid.height;
 
 	LoadMapPalette();
 
diff --git a/src/y_inter.c b/src/y_inter.c
index f6eb93fc51..d7e644567e 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -325,7 +325,7 @@ void Y_ConsiderScreenBuffer(void)
 	y_buffer->source_bpp = vid.bpp;
 	y_buffer->source_rowbytes = vid.rowbytes;
 	y_buffer->source_picture = ZZ_Alloc(y_buffer->source_width*vid.bpp * y_buffer->source_height);
-	VID_BlitLinearScreen(screens[1], y_buffer->source_picture, vid.width*vid.bpp, vid.height, vid.rowbytes, vid.rowbytes);
+	VID_BlitLinearScreen(screens[1], y_buffer->source_picture, vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
 
 	// Make the rescaled screen buffer
 	Y_RescaleScreenBuffer();
@@ -364,9 +364,9 @@ static void Y_RescaleScreenBuffer(void)
 	rowfrac = FixedDiv(FRACUNIT, yscalefac);
 	colfrac = FixedDiv(FRACUNIT, scalefac);
 
-	for (sx = 0, dx = 0; sx < (y_buffer->source_width << FRACBITS) && dx < y_buffer->target_width; sx += colfrac, dx += y_buffer->target_bpp)
-		for (sy = 0, dy = 0; sy < (y_buffer->source_height << FRACBITS) && dy < y_buffer->target_height; sy += rowfrac, dy++)
-			dest[(dx * y_buffer->target_rowbytes) + dy] = y_buffer->source_picture[((sx>>FRACBITS) * y_buffer->source_height) + (sy>>FRACBITS)];
+	for (sy = 0, dy = 0; sy < (y_buffer->source_height << FRACBITS) && dy < y_buffer->target_height; sy += rowfrac, dy++)
+		for (sx = 0, dx = 0; sx < (y_buffer->source_width << FRACBITS) && dx < y_buffer->target_width; sx += colfrac, dx += y_buffer->target_bpp)
+			dest[(dy * y_buffer->target_rowbytes) + dx] = y_buffer->source_picture[((sy>>FRACBITS) * y_buffer->source_width) + (sx>>FRACBITS)];
 }
 
 //
@@ -412,7 +412,7 @@ void Y_IntermissionDrawer(void)
 		{
 			// no y_buffer
 			if (y_buffer == NULL)
-				VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.rowbytes, vid.rowbytes);
+				VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
 			else
 			{
 				// Maybe the resolution changed?
@@ -420,7 +420,7 @@ void Y_IntermissionDrawer(void)
 					Y_RescaleScreenBuffer();
 
 				// Blit the already-scaled screen buffer to the current screen
-				VID_BlitLinearScreen(y_buffer->target_picture, screens[0], vid.width*vid.bpp, vid.height, vid.rowbytes, vid.rowbytes);
+				VID_BlitLinearScreen(y_buffer->target_picture, screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
 			}
 		}
 #ifdef HWRENDER
-- 
GitLab


From 5034a8f2811f30a154e0f747814a121e804d4bcc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Sat, 29 Mar 2025 21:49:02 +0100
Subject: [PATCH 04/14] Let hardware handle resolutions

---
 src/dedicated/i_video.c |   5 +
 src/screen.c            |  15 +-
 src/sdl/i_video.c       | 310 +++++++++++++---------------------------
 src/sdl/ogl_sdl.c       |   2 +-
 4 files changed, 109 insertions(+), 223 deletions(-)

diff --git a/src/dedicated/i_video.c b/src/dedicated/i_video.c
index 72fe0cdd50..86d241dc0e 100644
--- a/src/dedicated/i_video.c
+++ b/src/dedicated/i_video.c
@@ -62,3 +62,8 @@ boolean VID_IsMaximized(void)
 	return false;
 }
 void VID_RestoreWindow(void){}
+
+boolean SCR_IsValidResolution(INT32 width, INT32 height)
+{
+	return false;
+}
diff --git a/src/screen.c b/src/screen.c
index fff97dca7e..085e2ab0d1 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -267,15 +267,6 @@ void SCR_Recalc(void)
 #endif
 }
 
-boolean SCR_IsValidResolution(INT32 width, INT32 height)
-{
-	if (width < BASEVIDWIDTH || width > MAXVIDWIDTH)
-		return false;
-	if (height < BASEVIDHEIGHT || height > MAXVIDHEIGHT)
-		return false;
-	return true;
-}
-
 static boolean SCR_SetSize(INT32 width, INT32 height)
 {
 	if (SCR_IsValidResolution(width, height))
@@ -362,9 +353,9 @@ void SCR_CheckDefaultMode(void)
 
 		if (!SCR_IsValidResolution(width, height))
 		{
-			CONS_Alert(CONS_WARNING, "Invalid resolution given, defaulting to base resolution\n");
-			width = BASEVIDWIDTH;
-			height = BASEVIDHEIGHT;
+			CONS_Alert(CONS_WARNING, "Invalid resolution given, defaulting to a safe resolution\n");
+			width = 800;
+			height = 600;
 		}
 
 		SCR_ChangeResolution(width, height);
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index d745eec8d3..1ec302b694 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -70,6 +70,7 @@
 #include "../st_stuff.h"
 #include "../hu_stuff.h"
 #include "../g_game.h"
+#include "../z_zone.h"
 #include "../i_video.h"
 #include "../console.h"
 #include "../command.h"
@@ -115,21 +116,14 @@ static SDL_bool disable_mouse = SDL_FALSE;
 static      INT32        mousemovex = 0, mousemovey = 0;
 
 // SDL vars
-static      SDL_Surface *vidSurface = NULL;
-static      SDL_Surface *bufSurface = NULL;
-static      SDL_Color    localPalette[256];
+static      UINT32       softPalette[256];
 static       SDL_bool    mousegrabok = SDL_TRUE;
 static       SDL_bool    wrapmouseok = SDL_FALSE;
 #define HalfWarpMouse(x,y) if (wrapmouseok) SDL_WarpMouseInWindow(window, (Uint16)(x/2),(Uint16)(y/2))
-static       SDL_bool    usesdl2soft = SDL_FALSE;
 static       SDL_bool    borderlesswindow = SDL_FALSE;
 
-Uint16      realwidth = BASEVIDWIDTH;
-Uint16      realheight = BASEVIDHEIGHT;
-
 SDL_Window   *window;
 SDL_Renderer *renderer;
-static SDL_Texture  *texture;
 static SDL_bool      havefocus = SDL_TRUE;
 
 static UINT32 refresh_rate;
@@ -138,9 +132,6 @@ static boolean video_init = false;
 
 static SDL_bool Impl_CreateWindow(SDL_bool fullscreen);
 
-static void Impl_VideoSetupSurfaces(int width, int height);
-static void Impl_VideoSetupBuffer(void);
-
 static void Impl_SetupSoftwareBuffer(void);
 
 static void Impl_InitOpenGL(void);
@@ -167,32 +158,8 @@ static SDL_bool Impl_RenderContextCreate(void)
 {
 	if (rendermode != render_opengl)
 	{
-		int flags = 0; // Use this to set SDL_RENDERER_* flags now
-
-		if (usesdl2soft)
-			flags |= SDL_RENDERER_SOFTWARE;
-		else if (cv_vidwait.value)
-		{
-#if SDL_VERSION_ATLEAST(2, 0, 18)
-			// If SDL is new enough, we can turn off vsync later.
-			flags |= SDL_RENDERER_PRESENTVSYNC;
-#else
-			// However, if it isn't, we should just silently turn vid_wait off
-			// This is because the renderer will be created before the config
-			// is read and vid_wait is set from the user's preferences, and thus
-			// vid_wait will have no effect.
-			CV_StealthSetValue(&cv_vidwait, 0);
-#endif
-		}
-
-		if (!renderer)
-			renderer = SDL_CreateRenderer(window, -1, flags);
-
-		if (renderer == NULL)
-		{
-			VIDEO_INIT_ERROR("Couldn't create rendering context: %s");
-			return SDL_FALSE;
-		}
+		// we do rasterization ourselves, so nothing to do
+		return SDL_TRUE;
 	}
 
 #ifdef HWRENDER
@@ -216,79 +183,23 @@ static SDL_bool Impl_RenderContextCreate(void)
 
 static SDL_bool Impl_RenderContextReset(void)
 {
-	if (renderer)
-	{
-		SDL_DestroyRenderer(renderer);
-		texture = NULL; // Destroying a renderer also destroys all of its textures
-	}
-	renderer = NULL;
-
 	if (Impl_RenderContextCreate() == SDL_FALSE)
 		return SDL_FALSE;
 
-	if (vidSurface != NULL)
-	{
-		SDL_FreeSurface(vidSurface);
-		vidSurface = NULL;
-	}
-
-	if (bufSurface != NULL)
-	{
-		SDL_FreeSurface(bufSurface);
-		bufSurface = NULL;
-	}
-
 #ifdef HWRENDER
 	if (rendermode == render_opengl)
 	{
 		SDL_GL_MakeCurrent(window, sdlglcontext);
 		SDL_GL_SetSwapInterval(cv_vidwait.value ? 1 : 0);
 
-		OglSdlSurface(realwidth, realheight);
+		OglSdlSurface(vid.width, vid.height);
 		HWR_Startup();
 	}
-	else
 #endif
-	{
-		SDL_RenderClear(renderer);
-		SDL_RenderSetLogicalSize(renderer, realwidth, realheight);
-		Impl_VideoSetupSurfaces(realwidth, realheight);
-	}
 
 	return SDL_TRUE;
 }
 
-static void Impl_VideoSetupSurfaces(int width, int height)
-{
-	int bpp = 16;
-	int sw_texture_format = SDL_PIXELFORMAT_ABGR8888;
-
-	if (!usesdl2soft)
-	{
-		sw_texture_format = SDL_PIXELFORMAT_RGB565;
-	}
-	else
-	{
-		bpp = 32;
-		sw_texture_format = SDL_PIXELFORMAT_RGBA8888;
-	}
-
-	if (texture == NULL)
-		texture = SDL_CreateTexture(renderer, sw_texture_format, SDL_TEXTUREACCESS_STREAMING, width, height);
-
-	// Set up SW surface
-	if (vidSurface == NULL)
-	{
-		Uint32 rmask;
-		Uint32 gmask;
-		Uint32 bmask;
-		Uint32 amask;
-
-		SDL_PixelFormatEnumToMasks(sw_texture_format, &bpp, &rmask, &gmask, &bmask, &amask);
-		vidSurface = SDL_CreateRGBSurface(0, width, height, bpp, rmask, gmask, bmask, amask);
-	}
-}
-
 static void Impl_SetupSoftwareBuffer(void)
 {
 	// Set up game's software render buffer
@@ -311,33 +222,67 @@ static void Impl_SetupSoftwareBuffer(void)
 		I_Error("%s", M_GetText("Not enough memory for video buffer\n"));
 }
 
-static SDL_Rect src_rect = { 0, 0, 0, 0 };
-
-static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition)
+static SDL_DisplayMode *Impl_ListAvailableResolutions(INT32 *count)
 {
-	static SDL_bool wasfullscreen = SDL_FALSE;
-	int fullscreen_type = SDL_WINDOW_FULLSCREEN_DESKTOP;
+	static SDL_DisplayMode *modes;
+	static INT32 nummodes;
+	INT32 i;
+	if (modes != NULL)
+	{
+		*count = nummodes;
+		return modes;
+	}
 
-	boolean should_set_window_size = realwidth != width || realheight != height;
+	// TODO: add support for multiple monitors
+	nummodes = SDL_GetNumDisplayModes(0);
+	modes = Z_Malloc(sizeof(SDL_DisplayMode) * nummodes, PU_STATIC, NULL);
+	CONS_Printf("Available resolutions:\n");
+	for (i = 0; i < nummodes; i++)
+	{
+		SDL_GetDisplayMode(0, i, &modes[i]);
+		CONS_Printf(" * %dx%d@%d\n", modes[i].w, modes[i].h, modes[i].refresh_rate);
+	}
 
-	src_rect.w = realwidth = width;
-	src_rect.h = realheight = height;
+	*count = nummodes;
+	return modes;
+}
+
+static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition)
+{
+	int fullscreen_type = SDL_WINDOW_FULLSCREEN;
 
 	if (window)
 	{
 		if (fullscreen)
 		{
-			wasfullscreen = SDL_TRUE;
+			SDL_DisplayMode *modes;
+			INT32 nummodes, i;
+
+			// go into window mode temporarily so we can be sure it actually applied the resolution
+			SDL_SetWindowFullscreen(window, 0);
+
+			modes = Impl_ListAvailableResolutions(&nummodes);
+			for (i = 0; i < nummodes; i++)
+			{
+				if (modes[i].w == width && modes[i].h == height)
+				{
+					if (SDL_SetWindowDisplayMode(window, &modes[i]))
+					{
+						CONS_Printf("Couldn't change resolution to %dx%d: %s\n", width, height, SDL_GetError());
+						return SDL_FALSE;
+					}
+					break;
+				}
+			}
+
 			SDL_SetWindowFullscreen(window, fullscreen_type);
+
+			if (i == nummodes)
+				return SDL_FALSE; // resolution is not supported
 		}
 		else // windowed mode
 		{
-			if (wasfullscreen)
-			{
-				wasfullscreen = SDL_FALSE;
-				SDL_SetWindowFullscreen(window, 0);
-			}
-
+			SDL_SetWindowFullscreen(window, 0);
 			SDL_SetWindowSize(window, width, height);
 
 			if (reposition)
@@ -355,9 +300,7 @@ static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_b
 		if (Impl_CreateWindow(fullscreen) == SDL_FALSE)
 			return SDL_FALSE;
 
-		wasfullscreen = fullscreen;
-		if (should_set_window_size)
-			SDL_SetWindowSize(window, width, height);
+		SDL_SetWindowSize(window, width, height);
 		if (fullscreen)
 			SDL_SetWindowFullscreen(window, fullscreen_type);
 
@@ -609,36 +552,6 @@ static void VID_Command_NumModes_f (void)
 	CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), MAXWINMODES);
 }
 
-// SDL2 doesn't have SDL_GetVideoSurface or a lot of the SDL_Surface flags that SDL 1.2 had
-static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText)
-{
-	INT32 vfBPP;
-
-	if (!infoSurface)
-		return;
-
-	if (!SurfaceText)
-		SurfaceText = M_GetText("Unknown Surface");
-
-	vfBPP = infoSurface->format?infoSurface->format->BitsPerPixel:0;
-
-	CONS_Printf("\x82" "%s\n", SurfaceText);
-	CONS_Printf(M_GetText(" %ix%i at %i bit color\n"), infoSurface->w, infoSurface->h, vfBPP);
-
-	if (infoSurface->flags&SDL_PREALLOC)
-		CONS_Printf("%s", M_GetText(" Uses preallocated memory\n"));
-	else
-		CONS_Printf("%s", M_GetText(" Stored in system memory\n"));
-	if (infoSurface->flags&SDL_RLEACCEL)
-		CONS_Printf("%s", M_GetText(" Colorkey RLE acceleration blit\n"));
-}
-
-static void VID_Command_Info_f (void)
-{
-	SurfaceInfo(bufSurface, M_GetText("Current Engine Mode"));
-	SurfaceInfo(vidSurface, M_GetText("Current Video Mode"));
-}
-
 static void VID_Command_ModeList_f(void)
 {
 	for (INT32 i = 0; i < MAXWINMODES; i++)
@@ -667,6 +580,27 @@ static void VID_Command_Mode_f (void)
 	}
 }
 
+boolean SCR_IsValidResolution(INT32 width, INT32 height)
+{
+	if (width < BASEVIDWIDTH || width > MAXVIDWIDTH)
+		return false;
+	if (height < BASEVIDHEIGHT || height > MAXVIDHEIGHT)
+		return false;
+
+	if (USE_FULLSCREEN)
+	{
+		INT32 nummodes, i;
+		SDL_DisplayMode *modes = Impl_ListAvailableResolutions(&nummodes);
+		for (i = 0; i < nummodes; i++)
+		{
+			if (modes[i].w == width && modes[i].h == height)
+				return true;
+		}
+		return false;
+	}
+	return true;
+}
+
 static void VID_Command_Width_f (void)
 {
 	if (COM_Argc() != 2)
@@ -745,9 +679,9 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
 			mousefocus = SDL_FALSE;
 			break;
 		case SDL_WINDOWEVENT_SIZE_CHANGED:
-			if ((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0)
+			if ((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) == 0)
 			{
-				if (realwidth != evt.data1 || realheight != evt.data2)
+				if (vid.width != evt.data1 || vid.height != evt.data2)
 					SCR_SetSizeNoRestore(evt.data1, evt.data2);
 				SCR_SetDefaultMode(evt.data1, evt.data2);
 			}
@@ -845,7 +779,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
 
 		// If the event is from warping the pointer to middle
 		// of the screen then ignore it.
-		if ((evt.x == realwidth/2) && (evt.y == realheight/2))
+		if ((evt.x == vid.width/2) && (evt.y == vid.height/2))
 		{
 			firstmove = false;
 			return;
@@ -1265,8 +1199,8 @@ void I_GetEvent(void)
 		//SDL_memset(&event, 0, sizeof(event_t));
 		event.type = ev_mouse;
 		event.key = 0;
-		event.x = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth));
-		event.y = (INT32)lround(mousemovey * ((float)wheight / (float)realheight));
+		event.x = (INT32)lround(mousemovex * ((float)wwidth / (float)vid.width));
+		event.y = (INT32)lround(mousemovey * ((float)wheight / (float)vid.height));
 		D_PostEvent(&event);
 	}
 
@@ -1284,7 +1218,7 @@ void I_StartupMouse(void)
 
 	if (!firsttimeonmouse)
 	{
-		HalfWarpMouse(realwidth, realheight); // warp to center
+		HalfWarpMouse(vid.width, vid.height); // warp to center
 	}
 	else
 		firsttimeonmouse = SDL_FALSE;
@@ -1360,18 +1294,16 @@ void I_FinishUpdate(void)
 
 	if (rendermode == render_soft && screens[0])
 	{
-		if (!bufSurface) // Double-check
-			Impl_VideoSetupBuffer();
-
-		SDL_BlitSurface(bufSurface, &src_rect, vidSurface, &src_rect);
-		// Fury -- there's no way around UpdateTexture, the GL backend uses it anyway
-		SDL_LockSurface(vidSurface);
-		SDL_UpdateTexture(texture, &src_rect, vidSurface->pixels, vidSurface->pitch);
-		SDL_UnlockSurface(vidSurface);
-
-		SDL_RenderClear(renderer);
-		SDL_RenderCopy(renderer, texture, &src_rect, NULL);
-		SDL_RenderPresent(renderer);
+		SDL_Surface *surface = SDL_GetWindowSurface(window);
+		SDL_LockSurface(surface);
+		UINT32 *restrict pixels = surface->pixels;
+		INT32 size = surface->w * surface->h;
+		const UINT8 *restrict source = screens[0];
+		INT32 i;
+		for (i = 0; i < size; i++)
+			*pixels++ = softPalette[*source++];
+		SDL_UnlockSurface(surface);
+		SDL_UpdateWindowSurface(window);
 	}
 #ifdef HWRENDER
 	else if (rendermode == render_opengl)
@@ -1419,15 +1351,15 @@ void I_ReadScreen(UINT8 *scr)
 void I_SetPalette(RGBA_t *palette)
 {
 	size_t i;
+	SDL_Surface *surface = SDL_GetWindowSurface(window);
 	for (i=0; i<256; i++)
 	{
-		localPalette[i].r = palette[i].s.red;
-		localPalette[i].g = palette[i].s.green;
-		localPalette[i].b = palette[i].s.blue;
+		UINT32 color = palette[i].s.red << surface->format->Rshift;
+		color |= palette[i].s.green << surface->format->Gshift;
+		color |= palette[i].s.blue << surface->format->Bshift;
+		color |= surface->format->Amask;
+		softPalette[i] = color;
 	}
-	//if (vidSurface) SDL_SetPaletteColors(vidSurface->format->palette, localPalette, 0, 256);
-	// Fury -- SDL2 vidSurface is a 32-bit surface buffer copied to the texture. It's not palletized, like bufSurface.
-	if (bufSurface) SDL_SetPaletteColors(bufSurface->format->palette, localPalette, 0, 256);
 }
 
 void VID_CheckGLLoaded(rendermode_t oldrender)
@@ -1591,7 +1523,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 		return SDL_TRUE;
 
 	if (fullscreen)
-		flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+		flags |= SDL_WINDOW_FULLSCREEN;
 
 	if (borderlesswindow)
 		flags |= SDL_WINDOW_BORDERLESS;
@@ -1606,7 +1538,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 #endif
 
 	// Create a window
-	window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, realwidth, realheight, flags);
+	window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, vid.width, vid.height, flags);
 	if (window == NULL)
 	{
 		VIDEO_INIT_ERROR("Couldn't create window: %s");
@@ -1630,34 +1562,6 @@ static void Impl_SetWindowIcon(void)
 }
 #endif
 
-static void Impl_VideoSetupBuffer(void)
-{
-	if (bufSurface != NULL)
-	{
-		SDL_FreeSurface(bufSurface);
-		bufSurface = NULL;
-	}
-	// Set up the SDL palletized buffer (copied to vidbuffer before being rendered to texture)
-	if (vid.bpp == 1)
-	{
-		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,8,
-			(int)vid.rowbytes,0x00000000,0x00000000,0x00000000,0x00000000); // 256 mode
-	}
-	else if (vid.bpp == 2) // Fury -- don't think this is used at all anymore
-	{
-		bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,15,
-			(int)vid.rowbytes,0x00007C00,0x000003E0,0x0000001F,0x00000000); // 555 mode
-	}
-	if (bufSurface)
-	{
-		SDL_SetPaletteColors(bufSurface->format->palette, localPalette, 0, 256);
-	}
-	else
-	{
-		I_Error("%s", M_GetText("No system memory for SDL buffer surface\n"));
-	}
-}
-
 static void Impl_InitVideoSubSystem(void)
 {
 	if (video_init)
@@ -1683,7 +1587,6 @@ void I_StartupGraphics(void)
 		return;
 
 	COM_AddCommand ("vid_nummodes", NULL, VID_Command_NumModes_f, COM_LUA);
-	COM_AddCommand ("vid_info", NULL, VID_Command_Info_f, COM_LUA);
 	COM_AddCommand ("vid_modelist", NULL, VID_Command_ModeList_f, COM_LUA);
 	COM_AddCommand ("vid_mode", NULL, VID_Command_Mode_f, 0);
 	COM_AddCommand ("vid_width", NULL, VID_Command_Width_f, 0);
@@ -1754,7 +1657,6 @@ void I_StartupGraphics(void)
 	if (chosenrendermode != render_none)
 		rendermode = chosenrendermode;
 
-	usesdl2soft = M_CheckParm("-softblit");
 	borderlesswindow = M_CheckParm("-borderless");
 
 #ifdef HWRENDER
@@ -1783,7 +1685,6 @@ void I_StartupGraphics(void)
 	if (M_CheckParm("-nomousegrab"))
 		mousegrabok = SDL_FALSE;
 
-	VID_Command_Info_f();
 	SDLdoUngrabMouse();
 
 	SDL_RaiseWindow(window);
@@ -1863,17 +1764,6 @@ void I_ShutdownGraphics(void)
 	icoSurface = NULL;
 #endif
 
-	if (rendermode == render_soft)
-	{
-		if (vidSurface)
-			SDL_FreeSurface(vidSurface);
-		vidSurface = NULL;
-
-		if (bufSurface)
-			SDL_FreeSurface(bufSurface);
-		bufSurface = NULL;
-	}
-
 	free(vid.buffer);
 	vid.buffer = NULL;
 
diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c
index c78b43ec40..ea02279958 100644
--- a/src/sdl/ogl_sdl.c
+++ b/src/sdl/ogl_sdl.c
@@ -189,7 +189,7 @@ void OglSdlFinishUpdate(boolean waitvbl)
 	HWR_DrawScreenFinalTexture(sdlw, sdlh);
 	SDL_GL_SwapWindow(window);
 
-	GClipRect(0, 0, realwidth, realheight, NZCLIP_PLANE);
+	GClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE);
 
 	// Sryder:	We need to draw the final screen texture again into the other buffer in the original position so that
 	//			effects that want to take the old screen can do so after this
-- 
GitLab


From b9ac5b21861a6d8dbfddaec900941767b8aa6d9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Sun, 30 Mar 2025 00:40:26 +0100
Subject: [PATCH 05/14] Fix segfault when drawing vissprites on screen edges

---
 src/r_things.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/r_things.c b/src/r_things.c
index 7c096519fd..6b1c531ae2 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1234,7 +1234,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
 #endif
 
 		// Non-paper drawing loop
-		for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
+		for (dc_x = vis->x1; dc_x <= vis->x2 && (frac>>FRACBITS) < patch->width; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
 		{
 			column = &patch->columns[frac>>FRACBITS];
 			localcolfunc (column, lengthcol);
-- 
GitLab


From 830cfff1a4d937a5cef34fb12df333a4dc606c89 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Sun, 30 Mar 2025 11:57:51 +0200
Subject: [PATCH 06/14] Fix compiler warnings on dedicated builds

---
 src/dedicated/i_video.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/dedicated/i_video.c b/src/dedicated/i_video.c
index 86d241dc0e..fb8c06f879 100644
--- a/src/dedicated/i_video.c
+++ b/src/dedicated/i_video.c
@@ -1,6 +1,7 @@
 #include "../doomdef.h"
 #include "../command.h"
 #include "../i_video.h"
+#include "../screen.h"
 
 rendermode_t rendermode = render_none;
 rendermode_t chosenrendermode = render_none;
@@ -65,5 +66,7 @@ void VID_RestoreWindow(void){}
 
 boolean SCR_IsValidResolution(INT32 width, INT32 height)
 {
+	(void)width;
+	(void)height;
 	return false;
 }
-- 
GitLab


From 74c1f9bea1772a2c5a09497135dfa94d2a639ac3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Sun, 30 Mar 2025 13:12:13 +0200
Subject: [PATCH 07/14] Fix instability when switching renderers

---
 src/f_finale.c    |  9 ++++---
 src/sdl/i_video.c | 61 ++++++++++++++++++++++++++++-------------------
 src/z_zone.c      |  4 ++--
 3 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/src/f_finale.c b/src/f_finale.c
index 31c68be736..c4973a1ae6 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -2638,10 +2638,13 @@ static void F_FigureActiveTtScale(void)
 			break;
 	}
 
-	for (; newttscale <= 6; newttscale++)
+	if (newttscale < 1)
 	{
-		if (ttavailable[newttscale-1])
-			break;
+		for (newttscale++; newttscale <= 6; newttscale++)
+		{
+			if (ttavailable[newttscale-1])
+				break;
+		}
 	}
 
 	activettscale = (newttscale >= 1 && newttscale <= 6) ? newttscale : 0;
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 1ec302b694..e71426be10 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -255,30 +255,10 @@ static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_b
 	{
 		if (fullscreen)
 		{
-			SDL_DisplayMode *modes;
-			INT32 nummodes, i;
-
-			// go into window mode temporarily so we can be sure it actually applied the resolution
-			SDL_SetWindowFullscreen(window, 0);
-
-			modes = Impl_ListAvailableResolutions(&nummodes);
-			for (i = 0; i < nummodes; i++)
-			{
-				if (modes[i].w == width && modes[i].h == height)
-				{
-					if (SDL_SetWindowDisplayMode(window, &modes[i]))
-					{
-						CONS_Printf("Couldn't change resolution to %dx%d: %s\n", width, height, SDL_GetError());
-						return SDL_FALSE;
-					}
-					break;
-				}
-			}
-
-			SDL_SetWindowFullscreen(window, fullscreen_type);
-
-			if (i == nummodes)
-				return SDL_FALSE; // resolution is not supported
+			SDL_DestroyWindow(window);
+			window = NULL;
+			// create a new window to fix resolution quirks
+			return SDLSetMode(width, height, fullscreen, reposition);
 		}
 		else // windowed mode
 		{
@@ -302,7 +282,40 @@ static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_b
 
 		SDL_SetWindowSize(window, width, height);
 		if (fullscreen)
+		{
+			SDL_DisplayMode *modes;
+			INT32 nummodes, i;
+
+			modes = Impl_ListAvailableResolutions(&nummodes);
+			for (i = 0; i < nummodes; i++)
+			{
+				if (modes[i].w == width && modes[i].h == height)
+				{
+					if (SDL_SetWindowDisplayMode(window, &modes[i]))
+					{
+						CONS_Alert(CONS_WARNING, "Couldn't change resolution to %dx%d: %s\n", width, height, SDL_GetError());
+						continue;
+					}
+					break;
+				}
+			}
+
+			if (i == nummodes)
+			{
+				// resolution is not supported, so default to native
+				CONS_Alert(CONS_WARNING, "Resolution %dx%d is not supported, defaulting to native\n", width, height);
+				SDL_DisplayMode resolution;
+
+				if (SDL_GetCurrentDisplayMode(i, &resolution) == 0)
+				{
+					vid.width = width = (INT32)(resolution.w);
+					vid.height = height = (INT32)(resolution.h);
+					SDL_SetWindowDisplayMode(window, &resolution);
+				}
+			}
+
 			SDL_SetWindowFullscreen(window, fullscreen_type);
+		}
 
 		Impl_SetDefaultWindowSizes();
 	}
diff --git a/src/z_zone.c b/src/z_zone.c
index dabd68dfa4..0c0fde6376 100644
--- a/src/z_zone.c
+++ b/src/z_zone.c
@@ -54,8 +54,8 @@ static boolean Z_calloc = false;
 #endif
 
 #if !defined(ASAN_POISON_MEMORY_REGION)
-#    define ASAN_POISON_MEMORY_REGION(a, b) do {} while(0)
-#    define ASAN_UNPOISON_MEMORY_REGION(a, b) do {} while(0)
+#    define ASAN_POISON_MEMORY_REGION(a, b)
+#    define ASAN_UNPOISON_MEMORY_REGION(a, b)
 #endif
 
 #define ZONEID 0xa441d13d
-- 
GitLab


From 881eefb173a584d1ec20a04deee925434f46a4f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Sun, 30 Mar 2025 13:30:34 +0200
Subject: [PATCH 08/14] Fix compiler warnings

---
 src/z_zone.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/z_zone.c b/src/z_zone.c
index 0c0fde6376..0a84efe963 100644
--- a/src/z_zone.c
+++ b/src/z_zone.c
@@ -54,8 +54,8 @@ static boolean Z_calloc = false;
 #endif
 
 #if !defined(ASAN_POISON_MEMORY_REGION)
-#    define ASAN_POISON_MEMORY_REGION(a, b)
-#    define ASAN_UNPOISON_MEMORY_REGION(a, b)
+#    define ASAN_POISON_MEMORY_REGION(a, b) {}
+#    define ASAN_UNPOISON_MEMORY_REGION(a, b) {}
 #endif
 
 #define ZONEID 0xa441d13d
-- 
GitLab


From c06de2f973578b18bdcbf899a25f7d1ba12a25cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Sun, 30 Mar 2025 13:42:58 +0200
Subject: [PATCH 09/14] Only list supported resolutions in the settings

---
 src/dedicated/i_video.c |  6 ++++++
 src/i_video.h           | 10 ++++++++++
 src/m_menu.c            |  8 +++++---
 src/sdl/i_video.c       | 19 ++++++++++++++++++-
 4 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/src/dedicated/i_video.c b/src/dedicated/i_video.c
index fb8c06f879..850eef60e9 100644
--- a/src/dedicated/i_video.c
+++ b/src/dedicated/i_video.c
@@ -58,6 +58,12 @@ void VID_SetSize(INT32 width, INT32 height)
 	(void)height;
 }
 
+resolution_t *VID_GetSupportedResolutions(INT32 *count)
+{
+	*count = 0;
+	return NULL;
+}
+
 boolean VID_IsMaximized(void)
 {
 	return false;
diff --git a/src/i_video.h b/src/i_video.h
index 0cbdd8447a..fb171abe60 100644
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -32,6 +32,12 @@ typedef enum
 	render_none = 3  // for dedicated server
 } rendermode_t;
 
+typedef struct
+{
+	UINT32 width;
+	UINT32 height;
+} resolution_t;
+
 /**	\brief current render mode
 */
 extern rendermode_t rendermode;
@@ -85,6 +91,10 @@ void VID_RestoreWindow(void);
 */
 boolean VID_GetNativeResolution(INT32 *width, INT32 *height);
 
+/**	\brief List resolutions that the current display supports
+*/
+resolution_t *VID_GetSupportedResolutions(INT32 *count);
+
 /**	\brief can video system do fullscreen
 */
 extern boolean allow_fullscreen;
diff --git a/src/m_menu.c b/src/m_menu.c
index cd23ef77bd..4a608b3c80 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -13811,18 +13811,20 @@ static modedesc_t modedescs[MAXMODEDESCS];
 static void M_VideoModeMenu(INT32 choice)
 {
 	(void)choice;
+	INT32 count;
+	resolution_t *res = VID_GetSupportedResolutions(&count);
 
 	memset(modedescs, 0, sizeof(modedescs));
 
 	vidm_nummodes = 0;
 	vidm_selected = -1;
 
-	for (INT32 i = 0; i < MAXWINMODES && vidm_nummodes < MAXMODEDESCS; i++)
+	for (INT32 i = 0; i < count; i++)
 	{
 		modedesc_t *desc = &modedescs[vidm_nummodes];
 
-		INT32 width = windowedModes[i][0];
-		INT32 height = windowedModes[i][1];
+		INT32 width = res[i].width;
+		INT32 height = res[i].height;
 
 		desc->width = width;
 		desc->height = height;
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index e71426be10..54ccdeea98 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -235,7 +235,7 @@ static SDL_DisplayMode *Impl_ListAvailableResolutions(INT32 *count)
 
 	// TODO: add support for multiple monitors
 	nummodes = SDL_GetNumDisplayModes(0);
-	modes = Z_Malloc(sizeof(SDL_DisplayMode) * nummodes, PU_STATIC, NULL);
+	Z_Malloc(sizeof(SDL_DisplayMode) * nummodes, PU_STATIC, &modes);
 	CONS_Printf("Available resolutions:\n");
 	for (i = 0; i < nummodes; i++)
 	{
@@ -247,6 +247,23 @@ static SDL_DisplayMode *Impl_ListAvailableResolutions(INT32 *count)
 	return modes;
 }
 
+resolution_t *VID_GetSupportedResolutions(INT32 *count)
+{
+	SDL_DisplayMode *modes = Impl_ListAvailableResolutions(count);
+	static resolution_t *res;
+	if (res != NULL)
+		return res;
+
+	Z_Malloc(sizeof(resolution_t *) * *count, PU_STATIC, &res);
+	for (INT32 i = 0; i < *count; i++)
+	{
+		res[i].width = modes[i].w;
+		res[i].height = modes[i].h;
+	}
+
+	return res;
+}
+
 static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition)
 {
 	int fullscreen_type = SDL_WINDOW_FULLSCREEN;
-- 
GitLab


From 285eaa2e1a0ce495fed371b46bf3c8adfa84c1e8 Mon Sep 17 00:00:00 2001
From: Hanicef <gustaf@hanicef.me>
Date: Mon, 31 Mar 2025 17:01:13 +0200
Subject: [PATCH 10/14] Scale manually if video mode change was ignored

---
 src/sdl/i_video.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 54ccdeea98..5dc6e9c3ef 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -266,8 +266,6 @@ resolution_t *VID_GetSupportedResolutions(INT32 *count)
 
 static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition)
 {
-	int fullscreen_type = SDL_WINDOW_FULLSCREEN;
-
 	if (window)
 	{
 		if (fullscreen)
@@ -330,8 +328,6 @@ static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_b
 					SDL_SetWindowDisplayMode(window, &resolution);
 				}
 			}
-
-			SDL_SetWindowFullscreen(window, fullscreen_type);
 		}
 
 		Impl_SetDefaultWindowSizes();
@@ -1327,11 +1323,28 @@ void I_FinishUpdate(void)
 		SDL_Surface *surface = SDL_GetWindowSurface(window);
 		SDL_LockSurface(surface);
 		UINT32 *restrict pixels = surface->pixels;
-		INT32 size = surface->w * surface->h;
 		const UINT8 *restrict source = screens[0];
-		INT32 i;
-		for (i = 0; i < size; i++)
-			*pixels++ = softPalette[*source++];
+		if (surface->w != vid.width || surface->h != vid.height)
+		{
+			// the screen doesn't allow the resolution even though it was supported
+			// this happens on wayland for some reason
+			// as a workaround, scale manually so graphics don't get fucked
+			INT32 skip = surface->w - vid.width;
+			INT32 i, j;
+			for (i = 0; i < vid.height; i++)
+			{
+				for (j = 0; j < vid.width; j++)
+					*pixels++ = softPalette[*source++];
+				pixels += skip;
+			}
+		}
+		else
+		{
+			INT32 size = surface->w * surface->h;
+			INT32 i;
+			for (i = 0; i < size; i++)
+				*pixels++ = softPalette[*source++];
+		}
 		SDL_UnlockSurface(surface);
 		SDL_UpdateWindowSurface(window);
 	}
@@ -1547,13 +1560,15 @@ void VID_RestoreWindow(void)
 
 static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 {
-	int flags = SDL_WINDOW_RESIZABLE;
+	int flags;
 
 	if (window != NULL)
 		return SDL_TRUE;
 
 	if (fullscreen)
-		flags |= SDL_WINDOW_FULLSCREEN;
+		flags = SDL_WINDOW_FULLSCREEN;
+	else
+		flags = SDL_WINDOW_RESIZABLE;
 
 	if (borderlesswindow)
 		flags |= SDL_WINDOW_BORDERLESS;
@@ -1575,7 +1590,8 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 		return SDL_FALSE;
 	}
 
-	SDL_SetWindowMinimumSize(window, BASEVIDWIDTH, BASEVIDHEIGHT);
+	if (!fullscreen)
+		SDL_SetWindowMinimumSize(window, BASEVIDWIDTH, BASEVIDHEIGHT);
 
 #ifdef USE_WINDOW_ICON
 	Impl_SetWindowIcon();
-- 
GitLab


From 024984c82137dfbb9119e4a24d811af99598676f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Tue, 1 Apr 2025 00:31:26 +0200
Subject: [PATCH 11/14] Do not list duplicate resolutions

---
 src/i_video.h     |  5 +++--
 src/sdl/i_video.c | 33 +++++++++++++++++++++++----------
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/src/i_video.h b/src/i_video.h
index fb171abe60..847faf2913 100644
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -34,8 +34,9 @@ typedef enum
 
 typedef struct
 {
-	UINT32 width;
-	UINT32 height;
+	UINT16 width;
+	UINT16 height;
+	UINT8 index;
 } resolution_t;
 
 /**	\brief current render mode
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 5dc6e9c3ef..0bbd9a0c58 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -254,13 +254,24 @@ resolution_t *VID_GetSupportedResolutions(INT32 *count)
 	if (res != NULL)
 		return res;
 
-	Z_Malloc(sizeof(resolution_t *) * *count, PU_STATIC, &res);
+	res = Z_Malloc(sizeof(resolution_t *) * *count, PU_STATIC, NULL);
+	INT32 j = 0;
 	for (INT32 i = 0; i < *count; i++)
 	{
-		res[i].width = modes[i].w;
-		res[i].height = modes[i].h;
+		if (i > 0 && modes[i-1].w == modes[i].w && modes[i-1].h == modes[i].h)
+		{
+			// pick the highest refresh rate of all duplicate resolutions
+			if (modes[i-1].refresh_rate < modes[i].refresh_rate)
+				res[j-1].index = i;
+			continue;
+		}
+
+		res[j].width = modes[i].w;
+		res[j].height = modes[i].h;
+		res[j++].index = i;
 	}
 
+	*count = j;
 	return res;
 }
 
@@ -298,15 +309,17 @@ static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_b
 		SDL_SetWindowSize(window, width, height);
 		if (fullscreen)
 		{
-			SDL_DisplayMode *modes;
-			INT32 nummodes, i;
+			resolution_t *res;
+			INT32 numres, i;
 
-			modes = Impl_ListAvailableResolutions(&nummodes);
-			for (i = 0; i < nummodes; i++)
+			res = VID_GetSupportedResolutions(&numres);
+			for (i = 0; i < numres; i++)
 			{
-				if (modes[i].w == width && modes[i].h == height)
+				if (res[i].width == width && res[i].height == height)
 				{
-					if (SDL_SetWindowDisplayMode(window, &modes[i]))
+					SDL_DisplayMode mode;
+					SDL_GetDisplayMode(0, res[i].index, &mode);
+					if (SDL_SetWindowDisplayMode(window, &mode))
 					{
 						CONS_Alert(CONS_WARNING, "Couldn't change resolution to %dx%d: %s\n", width, height, SDL_GetError());
 						continue;
@@ -315,7 +328,7 @@ static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_b
 				}
 			}
 
-			if (i == nummodes)
+			if (i == numres)
 			{
 				// resolution is not supported, so default to native
 				CONS_Alert(CONS_WARNING, "Resolution %dx%d is not supported, defaulting to native\n", width, height);
-- 
GitLab


From a09e1251f479054d23c012ca66a37da90416d9bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Tue, 1 Apr 2025 16:17:20 +0200
Subject: [PATCH 12/14] Clean up and refactor

---
 src/screen.c      | 50 -------------------------
 src/screen.h      |  7 ----
 src/sdl/i_video.c | 95 ++++++++++++++++++++++-------------------------
 3 files changed, 44 insertions(+), 108 deletions(-)

diff --git a/src/screen.c b/src/screen.c
index 085e2ab0d1..8978ed47f6 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -61,29 +61,6 @@ void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void);
 // ------------------
 viddef_t vid;
 
-// windowed video modes from which to choose from.
-INT32 windowedModes[MAXWINMODES][2] =
-{
-	{1920,1200}, // 1.60,6.00
-	{1920,1080}, // 1.66
-	{1680,1050}, // 1.60,5.25
-	{1600,1200}, // 1.33
-	{1600, 900}, // 1.66
-	{1366, 768}, // 1.66
-	{1440, 900}, // 1.60,4.50
-	{1280,1024}, // 1.33?
-	{1280, 960}, // 1.33,4.00
-	{1280, 800}, // 1.60,4.00
-	{1280, 720}, // 1.66
-	{1152, 864}, // 1.33,3.60
-	{1024, 768}, // 1.33,3.20
-	{ 800, 600}, // 1.33,2.50
-	{ 640, 480}, // 1.33,2.00
-	{ 640, 400}, // 1.60,2.00
-	{ 320, 240}, // 1.33,1.00
-	{ 320, 200}, // 1.60,1.00
-};
-
 static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}};
 
 //added : 03-02-98: default screen mode, as loaded/saved in config
@@ -454,33 +431,6 @@ boolean SCR_IsAspectCorrect(INT32 width, INT32 height)
 	 );
 }
 
-const char *SCR_GetModeName(INT32 modeNum)
-{
-	static char vidModeName[MAXWINMODES][32];
-
-	if (modeNum == -1)
-		return "Fallback";
-	else if (modeNum > MAXWINMODES)
-		return NULL;
-
-	snprintf(&vidModeName[modeNum][0], 32, "%dx%d", windowedModes[modeNum][0], windowedModes[modeNum][1]);
-
-	return &vidModeName[modeNum][0];
-}
-
-INT32 SCR_GetModeForSize(INT32 w, INT32 h)
-{
-	int i;
-	for (i = 0; i < MAXWINMODES; i++)
-	{
-		if (windowedModes[i][0] == w && windowedModes[i][1] == h)
-		{
-			return i;
-		}
-	}
-	return -1;
-}
-
 // XMOD FPS display
 // moved out of os-specific code for consistency
 static boolean ticsgraph[TICRATE];
diff --git a/src/screen.h b/src/screen.h
index 2a9767dbd3..5cb53e0779 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -85,10 +85,6 @@ enum
 	VID_GL_LIBRARY_ERROR
 };
 
-#define MAXWINMODES 18
-
-extern INT32 windowedModes[MAXWINMODES][2];
-
 // ---------------------------------------------
 // color mode dependent drawer function pointers
 // ---------------------------------------------
@@ -164,9 +160,6 @@ void SCR_SetWindowSize(INT32 width, INT32 height);
 void SCR_SetSizeNoRestore(INT32 width, INT32 height);
 void SCR_ChangeRenderer(void);
 
-const char *SCR_GetModeName(INT32 modeNum);
-INT32 SCR_GetModeForSize(INT32 w, INT32 h);
-
 boolean SCR_IsValidResolution(INT32 width, INT32 height);
 
 extern CV_PossibleValue_t cv_renderer_t[];
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 0bbd9a0c58..038117d831 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -222,56 +222,45 @@ static void Impl_SetupSoftwareBuffer(void)
 		I_Error("%s", M_GetText("Not enough memory for video buffer\n"));
 }
 
-static SDL_DisplayMode *Impl_ListAvailableResolutions(INT32 *count)
-{
-	static SDL_DisplayMode *modes;
-	static INT32 nummodes;
-	INT32 i;
-	if (modes != NULL)
-	{
-		*count = nummodes;
-		return modes;
-	}
-
-	// TODO: add support for multiple monitors
-	nummodes = SDL_GetNumDisplayModes(0);
-	Z_Malloc(sizeof(SDL_DisplayMode) * nummodes, PU_STATIC, &modes);
-	CONS_Printf("Available resolutions:\n");
-	for (i = 0; i < nummodes; i++)
-	{
-		SDL_GetDisplayMode(0, i, &modes[i]);
-		CONS_Printf(" * %dx%d@%d\n", modes[i].w, modes[i].h, modes[i].refresh_rate);
-	}
-
-	*count = nummodes;
-	return modes;
-}
-
 resolution_t *VID_GetSupportedResolutions(INT32 *count)
 {
-	SDL_DisplayMode *modes = Impl_ListAvailableResolutions(count);
 	static resolution_t *res;
+	static INT32 numres;
 	if (res != NULL)
+	{
+		*count = numres;
 		return res;
+	}
+
+	// TODO: add support for multiple monitors
+	INT32 nummodes = SDL_GetNumDisplayModes(0);
+	SDL_DisplayMode mode, prevmode;
 
-	res = Z_Malloc(sizeof(resolution_t *) * *count, PU_STATIC, NULL);
-	INT32 j = 0;
-	for (INT32 i = 0; i < *count; i++)
+	res = Z_Malloc(sizeof(resolution_t *) * nummodes, PU_STATIC, NULL);
+	numres = 0;
+	CONS_Printf("Available resolutions:\n");
+	for (INT32 i = 0; i < nummodes; i++)
 	{
-		if (i > 0 && modes[i-1].w == modes[i].w && modes[i-1].h == modes[i].h)
+		SDL_GetDisplayMode(0, i, &mode);
+		CONS_Printf(" * %dx%d@%d\n", mode.w, mode.h, mode.refresh_rate);
+		if (i > 0 && prevmode.w == mode.w && prevmode.h == mode.h)
 		{
 			// pick the highest refresh rate of all duplicate resolutions
-			if (modes[i-1].refresh_rate < modes[i].refresh_rate)
-				res[j-1].index = i;
+			if (prevmode.refresh_rate < mode.refresh_rate)
+			{
+				res[numres-1].index = i;
+				prevmode = mode;
+			}
 			continue;
 		}
 
-		res[j].width = modes[i].w;
-		res[j].height = modes[i].h;
-		res[j++].index = i;
+		res[numres].width = mode.w;
+		res[numres].height = mode.h;
+		res[numres++].index = i;
+		prevmode = mode;
 	}
 
-	*count = j;
+	*count = numres;
 	return res;
 }
 
@@ -334,7 +323,7 @@ static SDL_bool SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_b
 				CONS_Alert(CONS_WARNING, "Resolution %dx%d is not supported, defaulting to native\n", width, height);
 				SDL_DisplayMode resolution;
 
-				if (SDL_GetCurrentDisplayMode(i, &resolution) == 0)
+				if (SDL_GetDesktopDisplayMode(i, &resolution) == 0)
 				{
 					vid.width = width = (INT32)(resolution.w);
 					vid.height = height = (INT32)(resolution.h);
@@ -588,13 +577,17 @@ void I_SetMouseGrab(boolean grab)
 
 static void VID_Command_NumModes_f (void)
 {
-	CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), MAXWINMODES);
+	INT32 numres;
+	VID_GetSupportedResolutions(&numres);
+	CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), numres);
 }
 
 static void VID_Command_ModeList_f(void)
 {
-	for (INT32 i = 0; i < MAXWINMODES; i++)
-		CONS_Printf("%2d: %dx%d\n", i, windowedModes[i][0], windowedModes[i][1]);
+	INT32 numres;
+	resolution_t *res = VID_GetSupportedResolutions(&numres);
+	for (INT32 i = 0; i < numres; i++)
+		CONS_Printf("%2d: %dx%d\n", i, res[i].width, res[i].height);
 }
 
 static void VID_Command_Mode_f (void)
@@ -605,16 +598,18 @@ static void VID_Command_Mode_f (void)
 		return;
 	}
 
+	INT32 numres;
+	resolution_t *res = VID_GetSupportedResolutions(&numres);
 	INT32 modenum = atoi(COM_Argv(1));
-	if (modenum >= MAXWINMODES)
+	if (modenum >= numres)
 		CONS_Printf(M_GetText("Video mode not present\n"));
 	else
 	{
 		if (modenum < 0)
 			modenum = 0;
 
-		vid.change.width = windowedModes[modenum][0];
-		vid.change.height = windowedModes[modenum][1];
+		vid.change.width = res[modenum].width;
+		vid.change.height = res[modenum].height;
 		vid.change.set = VID_RESOLUTION_CHANGED;
 	}
 }
@@ -628,11 +623,11 @@ boolean SCR_IsValidResolution(INT32 width, INT32 height)
 
 	if (USE_FULLSCREEN)
 	{
-		INT32 nummodes, i;
-		SDL_DisplayMode *modes = Impl_ListAvailableResolutions(&nummodes);
-		for (i = 0; i < nummodes; i++)
+		INT32 numres, i;
+		resolution_t *res = VID_GetSupportedResolutions(&numres);
+		for (i = 0; i < numres; i++)
 		{
-			if (modes[i].w == width && modes[i].h == height)
+			if (res[i].width == width && res[i].height == height)
 				return true;
 		}
 		return false;
@@ -1573,15 +1568,13 @@ void VID_RestoreWindow(void)
 
 static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 {
-	int flags;
+	int flags = SDL_WINDOW_RESIZABLE;
 
 	if (window != NULL)
 		return SDL_TRUE;
 
 	if (fullscreen)
-		flags = SDL_WINDOW_FULLSCREEN;
-	else
-		flags = SDL_WINDOW_RESIZABLE;
+		flags |= SDL_WINDOW_FULLSCREEN;
 
 	if (borderlesswindow)
 		flags |= SDL_WINDOW_BORDERLESS;
-- 
GitLab


From 12e72fc93ebaf0579877fb90c666e551b2e92d9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Tue, 1 Apr 2025 17:37:27 +0200
Subject: [PATCH 13/14] Fix segfault when flipping buffer if the window is not
 ready

---
 src/sdl/i_video.c | 44 ++++++++++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 038117d831..e5998adcd4 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1329,31 +1329,35 @@ void I_FinishUpdate(void)
 	if (rendermode == render_soft && screens[0])
 	{
 		SDL_Surface *surface = SDL_GetWindowSurface(window);
-		SDL_LockSurface(surface);
-		UINT32 *restrict pixels = surface->pixels;
-		const UINT8 *restrict source = screens[0];
-		if (surface->w != vid.width || surface->h != vid.height)
+		// make sure the surface is ready before we render
+		if (surface != NULL)
 		{
-			// the screen doesn't allow the resolution even though it was supported
-			// this happens on wayland for some reason
-			// as a workaround, scale manually so graphics don't get fucked
-			INT32 skip = surface->w - vid.width;
-			INT32 i, j;
-			for (i = 0; i < vid.height; i++)
+			SDL_LockSurface(surface);
+			UINT32 *restrict pixels = surface->pixels;
+			const UINT8 *restrict source = screens[0];
+			if (surface->w != vid.width || surface->h != vid.height)
 			{
-				for (j = 0; j < vid.width; j++)
+				// the screen doesn't allow the resolution even though it was supported
+				// this happens on wayland for some reason
+				// as a workaround, scale manually so graphics don't get fucked
+				INT32 skip = surface->w - vid.width;
+				INT32 i, j;
+				for (i = 0; i < vid.height; i++)
+				{
+					for (j = 0; j < vid.width; j++)
+						*pixels++ = softPalette[*source++];
+					pixels += skip;
+				}
+			}
+			else
+			{
+				INT32 size = surface->w * surface->h;
+				INT32 i;
+				for (i = 0; i < size; i++)
 					*pixels++ = softPalette[*source++];
-				pixels += skip;
 			}
+			SDL_UnlockSurface(surface);
 		}
-		else
-		{
-			INT32 size = surface->w * surface->h;
-			INT32 i;
-			for (i = 0; i < size; i++)
-				*pixels++ = softPalette[*source++];
-		}
-		SDL_UnlockSurface(surface);
 		SDL_UpdateWindowSurface(window);
 	}
 #ifdef HWRENDER
-- 
GitLab


From bc0a3ef496cf90b092a7da26780e964e12948d17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Wed, 2 Apr 2025 21:51:38 +0200
Subject: [PATCH 14/14] Avoid flipping buffer if the window is forced smaller
 than supported

---
 src/sdl/i_video.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index e5998adcd4..b8d7d88140 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1332,6 +1332,9 @@ void I_FinishUpdate(void)
 		// make sure the surface is ready before we render
 		if (surface != NULL)
 		{
+			if (surface->w < vid.width || surface->h < vid.height)
+				return; // sway/x11 forced us into a lower resolution than we support, don't render
+
 			SDL_LockSurface(surface);
 			UINT32 *restrict pixels = surface->pixels;
 			const UINT8 *restrict source = screens[0];
-- 
GitLab