diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c
index c194aaf1f0bcf9014fa51c85f511c9768100672e..c6adeebe9bd97f7a8574138d65068bdb62850e0c 100644
--- a/src/conio/bitmap_con.c
+++ b/src/conio/bitmap_con.c
@@ -31,6 +31,7 @@ int screenheight=0;
 static int default_font=-99;
 static int current_font[4]={-99, -99, -99, -99};
 static int bitmap_initialized=0;
+pthread_mutex_t vmem_lock;
 struct video_stats vstat;
 static int *damaged=NULL;
 
@@ -64,6 +65,22 @@ static __inline void *locked_screen_check(void)
 	return(ret);
 }
 
+static struct vstat_vmem *lock_vmem(struct video_stats *vs)
+{
+	struct vstat_vmem *ret;
+	pthread_mutex_lock(&vstatlock);
+	ret = get_vmem(vs);
+	pthread_mutex_unlock(&vstatlock);
+	pthread_mutex_lock(&vmem_lock);
+	return ret;
+}
+
+static void unlock_vmem(struct vstat_vmem *vm)
+{
+	pthread_mutex_unlock(&vmem_lock);
+	release_vmem(vm);
+}
+
 /* Blinker Thread */
 static void blinker_thread(void *data)
 {
@@ -75,15 +92,15 @@ static void blinker_thread(void *data)
 			SLEEP(10);
 		} while(locked_screen_check()==NULL);
 		count++;
-		pthread_mutex_lock(&vstatlock);
 		if(count==50) {
+			pthread_mutex_lock(&vstatlock);
 			if(vstat.blink)
 				vstat.blink=FALSE;
 			else
 				vstat.blink=TRUE;
 			count=0;
+			pthread_mutex_unlock(&vstatlock);
 		}
-		pthread_mutex_unlock(&vstatlock);
 		if(force_redraws)
 			update_rect(0,0,0,0,force_redraws--);
 		else
