src/gfx.cpp
branchgamebalance
changeset 9911 0b8b245a2391
parent 9910 0b2aebc8283e
child 9912 1ac8aac92385
--- a/src/gfx.cpp	Wed Jun 13 11:17:30 2007 +0000
+++ b/src/gfx.cpp	Wed Jun 13 11:45:14 2007 +0000
@@ -18,6 +18,7 @@
 #include "fontcache.h"
 #include "genworld.h"
 #include "debug.h"
+#include "zoom.hpp"
 
 #ifdef _DEBUG
 bool _dbg_screen_rect;
@@ -64,12 +65,12 @@
 
 void memcpy_pitch(void *dst, void *src, int w, int h, int srcpitch, int dstpitch)
 {
-	byte *dstp = (byte*)dst;
-	byte *srcp = (byte*)src;
+	Pixel *dstp = (Pixel *)dst;
+	Pixel *srcp = (Pixel *)src;
 
 	assert(h >= 0);
 	for (; h != 0; --h) {
-		memcpy(dstp, srcp, w);
+		memcpy(dstp, srcp, w * sizeof(Pixel));
 		dstp += dstpitch;
 		srcp += srcpitch;
 	}
@@ -110,7 +111,7 @@
 		}
 
 		for (ht = height; ht > 0; --ht) {
-			memcpy(dst, src, width);
+			memcpy(dst, src, width * sizeof(Pixel));
 			src -= p;
 			dst -= p;
 		}
@@ -136,7 +137,7 @@
 		/* the y-displacement may be 0 therefore we have to use memmove,
 		 * because source and destination may overlap */
 		for (ht = height; ht > 0; --ht) {
-			memmove(dst, src, width);
+			memmove(dst, src, width * sizeof(Pixel));
 			src += p;
 			dst += p;
 		}
@@ -153,7 +154,7 @@
 	const int otop = top;
 	const int oleft = left;
 
-	if (dpi->zoom != 0) return;
+	if (dpi->zoom != ZOOM_LVL_NORMAL) return;
 	if (left > right || top > bottom) return;
 	if (right < dpi->left || left >= dpi->left + dpi->width) return;
 	if (bottom < dpi->top || top >= dpi->top + dpi->height) return;
