diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c
index f902b48020058eaac5142219bc9fdcd7245672a3..0a09a2b410cc505493639f2c1b1a16b1982c72ab 100644
--- a/src/hardware/hw_draw.c
+++ b/src/hardware/hw_draw.c
@@ -194,36 +194,22 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
 			float adjustx = ((option & V_NOSCALESTART) ? vid.width : BASEVIDWIDTH)/2.0f;
 			pdupx /= 2;
 			cx /= 2;
-			if (stplyr == &players[displayplayer])
-				option &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
-			else if (stplyr == &players[secondarydisplayplayer])
-			{
+			if (stplyr == &players[secondarydisplayplayer])
 				cx += adjustx;
-				option &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
-			}
 			else if (stplyr == &players[thirddisplayplayer])
-			{
 				cy += adjusty;
-				option &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
-			}
-			else //if (stplyr == &players[fourthdisplayplayer])
+			else if (stplyr == &players[fourthdisplayplayer])
 			{
 				cx += adjustx;
 				cy += adjusty;
-				option &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
 			}
 		}
 		else
 #endif
 		// 2 players
 		{
-			if (stplyr == &players[displayplayer])
-				option &= ~V_SNAPTOBOTTOM;
-			else //if (stplyr == &players[secondarydisplayplayer])
-			{
+			if (stplyr == &players[secondarydisplayplayer])
 				cy += adjusty;
-				option &= ~V_SNAPTOTOP;
-			}
 		}
 	}
 
@@ -323,6 +309,37 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
 	if (option & V_NOSCALESTART)
 		sdupx = sdupy = 2.0f;
 
+	if (splitscreen && (option & V_PERPLAYER))
+	{
+		float adjusty = ((option & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
+		pdupy /= 2;
+		cy /= 2;
+		// unlike software no need to adjust texture sourcing
+#ifdef QUADS
+		if (splitscreen > 1) // 3 or 4 players
+		{
+			float adjustx = ((option & V_NOSCALESTART) ? vid.width : BASEVIDWIDTH)/2.0f;
+			pdupx /= 2;
+			cx /= 2;
+			if (stplyr == &players[secondarydisplayplayer])
+				cx += adjustx;
+			else if (stplyr == &players[thirddisplayplayer])
+				cy += adjusty;
+			if (stplyr == &players[fourthdisplayplayer])
+			{
+				cx += adjustx;
+				cy += adjusty;
+			}
+		}
+		else
+#endif
+		// 2 players
+		{
+			if (stplyr == &players[secondarydisplayplayer])
+				cy += adjusty;
+		}
+	}
+
 	v[0].x = v[3].x =     (cx*sdupx -           gpatch->leftoffset  * pdupx) / vid.width - 1;
 	v[2].x = v[1].x =     (cx*sdupx + ((w) - gpatch->leftoffset) * pdupx) / vid.width - 1;
 	v[0].y = v[1].y = 1 - (cy*sdupy -           gpatch->topoffset   * pdupy) / vid.height;
@@ -718,6 +735,36 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
 	if (color & V_NOSCALESTART)
 		sdupx = sdupy = 2.0f;
 
+	if (splitscreen && (color & V_PERPLAYER))
+	{
+		float adjusty = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
+		w >>= 1;
+		y >>= 1;
+#ifdef QUADS
+		if (splitscreen > 1) // 3 or 4 players
+		{
+			float adjustx = ((color & V_NOSCALESTART) ? vid.width : BASEVIDWIDTH)/2.0f;
+			w >>= 1;
+			x >>= 1;
+			if (stplyr == &players[secondarydisplayplayer])
+				x += adjustx;
+			else if (stplyr == &players[thirddisplayplayer])
+				y += adjusty;
+			else if (stplyr == &players[fourthdisplayplayer])
+			{
+				x += adjustx;
+				y += adjusty;
+			}
+		}
+		else
+#endif
+		// 2 players
+		{
+			if (stplyr == &players[secondarydisplayplayer])
+				y += adjusty;
+		}
+	}
+
 	v[0].x = v[3].x = (x*sdupx)/vid.width - 1;
 	v[2].x = v[1].x = (x*sdupx + w*sdupx)/vid.width - 1;
 	v[0].y = v[1].y = 1-(y*sdupy)/vid.height;
diff --git a/src/v_video.c b/src/v_video.c
index c9ab2933d42d0a4a4af32a30c6b6b7c9a38c0c42..10d2d9af5acc2acbd56fe2a3ad4e8fb0549ad521 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -714,9 +714,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
 			if (vid.height != BASEVIDHEIGHT * dupy)
 			{
 				// same thing here
-				/*if ((scrn & (V_PERPLAYER|V_SNAPTOBOTTOM)) == (V_PERPLAYER|V_SNAPTOBOTTOM))
-					y += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy));
-				else */if (scrn & V_SNAPTOBOTTOM)
+				if (scrn & V_SNAPTOBOTTOM)
 					y += (vid.height - (BASEVIDHEIGHT * dupy));
 				else if (!(scrn & V_SNAPTOTOP))
 					y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
@@ -837,6 +835,60 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
 	y -= FixedMul(SHORT(patch->topoffset)<<FRACBITS, pscale);
 	x -= FixedMul(SHORT(patch->leftoffset)<<FRACBITS, pscale);
 
+	if (splitscreen && (scrn & V_PERPLAYER))
+	{
+		fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
+		fdup >>= 1;
+		rowfrac <<= 1;
+		y >>= 1;
+		sy >>= 1;
+		h >>= 1;
+#ifdef QUADS
+		if (splitscreen > 1) // 3 or 4 players
+		{
+			fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1));
+			colfrac <<= 1;
+			x >>= 1;
+			sx >>= 1;
+			w >>= 1;
+			if (stplyr == &players[displayplayer])
+				scrn &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
+			else if (stplyr == &players[secondarydisplayplayer])
+			{
+				x += adjustx;
+				sx += adjustx;
+				scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
+			}
+			else if (stplyr == &players[thirddisplayplayer])
+			{
+				y += adjusty;
+				sy += adjusty;
+				scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
+			}
+			else //if (stplyr == &players[fourthdisplayplayer])
+			{
+				x += adjustx;
+				sx += adjustx;
+				y += adjusty;
+				sy += adjusty;
+				scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
+			}
+		}
+		else
+#endif
+		// 2 players
+		{
+			if (stplyr == &players[displayplayer])
+				scrn &= ~V_SNAPTOBOTTOM;
+			else //if (stplyr == &players[secondarydisplayplayer])
+			{
+				y += adjusty;
+				sy += adjusty;
+				scrn &= ~V_SNAPTOTOP;
+			}
+		}
+	}
+
 	desttop = screens[scrn&V_PARAMMASK];
 
 	if (!desttop)
@@ -879,9 +931,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
 			if (vid.height != BASEVIDHEIGHT * dupy)
 			{
 				// same thing here
-				if ((scrn & (V_PERPLAYER|V_SNAPTOBOTTOM)) == (V_PERPLAYER|V_SNAPTOBOTTOM))
-					y += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy));
-				else if (scrn & V_SNAPTOBOTTOM)
+				if (scrn & V_SNAPTOBOTTOM)
 					y += (vid.height - (BASEVIDHEIGHT * dupy));
 				else if (!(scrn & V_SNAPTOTOP))
 					y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