@@ -100,11 +117,12 @@ int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height,
 {
 	if(bitmap_initialized)
 		return(-1);
+	pthread_mutex_init(&vmem_lock, NULL);
 	pthread_mutex_init(&vstatlock, NULL);
 	pthread_mutex_init(&screenlock, NULL);
-	pthread_mutex_lock(&vstatlock);
+	pthread_mutex_lock(&vmem_lock);
 	vstat.vmem=NULL;
-	pthread_mutex_unlock(&vstatlock);
+	pthread_mutex_unlock(&vmem_lock);
 
 	callbacks.drawrect=drawrect_cb;
 	callbacks.flush=flush_cb;
@@ -150,8 +168,10 @@ int bitmap_init_mode(int mode, int *width, int *height)
 	damaged=newdamaged;
 
 	/* Initialize video memory with black background, white foreground */
+	pthread_mutex_lock(&vmem_lock);
 	for (i = 0; i < vstat.cols*vstat.rows; ++i)
-	    vstat.vmem[i] = 0x0700;
+	    vstat.vmem->vmem[i] = 0x0700;
+	pthread_mutex_unlock(&vmem_lock);
 
 	screenwidth=vstat.charwidth*vstat.cols;
 	if(width)
@@ -323,6 +343,7 @@ int bitmap_movetext(int x, int y, int ex, int ey, int tox, int toy)
 	int	sourcepos;
 	int width=ex-x+1;
 	int height=ey-y+1;
+	struct vstat_vmem *vmem_ptr;
 
 	if(		   x<1
 			|| y<1
@@ -344,13 +365,13 @@ int bitmap_movetext(int x, int y, int ex, int ey, int tox, int toy)
 	sourcepos=(y-1)*cio_textinfo.screenwidth+(x-1);
 	destoffset=(((toy-1)*cio_textinfo.screenwidth+(tox-1))-sourcepos);
 
-	pthread_mutex_lock(&vstatlock);
+	vmem_ptr = lock_vmem(&vstat);
 	for(cy=(direction==-1?(height-1):0); cy<height && cy>=0; cy+=direction) {
 		damaged[toy+cy-1]=1;
 		sourcepos=((y-1)+cy)*cio_textinfo.screenwidth+(x-1);
-		memmove(&(vstat.vmem[sourcepos+destoffset]), &(vstat.vmem[sourcepos]), sizeof(vstat.vmem[0])*width);
+		memmove(&(vmem_ptr->vmem[sourcepos+destoffset]), &(vmem_ptr->vmem[sourcepos]), sizeof(vmem_ptr->vmem[0])*width);
 	}
-	pthread_mutex_unlock(&vstatlock);
+	unlock_vmem(vmem_ptr);
 	return(1);
 }
 
@@ -358,27 +379,29 @@ void bitmap_clreol(void)
 {
 	int pos,x;
 	WORD fill=(cio_textinfo.attribute<<8)|space;
+	struct vstat_vmem *vmem_ptr;
 
 	pos=(cio_textinfo.cury+cio_textinfo.wintop-2)*cio_textinfo.screenwidth;
-	pthread_mutex_lock(&vstatlock);
+	vmem_ptr = lock_vmem(&vstat);
 	damaged[cio_textinfo.cury-1]=1;
 	for(x=cio_textinfo.curx+cio_textinfo.winleft-2; x<cio_textinfo.winright; x++)
-		vstat.vmem[pos+x]=fill;
-	pthread_mutex_unlock(&vstatlock);
+		vmem_ptr->vmem[pos+x]=fill;
+	unlock_vmem(vmem_ptr);
 }
 
 void bitmap_clrscr(void)
 {
 	int x,y;
 	WORD fill=(cio_textinfo.attribute<<8)|space;
+	struct vstat_vmem *vmem_ptr;
 
-	pthread_mutex_lock(&vstatlock);
+	vmem_ptr = lock_vmem(&vstat);
 	for(y=cio_textinfo.wintop-1; y<cio_textinfo.winbottom; y++) {
 		damaged[y]=1;
 		for(x=cio_textinfo.winleft-1; x<cio_textinfo.winright; x++)
-			vstat.vmem[y*cio_textinfo.screenwidth+x]=fill;
+			vmem_ptr->vmem[y*cio_textinfo.screenwidth+x]=fill;
 	}
-	pthread_mutex_unlock(&vstatlock);
+	unlock_vmem(vmem_ptr);
 }
 
 int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill)
@@ -386,6 +409,7 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill)
 	int x,y;
 	unsigned char *out;
 	WORD	sch;
+	struct vstat_vmem *vmem_ptr;
 
 	if(!bitmap_initialized)
 		return(0);
@@ -402,17 +426,17 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill)
 			|| fill==NULL)
 		return(0);
 
-	pthread_mutex_lock(&vstatlock);
+	vmem_ptr = lock_vmem(&vstat);
 	out=fill;
 	for(y=sy-1;y<ey;y++) {
 		damaged[y]=1;
 		for(x=sx-1;x<ex;x++) {
 			sch=*(out++);
 			sch |= (*(out++))<<8;
-			vstat.vmem[y*cio_textinfo.screenwidth+x]=sch;
+			vmem_ptr->vmem[y*cio_textinfo.screenwidth+x]=sch;
 		}
 	}
-	pthread_mutex_unlock(&vstatlock);
+	unlock_vmem(vmem_ptr);
 	return(1);
 }
 
@@ -422,6 +446,7 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill)
 	int x,y;
 	unsigned char *out;
 	WORD	sch;
+	struct vstat_vmem *vmem_ptr;
 
 	if(!bitmap_initialized)
 		return(0);
@@ -437,16 +462,16 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill)
 			|| fill==NULL)
 		return(0);
 
-	pthread_mutex_lock(&vstatlock);
+	vmem_ptr = lock_vmem(&vstat);
 	out=fill;
 	for(y=sy-1;y<ey;y++) {
 		for(x=sx-1;x<ex;x++) {
-			sch=vstat.vmem[y*cio_textinfo.screenwidth+x];
+			sch=vmem_ptr->vmem[y*cio_textinfo.screenwidth+x];
 			*(out++)=sch & 0xff;
 			*(out++)=sch >> 8;
 		}
 	}
