diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c
index a030f1e7f5e6293eb0a328395739dde9816c0ff3..444cdf88d79edb48cefa1f3b30573acdb381e45a 100644
--- a/src/conio/bitmap_con.c
+++ b/src/conio/bitmap_con.c
@@ -1745,12 +1745,24 @@ int bitmap_attr2palette(uint8_t attr, uint32_t *fgp, uint32_t *bgp)
 
 int bitmap_setpixel(uint32_t x, uint32_t y, uint32_t colour)
 {
-	update_from_vmem(FALSE);
+	int xchar = x / vstat.charwidth;
+	int ychar = y / vstat.charheight;
+
 	do_rwlock_wrlock(&vstatlock);
-	int off = vmem_cell_offset(vstat.vmem, x / vstat.charwidth, y / vstat.charheight);
+	pthread_mutex_lock(&screenlock);
+	if (screena.rect == NULL || screenb.rect == NULL || x >= screena.screenwidth || y >= screena.screenheight) {
+		pthread_mutex_unlock(&screenlock);
+		do_rwlock_unlock(&vstatlock);
+		return 0;
+	}
+	int off = vmem_cell_offset(vstat.vmem, xchar, ychar);
+	if (!same_cell(&bitmap_drawn[off], &vstat.vmem->vmem[off])) {
+		pthread_mutex_unlock(&screenlock);
+		bitmap_draw_from_vmem(xchar + 1, ychar + 1, xchar + 1, ychar + 1);
+		pthread_mutex_lock(&screenlock);
+	}
 	vstat.vmem->vmem[off].bg |= 0x04000000;
 	bitmap_drawn[off].bg |= 0x04000000;
-	pthread_mutex_lock(&screenlock);
 	if (x < screena.screenwidth && y < screena.screenheight) {
 		if (screena.rect->data[pixel_offset(&screena, x, y)] != colour) {
 			screena.update_pixels = 1;
@@ -1801,7 +1813,6 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_
 			return 0;
 	}
 
-	update_from_vmem(FALSE);
 	do_rwlock_wrlock(&vstatlock);
 	pthread_mutex_lock(&screenlock);
 	if (ex > screena.screenwidth || ey > screena.screenheight) {
@@ -1810,13 +1821,44 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_
 		return 0;
 	}
 
+	int charsx = sx / vstat.charwidth;
+	int charx = charsx;
+	int chary = sy / vstat.charheight;
+	int cpx = sx % vstat.charwidth;
+	int cpy = sy % vstat.charheight;
+	bool xupdated = false;
+	bool yupdated = false;
+	int off;
 	for (y = sy; y <= ey; y++) {
 		pos = pixels->width*(y-sy+y_off)+x_off;
+		if (!yupdated) {
+			off = vmem_cell_offset(vstat.vmem, charx, chary);
+		}
+		charx = charsx;
 		if (mask == NULL) {
 			for (x = sx; x <= ex; x++) {
-				int off = vmem_cell_offset(vstat.vmem, x / vstat.charwidth, y / vstat.charheight);
-				vstat.vmem->vmem[off].bg |= 0x04000000;
-				bitmap_drawn[off].bg |= 0x04000000;
+				if (!yupdated) {
+					if (!xupdated) {
+						if (!same_cell(&bitmap_drawn[off], &vstat.vmem->vmem[off])) {
+							pthread_mutex_unlock(&screenlock);
+							bitmap_draw_from_vmem(charx + 1, chary + 1, charx + 1, chary + 1);
+							pthread_mutex_lock(&screenlock);
+						}
+						if (vstat.vmem && vstat.vmem->vmem) {
+							vstat.vmem->vmem[off].bg |= 0x04000000;
+						}
+						if (bitmap_drawn) {
+							bitmap_drawn[off].bg |= 0x04000000;
+						}
+						xupdated = true;
+					}
+				}
+				if (++cpx >= vstat.charwidth) {
+					cpx = 0;
+					charx++;
+					xupdated = false;
+					off = vmem_next_offset(vstat.vmem, off);
+				}
 				if (screena.rect->data[pixel_offset(&screena, x, y)] != pixels->pixels[pos]) {
 					screena.rect->data[pixel_offset(&screena, x, y)] = pixels->pixels[pos];
 					screena.update_pixels = 1;
@@ -1839,9 +1881,28 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_
 		else {
 			mpos = mask->width * (y - sy + my_off) + mx_off;
 			for (x = sx; x <= ex; x++) {
-				int off = vmem_cell_offset(vstat.vmem, x / vstat.charwidth, y / vstat.charheight);
-				vstat.vmem->vmem[off].bg |= 0x04000000;
-				bitmap_drawn[off].bg |= 0x04000000;
+				if (!yupdated) {
+					if (!xupdated) {
+						if (!same_cell(&bitmap_drawn[off], &vstat.vmem->vmem[off])) {
+							pthread_mutex_unlock(&screenlock);
+							bitmap_draw_from_vmem(charx + 1, chary + 1, charx + 1, chary + 1);
+							pthread_mutex_lock(&screenlock);
+						}
+						if (vstat.vmem && vstat.vmem->vmem) {
+							vstat.vmem->vmem[off].bg |= 0x04000000;
+						}
+						if (bitmap_drawn) {
+							bitmap_drawn[off].bg |= 0x04000000;
+						}
+						xupdated = true;
+					}
+				}
+				if (++cpx >= vstat.charwidth) {
+					cpx = 0;
+					charx++;
+					xupdated = false;
+					off = vmem_next_offset(vstat.vmem, off);
+				}
 				mask_byte = mpos / 8;
 				mask_bit = mpos % 8;
 				mask_bit = 0x80 >> mask_bit;
@@ -1867,6 +1928,14 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_
 				mpos++;
 			}
 		}
+		cpy++;
+		if (cpy >= vstat.charheight) {
+			cpy = 0;
+			yupdated = false;
+			xupdated = false;
+		}
+		else
+			yupdated = true;
 	}
 	pthread_mutex_unlock(&screenlock);
 	do_rwlock_unlock(&vstatlock);