diff --git a/src/build/Common.gmake b/src/build/Common.gmake
index 0ab0f6fa928d66a6b320eb2aee1e411604ba8603..3647ce4263e4704bf5e1e4182e0263eaec153f1d 100644
--- a/src/build/Common.gmake
+++ b/src/build/Common.gmake
@@ -437,9 +437,9 @@ ifdef DEBUG
  CFLAGS	+=	-D_DEBUG
  CFLAGS +=	-Wall -Wno-char-subscripts
 else # RELEASE
- # -finline functions breaks the baja build badly.
- # This also means that -O3 won't work either.
- CFLAGS	:= -O2 -fomit-frame-pointer -ffast-math -funroll-loops $(CFLAGS)
+ # -finline-functions (used to) break the baja build badly.
+ # This also meant that -O3 wouldn't work either.
+ CFLAGS	:= -O3 -fomit-frame-pointer -ffast-math -funroll-loops $(CFLAGS)
 endif
 
 -include targets.mk
diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c
index 3809287461545b368f779480694d5904fae59099..35b523ef2367c9a0d1e4e130402052b344d6b3a7 100644
--- a/src/conio/bitmap_con.c
+++ b/src/conio/bitmap_con.c
@@ -69,6 +69,7 @@ struct bitmap_screen {
 	int		screenheight;
 	pthread_mutex_t	screenlock;
 	int		update_pixels;
+	struct rectlist *rect;
 };
 
 struct bitmap_callbacks {
@@ -114,10 +115,11 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos);
 static void cb_flush(void);
 static int check_redraw(void);
 static void blinker_thread(void *data);
-static __inline struct bitmap_screen *current_screen(void);
+static __inline void both_screens(struct bitmap_screen** current, struct bitmap_screen** noncurrent);
 static int update_from_vmem(int force);
 static int bitmap_vmem_puttext_locked(int sx, int sy, int ex, int ey, struct vmem_cell *fill);
 static uint32_t color_value(uint32_t col);
+void bitmap_drv_free_rect(struct rectlist *rect);
 
 /**************************************************************/
 /* These functions get called from the driver and ciolib only */
@@ -286,7 +288,8 @@ static int bitmap_vmem_puttext_locked(int sx, int sy, int ex, int ey, struct vme
 	return(1);
 }
 
-static void set_vmem_cell(struct vstat_vmem *vmem_ptr, size_t pos, uint16_t cell, uint32_t fg, uint32_t bg)
+static void
+set_vmem_cell(struct vstat_vmem *vmem_ptr, size_t pos, uint16_t cell, uint32_t fg, uint32_t bg)
 {
 	int		altfont;
 	int		font;
@@ -436,16 +439,15 @@ static struct rectlist *alloc_full_rect(struct bitmap_screen *screen)
 static uint32_t color_value(uint32_t col)
 {
 	if (col & 0x80000000)
-		return col;
+		return col & 0xffffff;
 	if ((col & 0xffffff) < sizeof(palette) / sizeof(palette[0]))
-		return (col & 0xff000000) | palette[col & 0xffffff];
+		return palette[col & 0xffffff] & 0xffffff;
 	fprintf(stderr, "Invalid colour value: %08x\n", col);
-	return 0xff000000;
+	return 0;
 }
 
 static struct rectlist *get_full_rectangle_locked(struct bitmap_screen *screen)
 {
-	size_t i;
 	struct rectlist *rect;
 
 	// TODO: Some sort of caching here would make things faster...?
@@ -453,8 +455,7 @@ static struct rectlist *get_full_rectangle_locked(struct bitmap_screen *screen)
 		rect = alloc_full_rect(screen);
 		if (!rect)
 			return rect;
-		for (i=0; i<screen->screenwidth*screen->screenheight; i++)
-			rect->data[i] = color_value(screen->screen[i]);
+		memcpy(rect->data, screen->rect->data, sizeof(*rect->data) * screen->screenwidth * screen->screenheight);
 		return rect;
 	}
 	return NULL;
@@ -486,6 +487,7 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
 	uint8_t fb = 0;
 	int		y;
 	int		fontoffset;
+	int		pixeloffset;
 	unsigned char *this_font;
 	WORD	sch;
 	struct vstat_vmem *vmem_ptr;
@@ -501,22 +503,6 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
 		return(-1);
 	}
 
