diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c
index 9187c52a797d41ef1139b9700a042f668a2ba811..7f5615ddff584b47108cf31be8b5896955efabc7 100644
--- a/src/conio/bitmap_con.c
+++ b/src/conio/bitmap_con.c
@@ -11,6 +11,7 @@
 #include "genwrap.h"
 #include "dirwrap.h"
 #include "xpbeep.h"
+#include "scale.h"
 
 #if (defined CIOLIB_IMPORTS)
  #undef CIOLIB_IMPORTS
@@ -1664,6 +1665,7 @@ int bitmap_drv_init(void (*drawrect_cb) (struct rectlist *data)
 	pthread_mutex_init(&screenb.screenlock, NULL);
 	pthread_mutex_init(&free_rect_lock, NULL);
 	pthread_mutex_lock(&vstatlock);
+	init_r2y();
 	vstat.vmem=NULL;
 	vstat.flags = VIDMODES_FLAG_PALETTE_VMEM;
 	pthread_mutex_lock(&screena.screenlock);
diff --git a/src/conio/scale.c b/src/conio/scale.c
index ff9fc37c5870bc989f460aae82b49543c867fc4a..880822e38cbbdb387631ce314054354c2e03165b 100644
--- a/src/conio/scale.c
+++ b/src/conio/scale.c
@@ -1,34 +1,113 @@
 #include "scale.h"
 #include "xbr.h"
 
+uint32_t r2y[1<<24];
+uint32_t y2r[1<<24];
+static int r2y_inited;
+
 static void pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height);
 static void pointy_scale5(uint32_t* src, uint32_t* dest, int width, int height);
