diff --git a/src/r_patch.c b/src/r_patch.c
index e123414017eda7f26d321dbc8aa6806ede04145f..9ca04dd55e60506c9d0fe31d1c2cdf9466d1e185 100644
--- a/src/r_patch.c
+++ b/src/r_patch.c
@@ -47,11 +47,11 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest)
 		}
 
 		if (!srcsize)
-			I_Error("R_CreatePatch: no source size!");
+			I_Error("Patch_Create: no source size!");
 
 		colsize = (INT32)(srcsize) - (INT32)offs;
 		if (colsize <= 0)
-			I_Error("R_CreatePatch: no column data!");
+			I_Error("Patch_Create: no column data!");
 
 		patch->columns = Z_Calloc(colsize, PU_PATCH_DATA, NULL);
 		M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize);
diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c
index 803e159ef5cb24b04ba5bd79f7f74b4588409b7f..98e3a7687f37ddd4e348947d6fa7d9da5dac6d61 100644
--- a/src/r_patchrotation.c
+++ b/src/r_patchrotation.c
@@ -82,6 +82,9 @@ patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spri
 		}
 
 		RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip);
+
+		//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
+		((patch_t *)rotsprite->patches[idx])->topoffset += FEETADJUST>>FRACBITS;
 	}
 
 	return rotsprite->patches[idx];
@@ -102,10 +105,32 @@ rotsprite_t *RotatedPatch_Create(INT32 numangles)
 	return rotsprite;
 }
 
+static void RotatedPatch_CalculateDimensions(
+	INT32 width, INT32 height,
+	fixed_t ca, fixed_t sa,
+	INT32 *newwidth, INT32 *newheight)
+{
+	fixed_t fixedwidth = (width * FRACUNIT);
+	fixed_t fixedheight = (height * FRACUNIT);
+
+	fixed_t w1 = abs(FixedMul(fixedwidth, ca) - FixedMul(fixedheight, sa));
+	fixed_t w2 = abs(FixedMul(-fixedwidth, ca) - FixedMul(fixedheight, sa));
+	fixed_t h1 = abs(FixedMul(fixedwidth, sa) + FixedMul(fixedheight, ca));
+	fixed_t h2 = abs(FixedMul(-fixedwidth, sa) + FixedMul(fixedheight, ca));
+
+	w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2)));
+	w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2)));
+	h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2)));
+	h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2)));
+
+	*newwidth = max(width, max(w1, w2));
+	*newheight = max(height, max(h1, h2));
+}
+
 void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip)
 {
 	patch_t *rotated;
-	UINT16 *rawdst;
+	UINT16 *rawdst, *rawconv;
 	size_t size;
 	pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0;
 
@@ -114,18 +139,20 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle
 	INT32 leftoffset = patch->leftoffset;
 	INT32 newwidth, newheight;
 
-	INT32 dx, dy;
 	fixed_t ca = rollcosang[angle];
 	fixed_t sa = rollsinang[angle];
+	fixed_t xcenter, ycenter;
 	INT32 idx = angle;
+	INT32 x, y;
+	INT32 sx, sy;
+	INT32 dx, dy;
+	INT32 ox, oy;
+	INT32 minx, miny, maxx, maxy;
 
 	// Don't cache angle = 0
 	if (angle < 1 || angle >= ROTANGLES)
 		return;
 
-#define ROTSPRITE_XCENTER (newwidth / 2)
-#define ROTSPRITE_YCENTER (newheight / 2)
-
 	if (flip)
 	{
 		idx += rotsprite->angles;
@@ -137,64 +164,22 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle
 		return;
 
 	// Find the dimensions of the rotated patch.
-	{
-		INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa));
-		INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa));
-		INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca));
-		INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca));
-		w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2)));
-		w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2)));
-		h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2)));
-		h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2)));
-		newwidth = max(width, max(w1, w2));
-		newheight = max(height, max(h1, h2));
-	}
+	RotatedPatch_CalculateDimensions(width, height, ca, sa, &newwidth, &newheight);
+
+	xcenter = (xpivot * FRACUNIT);
+	ycenter = (ypivot * FRACUNIT);
 
