diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c
index ea5691e7cd8e60aacce052ab8950eb892df85ba2..a34a20e9a9737241bbc183d71f8bae01a982cb7a 100644
--- a/src/r_draw8_npo2.c
+++ b/src/r_draw8_npo2.c
@@ -818,6 +818,8 @@ void R_DrawFloorSprite_NPO2_8 (void)
 	fixed_t xposition;
 	fixed_t yposition;
 	fixed_t xstep, ystep;
+	fixed_t x, y;
+	fixed_t fixedwidth, fixedheight;
 
 	UINT16 *source;
 	UINT8 *translation;
@@ -836,20 +838,39 @@ void R_DrawFloorSprite_NPO2_8 (void)
 	translation = ds_translation;
 	dest = ylookup[ds_y] + columnofs[ds_x1];
 
-	while (count-- && dest <= deststop)
-	{
-		fixed_t x = (xposition >> FRACBITS);
-		fixed_t y = (yposition >> FRACBITS);
+	fixedwidth = ds_flatwidth << FRACBITS;
+	fixedheight = ds_flatheight << FRACBITS;
 
-		// Carefully align all of my Friends.
-		if (x < 0)
-			x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
-		if (y < 0)
-			y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
+	// Fix xposition and yposition if they are out of bounds.
+	if (xposition < 0)
+		xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth);
+	else if (xposition >= fixedwidth)
+		xposition %= fixedwidth;
+	if (yposition < 0)
+		yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight);
+	else if (yposition >= fixedheight)
+		yposition %= fixedheight;
 
-		x %= ds_flatwidth;
-		y %= ds_flatheight;
+	while (count-- && dest <= deststop)
+	{
+		// The loops here keep the texture coordinates within the texture.
+		// They will rarely iterate multiple times, and are cheaper than a modulo operation,
+		// even if using libdivide.
+		if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop
+			while (xposition < 0)
+				xposition += fixedwidth;
+		else
+			while (xposition >= fixedwidth)
+				xposition -= fixedwidth;
+		if (ystep < 0)
+			while (yposition < 0)
+				yposition += fixedheight;
+		else
+			while (yposition >= fixedheight)
+				yposition -= fixedheight;
 
+		x = (xposition >> FRACBITS);
+		y = (yposition >> FRACBITS);
 		val = source[((y * ds_flatwidth) + x)];
 		if (val & 0xFF00)
 			*dest = colormap[translation[val & 0xFF]];
@@ -867,6 +888,8 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void)
 	fixed_t xposition;
 	fixed_t yposition;
 	fixed_t xstep, ystep;
+	fixed_t x, y;
+	fixed_t fixedwidth, fixedheight;
 
 	UINT16 *source;
 	UINT8 *translation;
@@ -885,20 +908,39 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void)
 	translation = ds_translation;
 	dest = ylookup[ds_y] + columnofs[ds_x1];
 
-	while (count-- && dest <= deststop)
-	{
-		fixed_t x = (xposition >> FRACBITS);
-		fixed_t y = (yposition >> FRACBITS);
+	fixedwidth = ds_flatwidth << FRACBITS;
+	fixedheight = ds_flatheight << FRACBITS;
 
-		// Carefully align all of my Friends.
-		if (x < 0)
-			x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
-		if (y < 0)
-			y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
+	// Fix xposition and yposition if they are out of bounds.
+	if (xposition < 0)
+		xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth);
+	else if (xposition >= fixedwidth)
+		xposition %= fixedwidth;
+	if (yposition < 0)
+		yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight);
+	else if (yposition >= fixedheight)
+		yposition %= fixedheight;
 
-		x %= ds_flatwidth;
-		y %= ds_flatheight;
+	while (count-- && dest <= deststop)
+	{
+		// The loops here keep the texture coordinates within the texture.
+		// They will rarely iterate multiple times, and are cheaper than a modulo operation,
+		// even if using libdivide.
+		if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop
+			while (xposition < 0)
+				xposition += fixedwidth;
+		else
+			while (xposition >= fixedwidth)
+				xposition -= fixedwidth;
+		if (ystep < 0)
+			while (yposition < 0)
+				yposition += fixedheight;
+		else
+			while (yposition >= fixedheight)
+				yposition -= fixedheight;
 
+		x = (xposition >> FRACBITS);
+		y = (yposition >> FRACBITS);
 		val = source[((y * ds_flatwidth) + x)];
 		if (val & 0xFF00)
 			*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);