@@ -1042,6 +1092,50 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
 	}
 #endif
 
+	if (splitscreen && (c & V_PERPLAYER))
+	{
+		fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
+		h >>= 1;
+		y >>= 1;
+#ifdef QUADS
+		if (splitscreen > 1) // 3 or 4 players
+		{
+			fixed_t adjustx = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
+			w >>= 1;
+			x >>= 1;
+			if (stplyr == &players[displayplayer])
+				c &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
+			else if (stplyr == &players[secondarydisplayplayer])
+			{
+				x += adjustx;
+				c &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
+			}
+			else if (stplyr == &players[thirddisplayplayer])
+			{
+				y += adjusty;
+				c &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
+			}
+			else //if (stplyr == &players[fourthdisplayplayer])
+			{
+				x += adjustx;
+				y += adjusty;
+				c &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
+			}
+		}
+		else
+#endif
+		// 2 players
+		{
+			if (stplyr == &players[displayplayer])
+				c &= ~V_SNAPTOBOTTOM;
+			else //if (stplyr == &players[secondarydisplayplayer])
+			{
+				y += adjusty;
+				c &= ~V_SNAPTOTOP;
+			}
+		}
+	}
+
 	if (!(c & V_NOSCALESTART))
 	{
 		INT32 dupx = vid.dupx, dupy = vid.dupy;
diff --git a/src/v_video.h b/src/v_video.h
index 66fd2f4304b2566fccbe5248fdef8adedabc58ff..c5dfd35a500ec8be1e3fced1e2e4c63faf329490 100644
--- a/src/v_video.h
+++ b/src/v_video.h
@@ -112,8 +112,8 @@ extern RGBA_t *pMasterPalette;
 #define V_WRAPX              0x10000000 // Don't clamp texture on X (for HW mode)
 #define V_WRAPY              0x20000000 // Don't clamp texture on Y (for HW mode)
 
-#define V_NOSCALESTART       0x40000000  // don't scale x, y, start coords
-#define V_PERPLAYER        0x80000000
+#define V_NOSCALESTART       0x40000000 // don't scale x, y, start coords
+#define V_PERPLAYER          0x80000000 // automatically adjust coordinates/scaling for splitscreen mode
 
 // defines for old functions
 #define V_DrawPatch(x,y,s,p) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT, s|V_NOSCALESTART|V_NOSCALEPATCH, p, NULL)