-	pthread_mutex_lock(&screena.screenlock);
-	pthread_mutex_lock(&screenb.screenlock);
-
-	if ((xoffset + vstat.charwidth > screena.screenwidth) || (yoffset + vstat.charheight > screena.screenheight) ||
-	    (xoffset + vstat.charwidth > screenb.screenwidth) || (yoffset + vstat.charheight > screenb.screenheight)) {
-		pthread_mutex_unlock(&screenb.screenlock);
-		pthread_mutex_unlock(&screena.screenlock);
-		return(-1);
-	}
-
-	if((!screena.screen) || (!screenb.screen)) {
-		pthread_mutex_unlock(&screenb.screenlock);
-		pthread_mutex_unlock(&screena.screenlock);
-		return(-1);
-	}
-
 	sch=vmem_ptr->vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)].legacy_attr << 8 | vmem_ptr->vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)].ch;
 	fg = vmem_ptr->vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)].fg;
 	bg = vmem_ptr->vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)].bg;
@@ -539,8 +525,6 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
 					this_font = (unsigned char *)conio_fontdata[vmem_ptr->vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)].font].eight_by_sixteen;
 					break;
 				default:
-					pthread_mutex_unlock(&screenb.screenlock);
-					pthread_mutex_unlock(&screena.screenlock);
 					return(-1);
 			}
 		}
@@ -550,7 +534,24 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
 	fdw = vstat.charwidth - (vstat.flags & VIDMODES_FLAG_EXPAND) ? 1 : 0;
 	fontoffset=(sch & 0xff) * (vstat.charheight * ((fdw + 7) / 8));
 
+	pthread_mutex_lock(&screena.screenlock);
+	pthread_mutex_lock(&screenb.screenlock);
+
+	if ((xoffset + vstat.charwidth > screena.screenwidth) || (yoffset + vstat.charheight > screena.screenheight) ||
+	    (xoffset + vstat.charwidth > screenb.screenwidth) || (yoffset + vstat.charheight > screenb.screenheight)) {
+		pthread_mutex_unlock(&screenb.screenlock);
+		pthread_mutex_unlock(&screena.screenlock);
+		return(-1);
+	}
+
+	if((!screena.screen) || (!screenb.screen)) {
+		pthread_mutex_unlock(&screenb.screenlock);
+		pthread_mutex_unlock(&screena.screenlock);
+		return(-1);
+	}
+
 	draw_fg = ((!(sch & 0x8000)) || vstat.no_blink);