@@ -175,7 +176,7 @@
 	if (!HASBIT(color, PALETTE_MODIFIER_GREYOUT)) {
 		if (!HASBIT(color, USE_COLORTABLE)) {
 			do {
-				memset(dst, color, right);
+				memset(dst, color, right * sizeof(Pixel));
 				dst += dpi->pitch;
 			} while (--bottom);
 		} else {
@@ -737,142 +738,7 @@
 	int pitch;
 };
 
-static void GfxBlitTileZoomIn(BlitterParams *bp)
-{
-	const byte *src_o = bp->sprite;
-	const byte *src;
-	int num, skip;
-	byte done;
-	Pixel *dst;
-	const byte *ctab;
-
-	src_o += ReadLE16Aligned(src_o + bp->start_y * 2);
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					ctab = _color_remap_ptr;
-
-					for (; num >= 4; num -=4) {
-						dst[3] = ctab[src[3]];
-						dst[2] = ctab[src[2]];
-						dst[1] = ctab[src[1]];
-						dst[0] = ctab[src[0]];
-						dst += 4;
-						src += 4;
-					}
-					for (; num != 0; num--) *dst++ = ctab[*src++];
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-			} while (--bp->height != 0);
-			break;
-
-		case BM_TRANSPARENT:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip;
-					} else {
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					ctab = _color_remap_ptr;
-					for (; num != 0; num--) {
-						*dst = ctab[*dst];
-						dst++;
-					}
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-			} while (--bp->height != 0);
-			break;
-
-		default:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-#if defined(_WIN32)
-					if (num & 1) *dst++ = *src++;
-					if (num & 2) { *(uint16*)dst = *(uint16*)src; dst += 2; src += 2; }
-					if (num >>= 2) {
-						do {
-							*(uint32*)dst = *(uint32*)src;
-							dst += 4;
-							src += 4;
-						} while (--num != 0);
-					}
-#else
-					memcpy(dst, src, num);
-#endif
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-			} while (--bp->height != 0);
-			break;
-	}
-}
-
-static void GfxBlitZoomInUncomp(BlitterParams *bp)
+static void GfxBlitZoomUncomp(BlitterParams *bp, ZoomLevel zoom)
 {
 	const byte *src = bp->sprite;
 	Pixel *dst = bp->dst;
@@ -883,62 +749,48 @@
 	assert(height > 0);
 	assert(width > 0);
 
+	height = UnScaleByZoom(height, zoom);
+
 	switch (bp->mode) {
 		case BM_COLOUR_REMAP: {
 			const byte *ctab = _color_remap_ptr;
 
-			do {
-				for (i = 0; i != width; i++) {
-					byte b = ctab[src[i]];
+			for (; height != 0; height--) {
+				for (i = 0; i != UnScaleByZoom(width, zoom); i++) {
+					byte b = ctab[src[ScaleByZoom(i, zoom)]];
 
 					if (b != 0) dst[i] = b;
 				}
-				src += bp->width_org;
+				src += ScaleByZoom(bp->width_org, zoom);
 				dst += bp->pitch;
-			} while (--height != 0);
+			}
 			break;
 		}
 
 		case BM_TRANSPARENT: {
 			const byte *ctab = _color_remap_ptr;
 
-			do {
-				for (i = 0; i != width; i++)
-					if (src[i] != 0) dst[i] = ctab[dst[i]];
-				src += bp->width_org;
+			for (; height != 0; height--) {
+				for (i = 0; i != UnScaleByZoom(width, zoom); i++)
+					if (src[ScaleByZoom(i, zoom)] != 0) dst[i] = ctab[dst[i]];
+				src += ScaleByZoom(bp->width_org, zoom);
 				dst += bp->pitch;
-			} while (--height != 0);
+			}
 			break;
 		}
 
 		default:
-			do {
-				int n = width;
-
-				for (; n >= 4; n -= 4) {
-					if (src[0] != 0) dst[0] = src[0];
-					if (src[1] != 0) dst[1] = src[1];
-					if (src[2] != 0) dst[2] = src[2];
-					if (src[3] != 0) dst[3] = src[3];
-
-					dst += 4;
-					src += 4;
-				}
-
-				for (; n != 0; n--) {
-					if (src[0] != 0) dst[0] = src[0];
-					src++;
-					dst++;
-				}
-
-				src += bp->width_org - width;
-				dst += bp->pitch - width;
-			} while (--height != 0);
+			for (; height != 0; height--) {
+				for (i = 0; i != UnScaleByZoom(width, zoom); i++)
+					if (src[ScaleByZoom(i, zoom)] != 0) dst[i] = src[ScaleByZoom(i, zoom)];
+				src += ScaleByZoom(bp->width_org, zoom);
+				dst += bp->pitch;
+			}
 			break;
 	}
 }
 
-static void GfxBlitTileZoomMedium(BlitterParams *bp)
+static void GfxBlitTileZoom(BlitterParams *bp, ZoomLevel zoom)
 {
 	const byte *src_o = bp->sprite;
 	const byte *src;
@@ -948,484 +800,111 @@
 	const byte *ctab;
 
 	src_o += ReadLE16Aligned(src_o + bp->start_y * 2);
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
 
-					if (skip & 1) {
-						skip++;
-						src++;
-						if (--num == 0) continue;
-					}
+	for (;;) {
+		do {
+			done = src_o[0];
+			num = done & 0x7F;
+			skip = src_o[1];
+			src = src_o + 2;
+			src_o += num + 2;
 
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 1;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
+			dst = bp->dst;
 
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
+			if (zoom >= ZOOM_LVL_OUT_2X && (skip & 1)) {
+				skip += 1;
+				src += 1;
+				num -= 1;
+				if (num <= 0) continue;
+			}
 
+			if (zoom >= ZOOM_LVL_OUT_4X && (skip & 2)) {
+				skip += 2;
+				src += 2;
+				num -= 2;
+				if (num <= 0) continue;
+			}
+
+			if (zoom >= ZOOM_LVL_OUT_8X && (skip & 4)) {
+				skip += 4;
+				src += 4;
+				num -= 4;
+				if (num <= 0) continue;
+			}
+
+			if (zoom >= ZOOM_LVL_OUT_16X && (skip & 8)) {
+				skip += 8;
+				src += 8;
+				num -= 8;
+				if (num <= 0) continue;
+			}
+
+			if ( (skip -= bp->start_x) > 0) {
+				dst += UnScaleByZoom(skip, zoom);
+			} else {
+				src -= skip;
+				num += skip;
+				if (num <= 0) continue;
+				skip = 0;
+			}
+
+			skip = skip + num - bp->width;
+			if (skip > 0) {
+				num -= skip;
+				if (num <= 0) continue;
+			}
+
+			num = UnScaleByZoom(num + ScaleByZoom(1, zoom) - 1, zoom);
+
+			switch (bp->mode) {
+				case BM_COLOUR_REMAP:
 					ctab = _color_remap_ptr;
-					num = (num + 1) >> 1;
 					for (; num != 0; num--) {
 							*dst = ctab[*src];
 							dst++;
-							src += 2;
+							src += ScaleByZoom(1, zoom);
 					}
-				} while (!(done & 0x80));
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-			} while (--bp->height != 0);
-			break;
-
-		case BM_TRANSPARENT:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src_o += num + 2;
+					break;
 
-					dst = bp->dst;
-
-					if (skip & 1) {
-						skip++;
-						if (--num == 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 1;
-					} else {
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
+				case BM_TRANSPARENT:
 					ctab = _color_remap_ptr;
-					num = (num + 1) >> 1;
 					for (; num != 0; num--) {
 							*dst = ctab[*dst];
 							dst++;
 					}
-				} while (!(done & 0x80));
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-			} while (--bp->height != 0);
-			break;
-
-		default:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
+					break;
 
-					if (skip & 1) {
-						skip++;
-						src++;
-						if (--num == 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 1;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					num = (num + 1) >> 1;
-
+				default:
 					for (; num != 0; num--) {
 							*dst = *src;
 							dst++;
-							src += 2;
+							src += ScaleByZoom(1, zoom);
 					}
-
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-			} while (--bp->height != 0);
-			break;
-	}
-}
-
-static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
-{
-	const byte *src = bp->sprite;
-	Pixel *dst = bp->dst;
-	int height = bp->height;
-	int width = bp->width;
-	int i;
-
-	assert(height > 0);
-	assert(width > 0);
-
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP: {
-			const byte *ctab = _color_remap_ptr;
+					break;
+			}
 
-			for (height >>= 1; height != 0; height--) {
-				for (i = 0; i != width >> 1; i++) {
-					byte b = ctab[src[i * 2]];
-
-					if (b != 0) dst[i] = b;
-				}
-				src += bp->width_org * 2;
-				dst += bp->pitch;
-			}
-			break;
-		}
-
-		case BM_TRANSPARENT: {
-			const byte *ctab = _color_remap_ptr;
 
-			for (height >>= 1; height != 0; height--) {
-				for (i = 0; i != width >> 1; i++)
-					if (src[i * 2] != 0) dst[i] = ctab[dst[i]];
-				src += bp->width_org * 2;
-				dst += bp->pitch;
-			}
-			break;
+		} while (!(done & 0x80));
+
+		bp->dst += bp->pitch;
+		if (--bp->height == 0) return;
+
+		for (int i = 0; i < ScaleByZoom(1, zoom) - 1; i++) {
+			do {
+				done = src_o[0];
+				src_o += (done & 0x7F) + 2;
+			} while (!(done & 0x80));
+			if (--bp->height == 0) return;
 		}
-
-		default:
-			for (height >>= 1; height != 0; height--) {
-				for (i = 0; i != width >> 1; i++)
-					if (src[i * 2] != 0) dst[i] = src[i * 2];
-				src += bp->width_org * 2;
-				dst += bp->pitch;
-			}
-			break;
 	}
 }
 