-	// check boundaries
+	if (xpivot != width / 2 || ypivot != height / 2)
 	{
-		fixed_t top[2][2];
-		fixed_t bottom[2][2];
-
-		top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS);
-		top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS);
-		top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS);
-		top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS);
-
-		bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS);
-		bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS);
-		bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (xpivot << FRACBITS);
-		bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (ypivot << FRACBITS);
-
-		top[0][0] >>= FRACBITS;
-		top[0][1] >>= FRACBITS;
-		top[1][0] >>= FRACBITS;
-		top[1][1] >>= FRACBITS;
-
-		bottom[0][0] >>= FRACBITS;
-		bottom[0][1] >>= FRACBITS;
-		bottom[1][0] >>= FRACBITS;
-		bottom[1][1] >>= FRACBITS;
-
-#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width)
-#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height)
-#define BOUNDARYADJUST(x) x *= 2
-		// top left/right
-		if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1]))
-			BOUNDARYADJUST(newwidth);
-		// bottom left/right
-		else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1]))
-			BOUNDARYADJUST(newwidth);
-		// top left/right
-		if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1]))
-			BOUNDARYADJUST(newheight);
-		// bottom left/right
-		else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1]))
-			BOUNDARYADJUST(newheight);
-#undef BOUNDARYWCHECK
-#undef BOUNDARYHCHECK
-#undef BOUNDARYADJUST
+		newwidth *= 2;
+		newheight *= 2;
 	}
 
+	minx = newwidth;
+	miny = newheight;
+	maxx = 0;
+	maxy = 0;
+
 	// Draw the rotated sprite to a temporary buffer.
 	size = (newwidth * newheight);
 	if (!size)
@@ -205,37 +190,76 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle
 	{
 		for (dx = 0; dx < newwidth; dx++)
 		{
-			INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS;
-			INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS;
-			INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (xpivot << FRACBITS);
-			INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (ypivot << FRACBITS);
+			x = (dx - (newwidth / 2)) * FRACUNIT;
+			y = (dy - (newheight / 2)) * FRACUNIT;
+			sx = FixedMul(x, ca) + FixedMul(y, sa) + xcenter;
+			sy = -FixedMul(x, sa) + FixedMul(y, ca) + ycenter;
+
 			sx >>= FRACBITS;
 			sy >>= FRACBITS;
+
 			if (sx >= 0 && sy >= 0 && sx < width && sy < height)
 			{
 				void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip);
 				if (input != NULL)
-					rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input));
+				{
+					rawdst[(dy * newwidth) + dx] = (0xFF00 | (*(UINT8 *)input));
+					if (dx < minx)
+						minx = dx;
+					if (dy < miny)
+						miny = dy;
+					if (dx > maxx)
+						maxx = dx;
+					if (dy > maxy)
+						maxy = dy;
+				}
 			}
 		}
 	}
 
-	// make patch
-	rotated = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0);
+	ox = (newwidth / 2) + (leftoffset - xpivot);
+	oy = (newheight / 2) + (patch->topoffset - ypivot);
+	width = (maxx - minx);
+	height = (maxy - miny);
 
-	Z_ChangeTag(rotated, PU_PATCH_ROTATED);
-	Z_SetUser(rotated, (void **)(&rotsprite->patches[idx]));
+	if ((unsigned)(width * height) != size)
+	{
+		UINT16 *src, *dest;
+
+		size = (width * height);
+		rawconv = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
+
+		src = &rawdst[(miny * newwidth) + minx];
+		dest = rawconv;
+		dy = height;
+
+		while (dy--)
+		{
+			M_Memcpy(dest, src, width * sizeof(UINT16));
+			dest += width;
+			src += newwidth;
+		}
+
+		ox -= minx;
+		oy -= miny;
 
-	rotated->leftoffset = (rotated->width / 2) + (leftoffset - xpivot);
-	rotated->topoffset = (rotated->height / 2) + (patch->topoffset - ypivot);
+		Z_Free(rawdst);
+	}
+	else
+	{
+		rawconv = rawdst;
+		width = newwidth;
+		height = newheight;
+	}
 
-	//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
-	rotated->topoffset += FEETADJUST>>FRACBITS;
+	// make patch
+	rotated = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawconv, PICFMT_PATCH, 0, NULL, width, height, 0, 0, 0);
 
-	// free rotated image data
-	Z_Free(rawdst);
+	Z_ChangeTag(rotated, PU_PATCH_ROTATED);
+	Z_SetUser(rotated, (void **)(&rotsprite->patches[idx]));
+	Z_Free(rawconv);
 
-#undef ROTSPRITE_XCENTER
-#undef ROTSPRITE_YCENTER
+	rotated->leftoffset = ox;
+	rotated->topoffset = oy;
 }
 #endif