+	pixeloffset = PIXEL_OFFSET(screena, xoffset, yoffset);
 	for(y=0; y<vstat.charheight; y++) {
 		for(x=0; x<vstat.charwidth; x++) {
 			fdx = x;
@@ -574,34 +575,39 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
 			}
 
 			if(fb & (0x80 >> (fdx & 7)) && draw_fg) {
-				if (screena.screen[PIXEL_OFFSET(screena, xoffset + x, yoffset + y)] != fg) {
+				if (screena.screen[pixeloffset] != fg) {
 					screena.update_pixels = 1;
-					screena.screen[PIXEL_OFFSET(screena, xoffset + x, yoffset + y)] = fg;
+					screena.screen[pixeloffset] = fg;
+					screena.rect->data[pixeloffset] = color_value(fg);
 				}
 			}
 			else {
-				if (screena.screen[PIXEL_OFFSET(screena, xoffset + x, yoffset + y)] != bg) {
+				if (screena.screen[pixeloffset] != bg) {
 					screena.update_pixels = 1;
-					screena.screen[PIXEL_OFFSET(screena, xoffset + x, yoffset + y)] = bg;
+					screena.screen[pixeloffset] = bg;
+					screena.rect->data[pixeloffset] = color_value(bg);
 				}
 			}
 
 			if(fb & (0x80 >> (fdx & 7))) {
-				if (screenb.screen[PIXEL_OFFSET(screenb, xoffset + x, yoffset + y)]!=fg) {
+				if (screenb.screen[pixeloffset] != fg) {
 					screenb.update_pixels = 1;
-					screenb.screen[PIXEL_OFFSET(screenb, xoffset + x, yoffset + y)]=fg;
+					screenb.screen[pixeloffset] = fg;
+					screenb.rect->data[pixeloffset] = color_value(fg);
 				}
 			}
 			else {
-				if (screenb.screen[PIXEL_OFFSET(screenb, xoffset+x, yoffset+y)]!=bg) {
+				if (screenb.screen[pixeloffset] != bg) {
 					screenb.update_pixels = 1;
-					screenb.screen[PIXEL_OFFSET(screenb, xoffset+x, yoffset+y)]=bg;
+					screenb.screen[pixeloffset]=bg;
+					screenb.rect->data[pixeloffset] = color_value(bg);
 				}
 			}
-
+			pixeloffset++;
 		}
 		if (x & 0x07)
 			fontoffset++;
+		pixeloffset += screena.screenwidth - vstat.charwidth;
 	}
 	pthread_mutex_unlock(&screenb.screenlock);
 	pthread_mutex_unlock(&screena.screenlock);
@@ -642,6 +648,7 @@ static void blinker_thread(void *data)
 	int curs_changed;
 	int blink_changed;
 	struct bitmap_screen *screen;
+	struct bitmap_screen *ncscreen;
 
 	SetThreadName("Blinker");
 	while(1) {
@@ -649,7 +656,7 @@ static void blinker_thread(void *data)
 		blink_changed = 0;
 		do {
 			SLEEP(10);
-			screen = current_screen();
+			both_screens(&screen, &ncscreen);
 		} while (screen->screen == NULL);
 		count++;
 		if (count==25) {
@@ -690,7 +697,13 @@ static void blinker_thread(void *data)
 					request_redraw();
 		}
 		pthread_mutex_lock(&screen->screenlock);
+		// TODO: Maybe we can optimize the blink_changed forced update?
 		if (screen->update_pixels || curs_changed || blink_changed) {
+			// If the other screen is update_pixels == 2, clear it.
+			pthread_mutex_lock(&ncscreen->screenlock);
+			if (ncscreen->update_pixels == 2)
+				ncscreen->update_pixels = 0;
+			pthread_mutex_unlock(&ncscreen->screenlock);
 			rect = get_full_rectangle_locked(screen);
 			screen->update_pixels = 0;
 			pthread_mutex_unlock(&screen->screenlock);
@@ -711,6 +724,13 @@ static void blinker_thread(void *data)
 	}
 }
 
+static __inline struct bitmap_screen *noncurrent_screen_locked(void)
+{
+	if (vstat.blink)
+		return &screenb;
+	return &screena;
+}
+
 static __inline struct bitmap_screen *current_screen_locked(void)
 {
 	if (vstat.blink)
@@ -718,14 +738,12 @@ static __inline struct bitmap_screen *current_screen_locked(void)
 	return(&screenb);
 }
 
-static __inline struct bitmap_screen *current_screen(void)
+static __inline void both_screens(struct bitmap_screen** current, struct bitmap_screen** noncurrent)
 {
-	struct bitmap_screen *ret;
-
 	pthread_mutex_lock(&vstatlock);
-	ret = current_screen_locked();
+	*current = current_screen_locked();
+	*noncurrent = noncurrent_screen_locked();
 	pthread_mutex_unlock(&vstatlock);
-	return(ret);
 }
 
 /*
@@ -901,7 +919,8 @@ void bitmap_gotoxy(int x, int y)
 		cio_textinfo.cury=y;
 		vstat.curs_col = x + cio_textinfo.winleft - 1;
 		vstat.curs_row = y + cio_textinfo.wintop - 1;
-		force_cursor = 1;
+		if (cursor_visible_locked())
+			force_cursor = 1;
 	}
 	pthread_mutex_unlock(&vstatlock);
 	pthread_mutex_unlock(&blinker_lock);
@@ -921,10 +940,12 @@ void bitmap_setcursortype(int type)
 		case _SOLIDCURSOR:
 			vstat.curs_start=0;
 			vstat.curs_end=vstat.charheight-1;
+			force_cursor = 1;
 			break;
 		default:
 		    vstat.curs_start = vstat.default_curs_start;
 		    vstat.curs_end = vstat.default_curs_end;
+			force_cursor = 1;
 			break;
 	}
 	pthread_mutex_unlock(&vstatlock);
@@ -1159,6 +1180,7 @@ int bitmap_movetext(int x, int y, int ex, int ey, int tox, int toy)
 	pthread_mutex_lock(&screena.screenlock);
 	for(screeny=0; screeny < height*vstat.charheight; screeny++) {
 		memmove(&(screena.screen[ssourcepos+sdestoffset]), &(screena.screen[ssourcepos]), sizeof(screena.screen[0])*width*vstat.charwidth);
+		memmove(&(screena.rect->data[ssourcepos+sdestoffset]), &(screena.rect->data[ssourcepos]), sizeof(screena.screen[0])*width*vstat.charwidth);
 		ssourcepos += direction * vstat.scrnwidth;
 	}
 	screena.update_pixels = 1;
@@ -1176,6 +1198,7 @@ int bitmap_movetext(int x, int y, int ex, int ey, int tox, int toy)
 	pthread_mutex_lock(&screenb.screenlock);
 	for(screeny=0; screeny < height*vstat.charheight; screeny++) {
 		memmove(&(screenb.screen[ssourcepos+sdestoffset]), &(screenb.screen[ssourcepos]), sizeof(screenb.screen[0])*width*vstat.charwidth);
+		memmove(&(screenb.rect->data[ssourcepos+sdestoffset]), &(screenb.rect->data[ssourcepos]), sizeof(screenb.screen[0])*width*vstat.charwidth);
 		ssourcepos += direction * vstat.scrnwidth;
 	}
 	screenb.update_pixels = 1;
@@ -1265,6 +1288,7 @@ void bitmap_setcustomcursor(int s, int e, int r, int b, int v)
 		vstat.curs_blinks=b;
 	if(v>=0)
 		vstat.curs_visible=v;
+	force_cursor = 1;
 	pthread_mutex_unlock(&vstatlock);
 	pthread_mutex_unlock(&blinker_lock);
 }
@@ -1344,6 +1368,7 @@ int bitmap_setpixel(uint32_t x, uint32_t y, uint32_t colour)
 		if (screena.screen[PIXEL_OFFSET(screena, x, y)] != colour) {
 			screena.screen[PIXEL_OFFSET(screena, x, y)]=colour;
 			screena.update_pixels = 1;
+			screena.rect->data[PIXEL_OFFSET(screena, x, y)]=color_value(colour);
 		}
 	}
 	pthread_mutex_unlock(&screena.screenlock);
@@ -1353,6 +1378,7 @@ int bitmap_setpixel(uint32_t x, uint32_t y, uint32_t colour)
 		if (screenb.screen[PIXEL_OFFSET(screenb, x, y)] != colour) {
 			screenb.screen[PIXEL_OFFSET(screenb, x, y)]=colour;
 			screenb.update_pixels = 1;
+			screenb.rect->data[PIXEL_OFFSET(screenb, x, y)]=color_value(colour);
 		}
 	}
 	pthread_mutex_unlock(&screenb.screenlock);
@@ -1401,10 +1427,14 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_
 		if (mask == NULL) {
 			for (x = sx; x <= ex; x++) {
 				screena.screen[PIXEL_OFFSET(screena, x, y)] = pixels->pixels[pos];
-				if (pixels->pixelsb)
+				if (pixels->pixelsb) {
 					screenb.screen[PIXEL_OFFSET(screenb, x, y)] = pixels->pixelsb[pos];
-				else
+					screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = color_value(pixels->pixelsb[pos]);
+				}
+				else {
 					screenb.screen[PIXEL_OFFSET(screenb, x, y)] = pixels->pixels[pos];
+					screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = color_value(pixels->pixels[pos]);
+				}
 				pos++;
 			}
 		}
@@ -1415,10 +1445,15 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_
 				mask_bit = 0x80 >> mask_bit;
 				if (m[mask_byte] & mask_bit) {
 					screena.screen[PIXEL_OFFSET(screena, x, y)] = pixels->pixels[pos];
-					if (pixels->pixelsb)
+					screena.rect->data[PIXEL_OFFSET(screena, x, y)] = color_value(pixels->pixels[pos]);
+					if (pixels->pixelsb) {
 						screenb.screen[PIXEL_OFFSET(screenb, x, y)] = pixels->pixelsb[pos];
-					else
+						screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = color_value(pixels->pixelsb[pos]);
+					}
+					else {
 						screenb.screen[PIXEL_OFFSET(screenb, x, y)] = pixels->pixels[pos];
+						screenb.rect->data[PIXEL_OFFSET(screenb, x, y)] = color_value(pixels->pixels[pos]);
+					}
 				}
 				pos++;
 			}
@@ -1597,6 +1632,13 @@ static int init_screen(struct bitmap_screen *screen, int *width, int *height)
 	screen->screen = newscreen;
 	memset_u32(screen->screen, vstat.palette[0], screen->screenwidth * screen->screenheight);
 	screen->update_pixels = 1;
+	bitmap_drv_free_rect(screen->rect);
+	screen->rect = alloc_full_rect(screen);
+	if (screen->rect == NULL) {
+		pthread_mutex_unlock(&screen->screenlock);
+		return(-1);
+	}
+	memset_u32(screen->rect->data, color_value(vstat.palette[0]), screen->rect->rect.width * screen->rect->rect.height);
 	pthread_mutex_unlock(&screen->screenlock);
 	return(0);
 }
@@ -1714,12 +1756,13 @@ int bitmap_drv_init(void (*drawrect_cb) (struct rectlist *data)
 
 void bitmap_drv_request_pixels(void)
 {
-	// TODO: We may need something extra now... this results in two updates.
 	pthread_mutex_lock(&screena.screenlock);
-	screena.update_pixels = 1;
+	if (screena.update_pixels == 0)
+		screena.update_pixels = 2;
 	pthread_mutex_unlock(&screena.screenlock);
 	pthread_mutex_lock(&screenb.screenlock);
-	screenb.update_pixels = 1;
+	if (screenb.update_pixels == 0)
+		screenb.update_pixels = 2;
 	pthread_mutex_unlock(&screenb.screenlock);
 }
 
@@ -1731,6 +1774,8 @@ void bitmap_drv_request_some_pixels(int x, int y, int width, int height)
 
 void bitmap_drv_free_rect(struct rectlist *rect)
 {
+	if (rect == NULL)
+		return;
 	pthread_mutex_lock(&free_rect_lock);
 	rect->next = free_rects;
 	free_rects = rect;
diff --git a/src/conio/scale.c b/src/conio/scale.c
index 6b5c0d8b97e8d72f69a0124f29d5fc616d024a35..a029b03929c24ab0ecbc59c5a2b64d25d8704710 100644
--- a/src/conio/scale.c
+++ b/src/conio/scale.c
@@ -185,6 +185,8 @@ get_buffer(void)
 void
 release_buffer(struct graphics_buffer *buf)
 {
+	if (buf == NULL)
+		return;
 	buf->next = free_list;
 	free_list = buf;
 }
@@ -724,30 +726,29 @@ pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height)
 	}
 }
 
-static
-uint32_t blend(const uint32_t c1, const uint32_t c2, const double weight)
+static uint32_t
+blend(const uint32_t c1, const uint32_t c2, int weight)
 {
 	uint8_t yuv1[4];
 	uint8_t yuv2[4];
-	int y, u, v;
-	const double iw = 1.0 - weight;
+	uint8_t yuv3[4];
+	const double iw = 256 - 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;
+	yuv3[0] = 0;
+	yuv3[1] = (yuv1[1] * iw + yuv2[1] * weight) / 256;
+	yuv3[2] = (yuv1[2] * iw + yuv2[2] * weight) / 256;
+	yuv3[3] = (yuv1[3] * iw + yuv2[3] * weight) / 256;
 #else
-	y = yuv1[2] * iw + yuv2[2] * weight;
-	u = yuv1[1] * iw + yuv2[1] * weight;
-	v = yuv1[0] * iw + yuv2[0] * weight;
+	yuv3[3] = 0;
+	yuv3[2] = (yuv1[2] * iw + yuv2[2] * weight) / 256;
+	yuv3[1] = (yuv1[1] * iw + yuv2[1] * weight) / 256;
+	yuv3[0] = (yuv1[0] * iw + yuv2[0] * weight) / 256;
 #endif
-	CLAMP(y);
-	CLAMP(u);
-	CLAMP(v);
 
-	return y2r[(y<<16)|(u<<8)|v];
+	return y2r[*(uint32_t*)yuv3];
 }
 
 /*
@@ -773,12 +774,12 @@ interpolate_width(uint32_t* src, uint32_t* dst, int width, int height, int newwi
 			else {
 				const double weight = xpos - xposi;
 				// Now pick the two pixels
-				const uint32_t pix1 = src[y * width + xposi] & 0xffffff;
+				const uint32_t pix1 = src[y * width + xposi];
 				uint32_t pix2;
 				if (xposi < width - 1)
-					pix2 = src[y * width + xposi + 1] & 0xffffff;
+					pix2 = src[y * width + xposi + 1];
 				else
-					pix2 = src[y * width + xposi] & 0xffffff;
+					pix2 = src[y * width + xposi];
 				if (pix1 == pix2)
 					*dst = pix1;
 				else {
@@ -799,23 +800,53 @@ static void
 interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newheight)
 {
 	int x, y;
-	bool em = false;
 	const double mult = (double)height / newheight;
+	double ypos = 0;
+	int last_yposi = 0;
+	int ywn = width;
+	static uint32_t *nline = NULL;
+	static uint32_t *tline = NULL;
+	static size_t nsz = 0;
+	static size_t tsz = 0;
+	uint32_t *stmp;
+
+	if (nsz < width * 4) {
+		stmp = realloc(nline, width * 4);
+		if (stmp == NULL)
+			goto fail;
+		nline = stmp;
+		nsz = width * 4;
+	}
+	if (tsz < width * 4) {
+		stmp = realloc(tline, width * 4);
+		if (stmp == NULL)
+			goto fail;
+		tline = stmp;
+		tsz = width * 4;
+	}
 
+	memcpy(tline, src, width * sizeof(*tline));
+	memcpy(nline, src + width, width * sizeof(*tline));
 	for (y = 0; y < newheight; y++) {
-		const double ypos = mult * y;
 		const int yposi = ypos;
-		em = (y == ypos || yposi >= height - 1);
-		if (em) {
-			memcpy(dst, &src[yposi * width], width * sizeof(dst[0]));
+		if (yposi != last_yposi) {
+			ywn += width;
+			last_yposi = yposi;
+			stmp = tline;
+			tline = nline;
+			nline = stmp;
+			memcpy(nline, &src[ywn], nsz);
+		}
+		if (y == ypos || yposi >= height - 1) {
+			memcpy(dst, tline, tsz);
 			dst += width;
 		}
 		else {
-			const double weight = ypos - yposi;
+			const uint8_t weight = ypos * 256;
 			for (x = 0; x < width; x++) {
 				// Now pick the two pixels
-				const uint32_t pix1 = src[yposi * width + x] & 0xffffff;
-				const uint32_t pix2 = src[(yposi + 1) * width + x] & 0xffffff;
+				const uint32_t pix1 = tline[x];
+				const uint32_t pix2 = nline[x];
 				if (pix1 == pix2)
 					*dst = pix1;
 				else
@@ -823,7 +854,19 @@ interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newh
 				dst++;
 			}
 		}
+		ypos += mult;
 	}
+
+	return;
+fail:
+	free(nline);
+	free(tline);
+	nline = NULL;
+	tline = NULL;
+	nsz = 0;
+	tsz = 0;
+	memcpy(src, dst, width * height * sizeof(*src));
+	fprintf(stderr, "Allocation failure in interpolate_height()!");
 }
 
 static void
diff --git a/src/conio/x_events.c b/src/conio/x_events.c
index 8266622e6172853c47f52a8fed04ad3a623a7cc3..086ca7d38d115c6346fe34d3cb29a29722126b8f 100644
--- a/src/conio/x_events.c
+++ b/src/conio/x_events.c
@@ -464,7 +464,8 @@ static int video_init()
     return(0);
 }
 
-static void local_draw_rect(struct rectlist *rect)
+static void
+local_draw_rect(struct rectlist *rect)
 {
 	int x, y, xoff = 0, yoff = 0;
 	unsigned int r, g, b;
@@ -476,10 +477,12 @@ static void local_draw_rect(struct rectlist *rect)
 	int idx;
 	uint32_t last_pixel = 0x55555555;
 	struct graphics_buffer *source;
-	int lines;
+	bool isRGB8 = false;
 
-	if (bitmap_width != rect->rect.width || bitmap_height != rect->rect.height)
+	if (bitmap_width != rect->rect.width || bitmap_height != rect->rect.height) {
+		bitmap_drv_free_rect(rect);
 		return;
+	}
 
 	xoff = (x11_window_width - xim->width) / 2;
 	if (xoff < 0)
@@ -490,12 +493,12 @@ static void local_draw_rect(struct rectlist *rect)
 
 	// Scale...
 	source = do_scale(rect, x_cvstat.scaling, x_cvstat.scaling, x_cvstat.aspect_width, x_cvstat.aspect_height);
-	bitmap_drv_free_rect(rect);
-	if (source == NULL)
+	if (source == NULL) {
+		bitmap_drv_free_rect(rect);
 		return;
+	}
 	cleft = source->w;
 	ctop = source->h;
-	lines = 0;
 
 	xoff = (x11_window_width - source->w) / 2;
 	if (xoff < 0)
@@ -511,6 +514,9 @@ static void local_draw_rect(struct rectlist *rect)
 
 	/* TODO: Translate into local colour depth */
 	idx = 0;
+	if (visual.red_mask == 0xff0000 && visual.green_mask == 0x00ff00 && visual.blue_mask == 0x0000ff)
+		isRGB8 = true;
+
 	for (y = 0; y < source->h; y++) {
 		for (x = 0; x < source->w; x++) {
 			if (last) {
@@ -529,40 +535,44 @@ static void local_draw_rect(struct rectlist *rect)
 					continue;
 				}
 			}
-			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;
-				pixel = base_pixel;
-				if (r_shift >= 0)
-					pixel |= (r << r_shift) & visual.red_mask;
-				else
-					pixel |= (r >> (0-r_shift)) & visual.red_mask;
-				if (g_shift >= 0)
-					pixel |= (g << g_shift) & visual.green_mask;
-				else
-					pixel |= (g >> (0-g_shift)) & visual.green_mask;
-				if (b_shift >= 0)
-					pixel |= (b << b_shift) & visual.blue_mask;
-				else
-					pixel |= (b >> (0-b_shift)) & visual.blue_mask;
+			if (isRGB8) {
+				pixel = source->data[idx];
+				((uint32_t*)xim->data)[idx] = pixel;
 			}
+			else {
+				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;
+					pixel = base_pixel;
+					if (r_shift >= 0)
+						pixel |= (r << r_shift) & visual.red_mask;
+					else
+						pixel |= (r >> (0-r_shift)) & visual.red_mask;
+					if (g_shift >= 0)
+						pixel |= (g << g_shift) & visual.green_mask;
+					else
+						pixel |= (g >> (0-g_shift)) & visual.green_mask;
+					if (b_shift >= 0)
+						pixel |= (b << b_shift) & visual.blue_mask;
+					else
+						pixel |= (b >> (0-b_shift)) & visual.blue_mask;
+				}
 #ifdef XPutPixel
-			XPutPixel(xim, (x + rect->rect.x), (y + rect->rect.y), pixel);
+				XPutPixel(xim, x, y, pixel);
 #else
-			x11.XPutPixel(xim, (x + rect->rect.x), (y + rect->rect.y), pixel);
+				x11.XPutPixel(xim, x, y, pixel);
 #endif
+			}
 			idx++;
 		}
-		lines++;
 		/* This line was changed */
 		// TODO: Previously this did one update per display line...
-		if (last && (cbottom != y || y == source->h - 1) && cright >= 0) {
-			lines = 0;
+		if (last && cright >= 0 && (cbottom != y || y == source->h - 1)) {
 			x11.XPutImage(dpy, win, gc, xim, cleft, ctop
 			    , cleft + xoff, ctop + yoff
 			    , (cright - cleft + 1), (cbottom - ctop + 1));
@@ -573,7 +583,7 @@ static void local_draw_rect(struct rectlist *rect)
 	}
 
 	if (last == NULL)
-		x11.XPutImage(dpy, win, gc, xim, rect->rect.x, rect->rect.y, rect->rect.x + xoff, rect->rect.y + yoff, source->w, source->h);
+		x11.XPutImage(dpy, win, gc, xim, 0, 0, xoff, yoff, source->w, source->h);
 	else
 		release_buffer(last);
 	last = source;
@@ -1231,7 +1241,7 @@ void x11_event_thread(void *args)
 			case -1:
 				/*
 				* Errno might be wrong, so we just select again.
-				* This could cause a problem is something really
+				* This could cause a problem if something really
 				* was wrong with select....
 				*/