diff --git a/source/common/2d/v_2ddrawer.cpp b/source/common/2d/v_2ddrawer.cpp
index cf1c0a637..32296fa72 100644
--- a/source/common/2d/v_2ddrawer.cpp
+++ b/source/common/2d/v_2ddrawer.cpp
@@ -426,13 +426,11 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms)
 	if (parms.flipX)
 	{
 		std::swap(u1, u2);
-		parms.left = parms.texwidth - parms.left;
 	}
 
 	if (parms.flipY)
 	{
 		std::swap(v1, v2);
-		parms.top = parms.texheight - parms.top;
 	}
 
 	if (parms.rotateangle == 0)
diff --git a/source/common/2d/v_draw.cpp b/source/common/2d/v_draw.cpp
index 1bde79cea..b18f4e94a 100644
--- a/source/common/2d/v_draw.cpp
+++ b/source/common/2d/v_draw.cpp
@@ -413,6 +413,9 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
 		parms->destwidth *= parms->patchscalex;
 		parms->destheight *= parms->patchscaley;
 
+		if (parms->flipoffsets && parms->flipY) parms->top = parms->texwidth - parms->top;
+		if (parms->flipoffsets && parms->flipX) parms->left = parms->texwidth - parms->left;
+
 		switch (parms->cleanmode)
 		{
 		default:
@@ -637,6 +640,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
 	parms->patchscalex = parms->patchscaley = 1;
 	parms->viewport = { 0,0,drawer->GetWidth(), drawer->GetHeight() };
 	parms->rotateangle = 0;
+	parms->flipoffsets = false;
 
 	// Parse the tag list for attributes. (For floating point attributes,
 	// consider that the C ABI dictates that all floats be promoted to
@@ -834,6 +838,10 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
 			parms->flipY = ListGetInt(tags);
 			break;
 
+		case DTA_FlipOffsets:
+			parms->flipoffsets = ListGetInt(tags);
+			break;
+
 		case DTA_SrcX:
 			parms->srcx = ListGetDouble(tags) / img->GetDisplayWidth();
 			break;
diff --git a/source/common/2d/v_draw.h b/source/common/2d/v_draw.h
index be4142145..4b2dc01a6 100644
--- a/source/common/2d/v_draw.h
+++ b/source/common/2d/v_draw.h
@@ -104,6 +104,7 @@ enum
 	DTA_TopLeft,			// always align to top left. Added to have a boolean condition for this alignment.
 	DTA_Pin,				// Pin a non-widescreen image to the left/right edge of the screen.
 	DTA_Rotate,
+	DTA_FlipOffsets,		// Flips offsets when using DTA_FlipX and DTA_FlipY, this cannot be automatic due to unexpected behavior with unoffsetted graphics.
 
 };
 
@@ -169,6 +170,7 @@ struct DrawParms
 	bool fortext;
 	bool virtBottom;
 	bool burn;
+	bool flipoffsets;
 	int8_t fsscalemode;
 	double srcx, srcy;
 	double srcwidth, srcheight;
diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp
index 4afe2e13c..8e79f074e 100644
--- a/source/glbackend/glbackend.cpp
+++ b/source/glbackend/glbackend.cpp
@@ -550,6 +550,7 @@ void hud_drawsprite(double sx, double sy, int z, int a, int picnum, int dashade,
 		DTA_FlipX, !!(dastat & RS_YFLIP),      // the weapon drawer uses y-flip+180� rotation for x-flip but no other transformation.
 		DTA_Pin, (dastat & RS_ALIGN_R) ? 1 : (dastat & RS_ALIGN_L) ? -1 : 0,
 		DTA_Rotate, a * (-360./2048),
+		DTA_FlipOffsets, !(dastat & (RS_TOPLEFT | RS_CENTER)),
 		TAG_DONE);
 }