-	pthread_mutex_unlock(&vstatlock);
+	unlock_vmem(vmem_ptr);
 	return(1);
 }
 
@@ -823,6 +848,7 @@ static int bitmap_draw_one_char(struct video_stats *vs, unsigned int xpos, unsig
 	int		altfont;
 	unsigned char *this_font;
 	WORD	sch;
+	struct vstat_vmem *vmem_ptr;
 
 	if(!bitmap_initialized)
 		return(-1);
@@ -838,7 +864,11 @@ static int bitmap_draw_one_char(struct video_stats *vs, unsigned int xpos, unsig
 		return(-1);
 	}
 
-	sch=vs->vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)];
+	vmem_ptr = lock_vmem(vs);
+
+	sch=vmem_ptr->vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)];
+
+	unlock_vmem(vmem_ptr);
 
 	altfont = (sch>>11 & 0x01) | ((sch>>14) & 0x02);
 	if(vs->bright_background) {
@@ -887,10 +917,12 @@ static int update_rect(int sx, int sy, int width, int height, int force)
 	static unsigned short *this_vmem=NULL;
 	static struct video_stats vs;
 	struct video_stats cvstat;
+	struct vstat_vmem cvmem;
 	struct rectangle this_rect;
 	int this_rect_used=0;
 	struct rectangle last_rect;
 	int last_rect_used=0;
+	struct vstat_vmem *vmem_ptr;
 
 	if(!bitmap_initialized)
 		return(-1);
@@ -937,9 +969,14 @@ static int update_rect(int sx, int sy, int width, int height, int force)
 			|| vstat.curs_end!=vs.curs_end)
 		redraw_cursor=1;
 	cvstat = vstat;
-	cvstat.vmem = this_vmem;
-	memcpy(cvstat.vmem, vstat.vmem, vstat.cols*vstat.rows*sizeof(unsigned short));
+	vmem_ptr = get_vmem(&vstat);
 	pthread_mutex_unlock(&vstatlock);