+static void interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newheight);
+static void multiply_scale(uint32_t* src, uint32_t* dst, int width, int height, int xmult, int ymult);
+
+static struct graphics_buffer *free_list;
+
+#define CLAMP(x) do { \
+	if (x < 0) \
+		x = 0; \
+	else if (x > 255) \
+		x = 255; \
+} while(0)
+
+void
+init_r2y(void)
+{
+	int r, g, b;
+	int y, u, v;
+	const double luma = 255.0 / 219;
+	const double col  = 255.0 / 224;
+
+	if (r2y_inited)
+		return;
+	for (r = 0; r < 256; r++) {
+		for (g = 0; g < 256; g++) {
+			for (b = 0; b < 256; b++) {
+				y =  16 + ( 65.738 * r + 129.057 * g +  25.064 * b + 128) / 256;
+				CLAMP(y);
+				u = 128 + (-37.945 * r -  74.494 * g + 112.439 * b + 128) / 256;
+				CLAMP(u);
+				v = 128 + (112.439 * r -  94.154 * g -  18.285 * b + 128) / 256;
+				CLAMP(v);
+
+				r2y[(r<<16) | (g<<8) | b] = (y<<16)|(u<<8)|v;
+			}
+		}
+	}
+	for (y = 0; y < 256; y++) {
+		for (u = 0; u < 256; u++) {
+			for (v = 0; v < 256; v++) {
+				const int c = y - 16;
+				const int d = u - 128;
+				const int e = v - 128;
+				r = luma * c                                     + col * 1.402 * e;
+				CLAMP(r);
+				g = luma * c - col * 1.772 * (0.114 / 0.587) * d - col * 1.402 * (0.299 / 0.587) * e;
+				CLAMP(g);
+				b = luma * c + col * 1.772 * d;
+				CLAMP(b);
 
-uint32_t*
-do_scale(struct rectlist* rect, uint32_t **target, size_t *targetsz, int* xscale, int* yscale, int* w, int* h)
+				y2r[(y<<16) | (u<<8) | v] = (r<<16)|(g<<8)|b;
+			}
+		}
+	}
+	r2y_inited = 1;
+}
+
+struct graphics_buffer *
+get_buffer(void)
 {
+	struct graphics_buffer* ret = NULL;
+
+	if (free_list) {
+		ret = free_list;
+		free_list = free_list->next;
+		ret->next = NULL;
+		return ret;
+	}
+
+	ret = calloc(1, sizeof(struct graphics_buffer));
+	return ret;
+}
+
+void
+release_buffer(struct graphics_buffer *buf)
+{
+	buf->next = free_list;
+	free_list = buf;
+}
+
+struct graphics_buffer *
+do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
+{
+	struct graphics_buffer* ret1 = get_buffer();
+	struct graphics_buffer* ret2 = get_buffer();
 	int pointy5 = 0;
 	int pointy3 = 0;
 	int xbr2 = 0;
 	int xbr4 = 0;
+	int ymult = 1;
+	int xmult = 1;
 	int newscale = 1;
-	int total_scaling = 1;
-	static uint32_t *tmptarget = NULL;
-	static size_t tmptargetsz = 0;
-	uint32_t *ctarget;
-	uint32_t *csrc = rect->data;
+	int total_xscaling = 1;
+	int total_yscaling = 1;
+	struct graphics_buffer *ctarget;
+	struct graphics_buffer *csrc;
 	uint32_t* nt;
-	int swidth = rect->rect.width;
-	int sheight = rect->rect.height;
-
-	*w = rect->rect.width;
-	*h = rect->rect.height;
-	// As a first pass, only do equal integer scaling
-	if (*xscale != *yscale)
-		return rect->data;
+	int fheight;
+
 	switch (*xscale) {
 		case 1:
-			return rect->data;
+			break;
 		case 2:
 			xbr2 = 1;
 			break;
@@ -45,105 +124,155 @@ do_scale(struct rectlist* rect, uint32_t **target, size_t *targetsz, int* xscale
 			pointy3 = 1;
 			xbr2 = 1;
 			break;
+		case 7:	// TODO: Do we want a pointy7 and pointy11?
+			xmult = 7;
+			ymult = 7;
+			break;
 		default:
-			total_scaling = *xscale;
+			total_xscaling = *xscale;
 			*xscale = 1;
-			while (total_scaling > 1 && ((total_scaling % 5) == 0)) {
+			total_yscaling = *yscale;
+			*yscale = 1;
+			while (total_xscaling > 1 && ((total_xscaling % 5) == 0) && ((total_yscaling % 5) == 0)) {
 				pointy5++;
-				total_scaling /= 5;
+				total_xscaling /= 5;
 				*xscale *= 5;
+				total_yscaling /= 5;
+				*yscale *= 5;
 			}
-			while (total_scaling > 1 && ((total_scaling % 3) == 0)) {
+			while (total_xscaling > 1 && ((total_xscaling % 3) == 0) && ((total_yscaling % 3) == 0)) {
 				pointy3++;
-				total_scaling /= 3;
+				total_xscaling /= 3;
 				*xscale *= 3;
+				total_yscaling /= 3;
+				*yscale *= 3;
 			}
-			while (total_scaling > 1 && ((total_scaling % 4) == 0)) {
+			while (total_xscaling > 1 && ((total_xscaling % 4) == 0) && ((total_yscaling % 4) == 0)) {
 				xbr4++;
-				total_scaling /= 4;
+				total_xscaling /= 4;
 				*xscale *= 4;
+				total_yscaling /= 4;
+				*yscale *= 4;
 			}
-			while (total_scaling > 1 && ((total_scaling % 2) == 0)) {
+			while (total_xscaling > 1 && ((total_xscaling % 2) == 0) && ((total_yscaling % 2) == 0)) {
 				xbr2++;
-				total_scaling /= 2;
+				total_xscaling /= 2;
 				*xscale *= 2;
+				total_yscaling /= 2;
+				*yscale *= 2;
 			}
-			if (*xscale == 1)
-				return rect->data;
 			break;
 	}
 
+	if (*xscale != *yscale) {
+		if (*yscale == *xscale * 2)
+			ymult *= 2;
+		else
+			return NULL;
+	}
+
+	// Calculate the scaled height from ratio...
+	fheight = lround((double)(rect->rect.height * (*yscale)) / ratio);
+
 	// Now make sure target is big enough...
-	size_t needsz = rect->rect.width * rect->rect.height * (*xscale) * (*xscale) * sizeof(uint32_t);
-	if (needsz > *targetsz) {
-		nt = realloc(*target, needsz);
+	size_t needsz = rect->rect.width * (*xscale) * fheight * sizeof(uint32_t);
+	if (needsz > ret1->sz) {
+		nt = realloc(ret1->data, needsz);
 		if (nt == NULL)
-			return rect->data;
-		*target = nt;
-		*targetsz = needsz;
+			return NULL;
+		ret1->data = nt;
+		ret1->sz = needsz;
 	}
-	ctarget = *target;
-
-	// And if we need an extra target, do the same there...
-	if (pointy3 + pointy5 + xbr4 + xbr2 > 1) {
-		if (needsz > tmptargetsz) {
-			nt = realloc(tmptarget, needsz);
-			if (nt == NULL)
-				return rect->data;
-			tmptarget = nt;
-			tmptargetsz = needsz;
-		}
+
+	if (needsz > ret2->sz) {
+		nt = realloc(ret2->data, needsz);
+		if (nt == NULL)
+			return NULL;
+		ret2->data = nt;
+		ret2->sz = needsz;
 	}
 
-	// And finally, scale...
+	// Copy rect into first buffer
+	// TODO: Unify bitmap rects and scaling buffers so this can just whomp on over.
+	csrc = ret1;
+	ctarget = ret2;
+	memcpy(csrc->data, rect->data, rect->rect.width * rect->rect.height * sizeof(rect->data[0]));
+	csrc->w = rect->rect.width;
+	csrc->h = rect->rect.height;
+
+	// And scale...
+	if (ymult != 1 || xmult != 1) {
+		multiply_scale(csrc->data, ctarget->data, csrc->w, csrc->h, xmult, ymult);
+		ctarget->w = csrc->w * xmult;
+		ctarget->h = csrc->h * ymult;
+		ymult = 1;
+		xmult = 1;
+		csrc = ctarget;
+		if (ctarget == ret1)
+			ctarget = ret2;
+		else
+			ctarget = ret1;
+	}
 	while (xbr4 > 0) {
-		xbr_filter(csrc, ctarget, swidth, sheight, 4);
+		xbr_filter(csrc->data, ctarget->data, csrc->w, csrc->h, 4);
 		xbr4--;
-		swidth *= 4;
-		sheight *= 4;
+		ctarget->w = csrc->w * 4;
+		ctarget->h = csrc->h * 4;
 		csrc = ctarget;
-		if (ctarget == tmptarget)
-			ctarget = *target;
+		if (ctarget == ret1)
+			ctarget = ret2;
 		else
-			ctarget = tmptarget;
+			ctarget = ret1;
 	}
 	while (xbr2 > 0) {
-		xbr_filter(csrc, ctarget, swidth, sheight, 2);
+		xbr_filter(csrc->data, ctarget->data, csrc->w, csrc->h, 2);
 		xbr2--;
-		swidth *= 2;
-		sheight *= 2;
+		ctarget->w = csrc->w * 2;
+		ctarget->h = csrc->h * 2;
 		csrc = ctarget;
-		if (ctarget == tmptarget)
-			ctarget = *target;
+		if (ctarget == ret1)
+			ctarget = ret2;
 		else
-			ctarget = tmptarget;
+			ctarget = ret1;
 	}
 	while (pointy5 > 0) {
-		pointy_scale5(csrc, ctarget, swidth, sheight);
+		pointy_scale5(csrc->data, ctarget->data, csrc->w, csrc->h);
 		pointy5--;
-		swidth *= 5;
-		sheight *= 5;
+		ctarget->w = csrc->w * 5;
+		ctarget->h = csrc->h * 5;
 		csrc = ctarget;
-		if (ctarget == tmptarget)
-			ctarget = *target;
+		if (ctarget == ret1)
+			ctarget = ret2;
 		else
-			ctarget = tmptarget;
+			ctarget = ret1;
 	}
 	while (pointy3 > 0) {
-		pointy_scale3(csrc, ctarget, swidth, sheight);
+		pointy_scale3(csrc->data, ctarget->data, csrc->w, csrc->h);
 		pointy3--;
-		swidth *= 3;
-		sheight *= 3;
+		ctarget->w = csrc->w * 3;
+		ctarget->h = csrc->h * 3;
 		csrc = ctarget;
-		if (ctarget == tmptarget)
-			ctarget = *target;
+		if (ctarget == ret1)
+			ctarget = ret2;
 		else
-			ctarget = tmptarget;
+			ctarget = ret1;
 	}
-	*w *= *xscale;
-	*h *= *xscale;
+
+	// And finally, interpolate if needed
+	if (ratio != 1) {
+		interpolate_height(csrc->data, ctarget->data, csrc->w, csrc->h, fheight);
+		ctarget->h = fheight;
+		ctarget->w = csrc->w;
+		csrc = ctarget;
+		if (ctarget == ret1)
+			ctarget = ret2;
+		else
+			ctarget = ret1;
+	}
+
 	*xscale = newscale;
 	*yscale = newscale;
+	release_buffer(ctarget);
 	return csrc;
 }
 
@@ -339,3 +468,93 @@ pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height)
 			prevline = -width;
 	}
 }
+
+static __attribute__((always_inline))
+uint32_t blend(const uint32_t c1, const uint32_t c2, const double weight)
+{
+	uint8_t yuv1[4];
+	uint8_t yuv2[4];
+	int y, u, v;
+	const double iw = 1.0 - weight;
+
+	*(uint32_t *)yuv1 = r2y[c1];
+	*(uint32_t *)yuv2 = r2y[c2];
+#ifdef __BIG_ENDIAN__
+	y = yuv1[1] * iw + yuv2[1] * weight;
+	u = yuv1[2] * iw + yuv2[2] * weight;
+	v = yuv1[3] * iw + yuv2[3] * weight;
+#else
+	y = yuv1[2] * iw + yuv2[2] * weight;
+	u = yuv1[1] * iw + yuv2[1] * weight;
+	v = yuv1[0] * iw + yuv2[0] * weight;
+#endif
+	CLAMP(y);
+	CLAMP(u);
+	CLAMP(v);
+
+	return y2r[(y<<16)|(u<<8)|v];
+}
+
+/*
+ * This does non-integer *height* scaling.  It does not scale in the other
+ * direction.  This does the interpolation using Y'UV to prevent dimming of
+ * pixels.
+ */
+static void
+interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newheight)
+{
+	int x, y;
+	const double mult = (double)height / newheight;
+
+	for (y = 0; y < newheight; y++) {
+		for (x = 0; x < width; x++) {
+			// First, calculate which two pixels this is between.
+			const double ypos = mult * y;
+			const int yposi = ypos;
+			if (y == ypos) {
+				// Exact match!
+				*dst = src[width * yposi + x];
+			}
+			else {
+				const double weight = ypos - yposi;
+				// Now pick the two pixels
+				const uint32_t pix1 = src[yposi * width + x] & 0xffffff;
+				uint32_t pix2;
+				if (yposi < height - 1)
+					pix2 = src[(yposi + 1) * width + x] & 0xffffff;
+				else
+					pix2 = src[yposi * width + x] & 0xffffff;
+				if (pix1 == pix2)
+					*dst = pix1;
+				else {
+					*dst = blend(pix1, pix2, weight);
+				}
+			}
+			dst++;
+		}
+	}
+}
+
+static void
+multiply_scale(uint32_t* src, uint32_t* dst, int width, int height, int xmult, int ymult)
+{
+	int nheight = height * ymult;
+	int nwidth = width * xmult;
+	int x, y;
+	int mx, my;
+	uint32_t* slstart;
+
+	for (y = 0; y < height; y++) {
+		slstart = src;
+		for (my = 0; my < ymult; my++) {
+			src = slstart;
+			for (x = 0; x < width; x++) {
+				for (mx = 0; mx < xmult; mx++) {
+					*dst = *src;
+					dst++;
+				}
+				src++;
+			}
+		}
+	}
+}
diff --git a/src/conio/scale.h b/src/conio/scale.h
index b867d034b669190cb182f1eecbe6ff0de3252b71..2d30202adf5e1653181baee3ea1b7f1bffe1b5e6 100644
--- a/src/conio/scale.h
+++ b/src/conio/scale.h
@@ -1,3 +1,18 @@
 #include "bitmap_con.h"
 
-uint32_t* do_scale(struct rectlist* rect, uint32_t **target, size_t *targetsz, int* xscale, int* yscale, int* w, int* h);
+struct graphics_buffer {
+	uint32_t* data;
+	size_t    sz;
+	size_t    w;
+	size_t    h;
+	struct graphics_buffer *next;
+};
+
+extern uint32_t r2y[1<<24];
+extern uint32_t y2r[1<<24];
+
+struct graphics_buffer * get_buffer(void);
+void release_buffer(struct graphics_buffer *);
+void init_r2y(void);
+
+struct graphics_buffer * do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio);
diff --git a/src/conio/x_events.c b/src/conio/x_events.c
index e3014eedf551fe6ed7e1ff041fb1373fb3bfe17c..bd21f53cc81d8edec8e280a48d2ba208b4c29327 100644
--- a/src/conio/x_events.c
+++ b/src/conio/x_events.c
@@ -85,7 +85,7 @@ static unsigned long base_pixel;
 static int r_shift;
 static int g_shift;
 static int b_shift;
-static struct rectlist *last = NULL;
+static struct graphics_buffer *last = NULL;
 
 /* Array of Graphics Contexts */
 static GC gc;
@@ -208,9 +208,13 @@ static struct {
 
 static void resize_xim(void)
 {
+	int width = bitmap_width * x_cvstat.scaling;
+	double ratio = (double)x_cvstat.scale_numerator / x_cvstat.scale_denominator;
+	int height = lround((double)(bitmap_height * x_cvstat.scaling * x_cvstat.vmultiplier) / ratio);
+
 	if (xim) {
-		if (bitmap_width*x_cvstat.scaling == xim->width
-		    && bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier == xim->height) {
+		if (width == xim->width
+		    && height == xim->height) {
 			return;
 		}
 #ifdef XDestroyImage
@@ -220,11 +224,11 @@ static void resize_xim(void)
 #endif
 	}
 	if (last) {
-		bitmap_drv_free_rect(last);
+		release_buffer(last);
 		last = NULL;
 	}
-    xim=x11.XCreateImage(dpy,&visual,depth,ZPixmap,0,NULL,bitmap_width*x_cvstat.scaling,bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier,32,0);
-    xim->data=(char *)malloc(xim->bytes_per_line*xim->height);
+	xim = x11.XCreateImage(dpy, &visual, depth, ZPixmap, 0, NULL, width, height, 32, 0);
+	xim->data=(char *)calloc(1, xim->bytes_per_line*xim->height);
 }
 
 /* Swiped from FreeBSD libc */
@@ -346,6 +350,7 @@ static int init_window()
 static void map_window()
 {
     XSizeHints *sh;
+	int scaled_height;
 
     sh = x11.XAllocSizeHints();
     if (sh == NULL) {
@@ -357,7 +362,9 @@ static void map_window()
 	sh->base_height = bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier;
 
     sh->min_width = sh->width_inc = sh->min_aspect.x = sh->max_aspect.x = bitmap_width;
-    sh->min_height = sh->height_inc = sh->min_aspect.y = sh->max_aspect.y = bitmap_height;
+
+	scaled_height = ceil((double)bitmap_height*x_cvstat.vmultiplier / ((double)x_cvstat.scale_numerator / x_cvstat.scale_denominator));
+    sh->min_height = sh->height_inc = sh->min_aspect.y = sh->max_aspect.y = scaled_height;
     sh->flags = USSize | PMinSize | PSize | PResizeInc | PAspect;
 
     x11.XSetWMNormalHints(dpy, win, sh);
@@ -371,10 +378,11 @@ static void map_window()
 /* Resize the window. This function is called after a mode change. */
 static void resize_window()
 {
-    x11.XResizeWindow(dpy, win, bitmap_width*x_cvstat.scaling, bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier);
-    resize_xim();
+	int scaled_height = ceil((double)bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier / ((double)x_cvstat.scale_numerator / x_cvstat.scale_denominator));
+	x11.XResizeWindow(dpy, win, bitmap_width*x_cvstat.scaling, scaled_height);
+	resize_xim();
 
-    return;
+	return;
 }
 
 static void init_mode_internal(int mode)
@@ -386,7 +394,7 @@ static void init_mode_internal(int mode)
 	pthread_mutex_lock(&blinker_lock);
 	pthread_mutex_lock(&vstatlock);
 	if (last) {
-		bitmap_drv_free_rect(last);
+		release_buffer(last);
 		last = NULL;
 	}
 	bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height);
@@ -451,7 +459,6 @@ static void local_draw_rect(struct rectlist *rect)
 {
 	int x,y,xscale,yscale,xoff=0,yoff=0;
 	int xscaling, yscaling;
-	int rxscaling, ryscaling;
 	unsigned int r, g, b;
 	unsigned long pixel;
 	int cleft;
@@ -459,14 +466,9 @@ static void local_draw_rect(struct rectlist *rect)
 	int ctop;
 	int cbottom = -1;
 	int idx;
-	int ridx;
-	int ridx_part;
 	uint32_t last_pixel = 0x55555555;
-	static uint32_t* target = NULL;
-	size_t targetsz = 0;
-	uint32_t* source;
-	int width, height;
-	int lheight, lines;
+	struct graphics_buffer *source;
+	int lines;
 
 	if (bitmap_width != rect->rect.width || bitmap_height != rect->rect.height)
 		return;
@@ -481,23 +483,32 @@ static void local_draw_rect(struct rectlist *rect)
 	// Scale...
 	xscaling = x_cvstat.scaling;
 	yscaling = x_cvstat.scaling*x_cvstat.vmultiplier;
-	source = do_scale(rect, &target, &targetsz, &xscaling, &yscaling, &width, &height);
-	rxscaling = width / rect->rect.width;
-	ryscaling = height / rect->rect.height;
-	cleft = width;
-	ctop = height;
+	source = do_scale(rect, &xscaling, &yscaling, (double)x_cvstat.scale_numerator / x_cvstat.scale_denominator);
+	bitmap_drv_free_rect(rect);
+	if (source == NULL)
+		return;
+	cleft = source->w;
+	ctop = source->h;
 	lines = 0;
-	lheight = x_cvstat.charheight * ryscaling;
+
+	xoff = (x11_window_width - source->w) / 2;
+	if (xoff < 0)
+		xoff = 0;
+	yoff = (x11_window_height - source->h) / 2;
+	if (yoff < 0)
+		yoff = 0;
+
+	if (last && (last->w != source->w || last->h != source->h)) {
+		release_buffer(last);
+		last = NULL;
+	}
 
 	/* TODO: Translate into local colour depth */
-	for(y=0;y<height;y++) {
-		idx = y * width;
-		ridx = y / ryscaling * rect->rect.width;
-		ridx_part = 0;
-		for(x=0; x<width; x++) {
+	idx = 0;
+	for (y = 0; y < source->h; y++) {
+		for (x = 0; x < source->w; x++) {
 			if (last) {
-				// TODO: Based on source pixel, not target pixel. :(
-				if (last->data[ridx] != rect->data[ridx]) {
+				if (last->data[idx] != source->data[idx]) {
 					if (x < cleft)
 						cleft = x;
 					if (x > cright)
@@ -508,29 +519,15 @@ static void local_draw_rect(struct rectlist *rect)
 						cbottom = y;
 				}
 				else {
-					if (source == rect->data) {
-						idx += (rxscaling);
-						x += (rxscaling - 1);
-						ridx++;
-						continue;
-					}
-					else {
-						if (cright < x - rxscaling * 2
-						    && (x >= width - (rxscaling * 3)
-						    || last->data[ridx + 1] == rect->data[ridx + 1])) {
-							idx += (rxscaling);
-							x += (rxscaling - 1);
-							ridx++;
-							continue;
-						}
-					}
+					idx++;
+					continue;
 				}
 			}
-			if (last_pixel != source[idx]) {
-				last_pixel = source[idx];
-				r = source[idx] >> 16 & 0xff;
-				g = source[idx] >> 8 & 0xff;
-				b = source[idx] & 0xff;
+			if (last_pixel != source->data[idx]) {
+				last_pixel = source->data[idx];
+				r = source->data[idx] >> 16 & 0xff;
+				g = source->data[idx] >> 8 & 0xff;
+				b = source->data[idx] & 0xff;
 				r = (r<<8)|r;
 				g = (g<<8)|g;
 				b = (b<<8)|b;
@@ -560,54 +557,36 @@ static void local_draw_rect(struct rectlist *rect)
 				}
 			}
 			idx++;
-			ridx_part++;
-			if (ridx_part >= rxscaling) {
-				ridx_part = 0;
-				ridx++;
-			}
 		}
 		lines++;
 		/* This line was changed */
-		if (last && ((lines == lheight) || (y == height - 1)) && cright >= 0) {
-#ifdef USE_XBRZ
-			if (source != rect->data) {
-				cleft -= 2 * rxscaling;
-				if (cleft < 0)
-					cleft = 0;
-				cright += 2 * rxscaling;
-				if (cright >= width)
-					cright = width - 1;
-			}
-#endif
+		// TODO: Previously this did one update per display line...
+		if (last && (cbottom != y || y == source->h - 1) && cright >= 0) {
 			lines = 0;
 			x11.XPutImage(dpy, win, gc, xim, cleft * xscaling, ctop * yscaling
 			    , cleft * xscaling + xoff, ctop * yscaling + yoff
 			    , (cright - cleft + 1) * xscaling, (cbottom - ctop + 1) * yscaling);
-			cleft = width;
+			cleft = source->w;
 			cright = cbottom = -100;
-			ctop = height;
+			ctop = source->h;
 		}
 	}
 
 	if (last == NULL)
-		x11.XPutImage(dpy, win, gc, xim, rect->rect.x*xscaling, rect->rect.y*yscaling, rect->rect.x*xscaling + xoff, rect->rect.y*yscaling + yoff, width * xscaling, height * yscaling);
+		x11.XPutImage(dpy, win, gc, xim, rect->rect.x*xscaling, rect->rect.y*yscaling, rect->rect.x*xscaling + xoff, rect->rect.y*yscaling + yoff, source->w * xscaling, source->h * yscaling);
 	else
-		bitmap_drv_free_rect(last);
-	last = rect;
+		release_buffer(last);
+	last = source;
 }
 
 static void handle_resize_event(int width, int height)
 {
 	int newFSH=1;
 	int newFSW=1;
-
-	// No change
-	if((width == x_cvstat.charwidth * x_cvstat.cols * x_cvstat.scaling)
-			&& (height == x_cvstat.charheight * x_cvstat.rows * x_cvstat.scaling*x_cvstat.vmultiplier))
-		return;
+	double ratio = (double)x_cvstat.scale_numerator / x_cvstat.scale_denominator;
 
 	newFSH=width/bitmap_width;
-	newFSW=height/bitmap_height;
+	newFSW=floor((double)height / bitmap_height * ratio);
 	if(newFSW<1)
 		newFSW=1;
 	if(newFSH<1)
@@ -627,9 +606,11 @@ static void handle_resize_event(int width, int height)
 	 */
 	if (newFSH != newFSW)
 		resize_window();
+#if 0	// TODO: Is this even worth looking at?
 	else if((width % (x_cvstat.charwidth * x_cvstat.cols) != 0)
 			|| (height % (x_cvstat.charheight * x_cvstat.rows) != 0))
 		resize_window();
+#endif
 	else
 		resize_xim();
 	bitmap_drv_request_pixels();
@@ -680,7 +661,7 @@ static void expose_rect(int x, int y, int width, int height)
 
 	/* Since we're exposing, we *have* to redraw */
 	if (last) {
-		bitmap_drv_free_rect(last);
+		release_buffer(last);
 		last = NULL;
 		bitmap_drv_request_some_pixels(sx, sy, ex-sx+1, ey-sy+1);
 	}
diff --git a/src/conio/xbr.c b/src/conio/xbr.c
index 64211daea20f668454644700cf2602f1e5ff1fde..60331c2b7dad33b15435b796c9bacea27247319a 100644
--- a/src/conio/xbr.c
+++ b/src/conio/xbr.c
@@ -30,6 +30,7 @@
 
 #include <inttypes.h>
 #include <stdlib.h>
+#include "scale.h"
 
 #define LB_MASK       0x00FEFEFE
 #define RED_BLUE_MASK 0x00FF00FF
@@ -39,8 +40,6 @@
 #undef PI
 #endif
 
-uint32_t r2y[1<<24];
-
 static uint32_t pixel_diff(uint32_t x, uint32_t y)
 {
 #define YMASK 0xff0000
@@ -190,6 +189,13 @@ static uint32_t pixel_diff(uint32_t x, uint32_t y)
     }                                                                                               \
 } while (0)
 
+#define CLAMP(x) do { \
+	if (x < 0) \
+		x = 0; \
+	else if (x > 255) \
+		x = 255; \
+} while(0)
+
 void
 xbr_filter(uint32_t *data, uint32_t *out, int width, int height, int n)
 {