-static void GfxBlitTileZoomOut(BlitterParams *bp)
-{
-	const byte *src_o = bp->sprite;
-	const byte *src;
-	int num, skip;
-	byte done;
-	Pixel *dst;
-	const byte *ctab;
-
-	src_o += ReadLE16Aligned(src_o + bp->start_y * 2);
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP:
-			for (;;) {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if (skip & 1) {
-						skip++;
-						src++;
-						if (--num == 0) continue;
-					}
-
-					if (skip & 2) {
-						skip += 2;
-						src += 2;
-						num -= 2;
-						if (num <= 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 2;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					ctab = _color_remap_ptr;
-					num = (num + 3) >> 2;
-					for (; num != 0; num--) {
-							*dst = ctab[*src];
-							dst++;
-							src += 4;
-					}
-				} while (!(done & 0x80));
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-			}
-			break;
-
-		case BM_TRANSPARENT:
-			for (;;) {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if (skip & 1) {
-						skip++;
-						if (--num == 0) continue;
-					}
-
-					if (skip & 2) {
-						skip += 2;
-						num -= 2;
-						if (num <= 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 2;
-					} else {
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					ctab = _color_remap_ptr;
-					num = (num + 3) >> 2;
-					for (; num != 0; num--) {
-							*dst = ctab[*dst];
-							dst++;
-					}
-
-				} while (!(done & 0x80));
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-			}
-			break;
-
-		default:
-			for (;;) {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if (skip & 1) {
-						skip++;
-						src++;
-						if (--num == 0) continue;
-					}
-
-					if (skip & 2) {
-						skip += 2;
-						src += 2;
-						num -= 2;
-						if (num <= 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 2;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					num = (num + 3) >> 2;
-
-					for (; num != 0; num--) {
-							*dst = *src;
-							dst++;
-							src += 4;
-					}
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-			}
-			break;
-	}
-}
-
-static void GfxBlitZoomOutUncomp(BlitterParams *bp)
-{
-	const byte *src = bp->sprite;
-	Pixel *dst = bp->dst;
-	int height = bp->height;
-	int width = bp->width;
-	int i;
-
-	assert(height > 0);
-	assert(width > 0);
-
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP: {
-			const byte *ctab = _color_remap_ptr;
-
-			for (height >>= 2; height != 0; height--) {
-				for (i = 0; i != width >> 2; i++) {
-					byte b = ctab[src[i * 4]];
-
-					if (b != 0) dst[i] = b;
-				}
-				src += bp->width_org * 4;
-				dst += bp->pitch;
-			}
-			break;
-		}
-
-		case BM_TRANSPARENT: {
-			const byte *ctab = _color_remap_ptr;
-
-			for (height >>= 2; height != 0; height--) {
-				for (i = 0; i != width >> 2; i++)
-					if (src[i * 4] != 0) dst[i] = ctab[dst[i]];
-				src += bp->width_org * 4;
-				dst += bp->pitch;
-			}
-			break;
-		}
-
-		default:
-			for (height >>= 2; height != 0; height--) {
-				for (i = 0; i != width >> 2; i++)
-					if (src[i * 4] != 0) dst[i] = src[i * 4];
-				src += bp->width_org * 4;
-				dst += bp->pitch;
-			}
-			break;
-	}
-}
-
-
 static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode)
 {
 	const DrawPixelInfo *dpi = _cur_dpi;
 	int start_x, start_y;
 	BlitterParams bp;
-	int zoom_mask = ~((1 << dpi->zoom) - 1);
+	int zoom_mask = ~(ScaleByZoom(1, dpi->zoom) - 1);
 
 	/* decode sprite header */
 	x += sprite->x_offs;
@@ -1444,7 +923,7 @@
 		/* tile blit */
 		start_y = 0;
 
-		if (dpi->zoom > 0) {
+		if (dpi->zoom > ZOOM_LVL_NORMAL) {
 			start_y += bp.height & ~zoom_mask;
 			bp.height &= zoom_mask;
 			if (bp.height == 0) return;
@@ -1457,7 +936,7 @@
 			start_y -= y;
 			y = 0;
 		} else {
-			bp.dst += bp.pitch * (y >> dpi->zoom);
+			bp.dst += bp.pitch * UnScaleByZoom(y, dpi->zoom);
 		}
 		bp.start_y = start_y;
 
@@ -1475,19 +954,14 @@
 			x = 0;
 		}
 		bp.start_x = start_x;
-		bp.dst += x >> dpi->zoom;
+		bp.dst += UnScaleByZoom(x, dpi->zoom);
 
 		if ( (x = x + bp.width - dpi->width) > 0) {
 			bp.width -= x;
 			if (bp.width <= 0) return;
 		}
 
-		switch (dpi->zoom) {
-			default: NOT_REACHED();
-			case 0: GfxBlitTileZoomIn(&bp);     break;
-			case 1: GfxBlitTileZoomMedium(&bp); break;
-			case 2: GfxBlitTileZoomOut(&bp);    break;
-		}
+		GfxBlitTileZoom(&bp, dpi->zoom);
 	} else {
 		bp.sprite += bp.width * (bp.height & ~zoom_mask);
 		bp.height &= zoom_mask;
@@ -1501,7 +975,7 @@
 			bp.sprite -= bp.width * y;
 			y = 0;
 		} else {
-			bp.dst += bp.pitch * (y >> dpi->zoom);
+			bp.dst += bp.pitch * UnScaleByZoom(y, dpi->zoom);
 		}
 
 		if (bp.height > dpi->height - y) {
@@ -1517,19 +991,14 @@
 			bp.sprite -= x;
 			x = 0;
 		}
-		bp.dst += x >> dpi->zoom;
+		bp.dst += UnScaleByZoom(x, dpi->zoom);
 
 		if (bp.width > dpi->width - x) {
 			bp.width = dpi->width - x;
 			if (bp.width <= 0) return;
 		}
 
-		switch (dpi->zoom) {
-			default: NOT_REACHED();
-			case 0: GfxBlitZoomInUncomp(&bp);     break;
-			case 1: GfxBlitZoomMediumUncomp(&bp); break;
-			case 2: GfxBlitZoomOutUncomp(&bp);    break;
-		}
+		GfxBlitZoomUncomp(&bp, dpi->zoom);
 	}
 }
 
@@ -1946,7 +1415,7 @@
 {
 	const DrawPixelInfo *o = _cur_dpi;
 
-	n->zoom = 0;
+	n->zoom = ZOOM_LVL_NORMAL;
 
 	assert(width > 0);
 	assert(height > 0);