+	pthread_mutex_lock(&vmem_lock);
+	cvstat.vmem = &cvmem;
+	cvstat.vmem->refcount = 1;
+	cvstat.vmem->vmem = this_vmem;
+	memcpy(cvstat.vmem->vmem, vmem_ptr->vmem, vstat.cols*vstat.rows*sizeof(unsigned short));
+	pthread_mutex_unlock(&vmem_lock);
 
 	for(y=0;y<height;y++) {
 		if(force 
@@ -950,11 +987,11 @@ static int update_rect(int sx, int sy, int width, int height, int force)
 			pos=(sy+y-1)*cvstat.cols+(sx-1);
 			for(x=0;x<width;x++) {
 				if(force
-						|| (last_vmem[pos] != cvstat.vmem[pos]) 					/* Different char */
-						|| ((cvstat.blink != vs.blink) && (cvstat.vmem[pos]>>15) && (!cvstat.no_blink)) 	/* Blinking char */
+						|| (last_vmem[pos] != cvstat.vmem->vmem[pos]) 					/* Different char */
+						|| ((cvstat.blink != vs.blink) && (cvstat.vmem->vmem[pos]>>15) && (!cvstat.no_blink)) 	/* Blinking char */
 						|| (redraw_cursor && ((vs.curs_col==sx+x && vs.curs_row==sy+y) || (cvstat.curs_col==sx+x && cvstat.curs_row==sy+y)))	/* Cursor */
 						) {
-					last_vmem[pos] = cvstat.vmem[pos];
+					last_vmem[pos] = cvstat.vmem->vmem[pos];
 					bitmap_draw_one_char(&cvstat, sx+x,sy+y);
 
 					if(!redraw_cursor && sx+x==cvstat.curs_col && sy+y==cvstat.curs_row)
diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c
index 3389807b5dea51910fd8ac569477ce32240b9c33..536c8058cffb9a3ce73b517d028945f9623f347c 100644
--- a/src/conio/sdl_con.c
+++ b/src/conio/sdl_con.c
@@ -892,6 +892,7 @@ void setup_surfaces(void)
 	int		flags=SDL_HWSURFACE|SDL_ANYFORMAT;
 	SDL_Surface	*tmp_rect;
 	SDL_Event	ev;
+	int charwidth, charheight, cols, scaling, rows, vmultiplier;
 
 	if(fullscreen)
 		flags |= SDL_FULLSCREEN;
@@ -900,14 +901,22 @@ void setup_surfaces(void)
 
 	sdl.mutexP(win_mutex);
 	pthread_mutex_lock(&vstatlock);
-	char_width=vstat.charwidth*vstat.cols*vstat.scaling;
-	char_height=vstat.charheight*vstat.rows*vstat.scaling*vstat.vmultiplier;
+	charwidth = vstat.charwidth;
+	charheight = vstat.charheight;
+	cols = vstat.cols;
+	scaling = vstat.scaling;
+	rows = vstat.rows;
+	vmultiplier = vstat.vmultiplier;
+	pthread_mutex_unlock(&vstatlock);
+	
+	char_width=charwidth*cols*scaling;
+	char_height=charheight*rows*scaling*vmultiplier;
 
 	if(yuv.enabled) {
 		if(!yuv.win_width)
-			yuv.win_width=vstat.charwidth*vstat.cols;
+			yuv.win_width=charwidth*cols;
 		if(!yuv.win_height)
-			yuv.win_height=vstat.charheight*vstat.rows;
+			yuv.win_height=charheight*rows;
 		if(fullscreen && yuv.screen_width && yuv.screen_height)
 			win=sdl.SetVideoMode(yuv.screen_width,yuv.screen_height,0,flags);
 		else
@@ -915,7 +924,6 @@ void setup_surfaces(void)
 	}
 	else
 		win=sdl.SetVideoMode(char_width,char_height,8,flags);
-	pthread_mutex_unlock(&vstatlock);
 
 #if !defined(NO_X) && defined(__unix__)
 	if(sdl_x11available && sdl_using_x11) {
@@ -1668,6 +1676,7 @@ int sdl_video_event_thread(void *data)
 									struct update_rect *rect=(struct update_rect *)ev.user.data1;
 									SDL_Rect r;
 									int x,y,offset;
+									int scaling, vmultiplier;
 
 									sdl.mutexP(win_mutex);
 									if(!win) {
@@ -1678,13 +1687,16 @@ int sdl_video_event_thread(void *data)
 									}
 									sdl.mutexP(newrect_mutex);
 									pthread_mutex_lock(&vstatlock);
+									scaling = vstat.scaling;
+									vmultiplier = vstat.vmultiplier;
+									pthread_mutex_unlock(&vstatlock);
 									for(y=0; y<rect->height; y++) {
 										offset=y*rect->width;
 										for(x=0; x<rect->width; x++) {
-											r.w=vstat.scaling;
-											r.h=vstat.scaling*vstat.vmultiplier;
-											r.x=(rect->x+x)*vstat.scaling;
-											r.y=(rect->y+y)*vstat.scaling*vstat.vmultiplier;
+											r.w=scaling;
+											r.h=scaling*vmultiplier;
+											r.x=(rect->x+x)*scaling;
+											r.y=(rect->y+y)*scaling*vmultiplier;
 											if(yuv.enabled)
 												yuv_fillrect(yuv.overlay, &r, rect->data[offset++]);
 											else
@@ -1700,10 +1712,10 @@ int sdl_video_event_thread(void *data)
 											pthread_mutex_unlock(&vstatlock);
 											break;
 										}
-										upd_rects[rectsused].x=rect->x*vstat.scaling;
-										upd_rects[rectsused].y=rect->y*vstat.scaling*vstat.vmultiplier;
-										upd_rects[rectsused].w=rect->width*vstat.scaling;
-										upd_rects[rectsused].h=rect->height*vstat.scaling*vstat.vmultiplier;
+										upd_rects[rectsused].x=rect->x*scaling;
+										upd_rects[rectsused].y=rect->y*scaling*vmultiplier;
+										upd_rects[rectsused].w=rect->width*scaling;
+										upd_rects[rectsused].h=rect->height*scaling*vmultiplier;
 										sdl.BlitSurface(new_rect, &(upd_rects[rectsused]), win, &(upd_rects[rectsused]));
 										rectsused++;
 										if(rectsused==rectspace) {
@@ -1711,7 +1723,6 @@ int sdl_video_event_thread(void *data)
 											rectsused=0;
 										}
 									}
-									pthread_mutex_unlock(&vstatlock);
 									sdl.mutexV(newrect_mutex);
 									sdl.mutexV(win_mutex);
 									free(rect->data);
diff --git a/src/conio/vidmodes.c b/src/conio/vidmodes.c
index 1fe79318cd587ea31eb4a08b277074ad5e4d94af..0c673ab8c2b2a06ba327335770f08b6ec9e341a8 100644
--- a/src/conio/vidmodes.c
+++ b/src/conio/vidmodes.c
@@ -158,18 +158,49 @@ int find_vmode(int mode)
 	return -1;
 }
 
+struct vstat_vmem *get_vmem(struct video_stats *vs)
+{
+	vs->vmem->refcount++;
+	return vs->vmem;
+}
+
+void release_vmem(struct vstat_vmem *vm)
+{
+	if (vm == NULL)
+		return;
+	vm->refcount--;
+	if (vm->refcount == 0) {
+		FREE_AND_NULL(vm->vmem);
+		FREE_AND_NULL(vm);
+	}
+}
+
+static struct vstat_vmem *new_vmem(int cols, int rows)
+{
+	struct vstat_vmem *ret = malloc(sizeof(struct vstat_vmem));
+
+	if (ret == NULL)
+		return ret;
+	ret->refcount = 1;
+	ret->vmem = (unsigned short *)malloc(cols*rows*sizeof(unsigned short));
+	if (ret->vmem == NULL) {
+		free(ret);
+		return NULL;
+	}
+	return ret;
+}
+
 int load_vmode(struct video_stats *vs, int mode)
 {
 	int i;
-	unsigned short *newvmem;
 
 	i=find_vmode(mode);
 	if(i==-1)
 		return(-1);
-	newvmem=(unsigned short *)realloc(vs->vmem, vparams[i].cols*vparams[i].rows*sizeof(unsigned short));
-	if(newvmem==NULL)
-		return(-1);
-	vs->vmem=newvmem;
+	release_vmem(vs->vmem);
+	vs->vmem=new_vmem(vparams[i].cols, vparams[i].rows);
+	if (vs->vmem == NULL)
+		return -1;
 	vs->rows=vparams[i].rows;
 	vs->cols=vparams[i].cols;
 	vs->curs_start=vparams[i].curs_start;
diff --git a/src/conio/vidmodes.h b/src/conio/vidmodes.h
index 968366a4e84799f96c07927db64951992ee60d1a..0d6425308460ba54c2518a5f29eebd8fc9ecbf6e 100644
--- a/src/conio/vidmodes.h
+++ b/src/conio/vidmodes.h
@@ -64,6 +64,11 @@ struct  video_params {
 	int	vmultiplier;
 };
 
+struct vstat_vmem {
+	unsigned refcount;
+	unsigned short *vmem;
+};
+
 struct video_stats {
 	int rows;
 	int cols;
@@ -89,7 +94,7 @@ struct video_stats {
 	int	vmultiplier;
 	struct dac_colors dac_colors[256];
 	unsigned char palette[16];
-	unsigned short *vmem;
+	struct vstat_vmem *vmem;
 };
 
 enum {
@@ -112,6 +117,8 @@ extern char vga_font_bitmap8[2048];
 extern "C" {
 #endif
 int find_vmode(int mode);
+struct vstat_vmem *get_vmem(struct video_stats *vs);
+void release_vmem(struct vstat_vmem *vm);
 int load_vmode(struct video_stats *vs, int mode);
 #ifdef __cplusplus
 }