diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c
index c98473510dca96eab50b8c11c7780ce893da9e33..89094f26c76cadb8f834f2fb39166b8ad10c80cd 100644
--- a/src/conio/bitmap_con.c
+++ b/src/conio/bitmap_con.c
@@ -35,6 +35,7 @@ struct video_stats vstat;
 
 struct bitmap_callbacks {
 	void	(*drawrect)		(int xpos, int ypos, int width, int height, unsigned char *data);
+	void	(*flush)		(void);
 };
 
 pthread_mutex_t		vstatlock;
@@ -66,7 +67,8 @@ static void blinker_thread(void *data)
 	}
 }
 
-int bitmap_init(void	(*drawrect_cb)		(int xpos, int ypos, int width, int height, unsigned char *data))
+int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, unsigned char *data)
+				,void (*flush_cb) (void))
 {
 	pthread_mutex_init(&vstatlock, NULL);
 	pthread_mutex_init(&screenlock, NULL);
@@ -75,6 +77,7 @@ int bitmap_init(void	(*drawrect_cb)		(int xpos, int ypos, int width, int height,
 	pthread_mutex_unlock(&vstatlock);
 
 	callbacks.drawrect=drawrect_cb;
+	callbacks.flush=flush_cb;
 	_beginthread(blinker_thread,0,NULL);
 
 	return(0);
@@ -89,10 +92,12 @@ void send_rectangle(int xoffset, int yoffset, int width, int height, int force)
 
 	pthread_mutex_lock(&screenlock);
 	if(callbacks.drawrect) {
+#ifdef PARANOIA
 		if(xoffset < 0 || xoffset >= screenwidth || yoffset < 0 || yoffset >= screenheight || width <= 0 || width > screenwidth || height <=0 || height >screenheight) {
 			pthread_mutex_unlock(&screenlock);
 			return;
 		}
+#endif
 
 		rect=(unsigned char *)malloc(width*height*sizeof(unsigned char));
 		if(!rect) {
@@ -203,14 +208,8 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill)
 			vstat.vmem[y*cio_textinfo.screenwidth+x]=sch;
 		}
 	}
-#ifdef SEPARATE_SEND_RECTANGLE
-	update_rect(sx,sy,ex-sx+1,ey-sy+1,FALSE,FALSE);
-	pthread_mutex_unlock(&vstatlock);
-	send_rectangle((sx-1)*vstat.charwidth, (sy-1)*vstat.charheight, (ex-sx+1)*vstat.charwidth, (ey-sy+1)*vstat.charheight, FALSE);
-#else
 	update_rect(sx,sy,ex-sx+1,ey-sy+1,FALSE,TRUE);
 	pthread_mutex_unlock(&vstatlock);
-#endif
 	return(1);
 }
 
@@ -227,8 +226,6 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill)
 			|| sy < 1
 			|| ex < 1
 			|| ey < 1
-			|| sx > cio_textinfo.screenwidth
-			|| sy > cio_textinfo.screenheight
 			|| sx > ex
 			|| sy > ey
 			|| ex > cio_textinfo.screenwidth
@@ -486,7 +483,7 @@ int bitmap_loadfont(char *filename)
 }
 
 /* Called from events thread only */
-static void bitmap_draw_cursor(void)
+static void bitmap_draw_cursor(int flush)
 {
 	int x;
 	int y;
@@ -513,6 +510,8 @@ static void bitmap_draw_cursor(void)
 			}
 			pthread_mutex_unlock(&screenlock);
 			send_rectangle(xoffset, yoffset+vstat.curs_start, vstat.charwidth, vstat.curs_end-vstat.curs_start+1,FALSE);
+			if(flush && callbacks.flush)
+				callbacks.flush();
 		}
 	}
 }
@@ -534,7 +533,7 @@ void bitmap_gotoxy(int x, int y)
 		if(lx != vstat.curs_col || ly != vstat.curs_row)
 			update_rect(lx,ly,1,1,TRUE,TRUE);
 		/* Draw new cursor */
-		bitmap_draw_cursor();
+		bitmap_draw_cursor(TRUE);
 		lx=vstat.curs_col;
 		ly=vstat.curs_row;
 	}
@@ -597,6 +596,7 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal
 	int this_rect_used=0;
 	struct rectangle last_rect;
 	int last_rect_used=0;
+	int	sent=FALSE;
 
 	if(sx==0 && sy==0 && width==0 && height==0)
 		fullredraw=1;
@@ -634,8 +634,8 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal
 		redraw_cursor=1;
 
 	for(y=0;y<height;y++) {
+		pos=(sy+y-1)*vstat.cols+(sx-1);
 		for(x=0;x<width;x++) {
-			pos=(sy+y-1)*vstat.cols+(sx+x-1);
 			if(force
 					|| (last_vmem[pos] != vstat.vmem[pos]) 					/* Different char */
 					|| (vstat.blink != vs.blink && vstat.vmem[pos]>>15) 	/* Blinking char */
@@ -643,6 +643,7 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal
 					) {
 				last_vmem[pos] = vstat.vmem[pos];
 				bitmap_draw_one_char(sx+x,sy+y);
+				sent=TRUE;
 
 				if(calls_send) {
 					if(lastcharupdated) {
@@ -653,7 +654,7 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal
 						if(this_rect_used) {
 							send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height,FALSE);
 						}
-	
+
 						this_rect.x=(sx+x-1)*vstat.charwidth;
 						this_rect.y=(sy+y-1)*vstat.charheight;
 						this_rect.width=vstat.charwidth;
@@ -731,7 +732,10 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal
 	}
 
 	if(redraw_cursor)
-		bitmap_draw_cursor();
+		bitmap_draw_cursor(FALSE);
+
+	if(sent && callbacks.flush)
+		callbacks.flush();
 
 	return(0);
 }
diff --git a/src/conio/bitmap_con.h b/src/conio/bitmap_con.h
index 58859654c30d2ecb7d5df6f1152d1eaa3ee5b4be..d6c47b7f65c4fc29f1606b29a6bdabe2ac628272 100644
--- a/src/conio/bitmap_con.h
+++ b/src/conio/bitmap_con.h
@@ -18,6 +18,7 @@ int bitmap_loadfont(char *filename);
 
 void send_rectangle(int xoffset, int yoffset, int width, int height, int force);
 int bitmap_init_mode(int mode, int *width, int *height);
-int bitmap_init(void	(*drawrect_cb)		(int xpos, int ypos, int width, int height, unsigned char *data));
+int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, unsigned char *data)
+				,void (*flush) (void));
 
 #endif
diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c
index 12df516f3b94736e445b5ad9601f9cf7428bbcb5..3a0b898a2ff8609abd17af3bad19bb24e3821f56 100644
--- a/src/conio/sdl_con.c
+++ b/src/conio/sdl_con.c
@@ -61,12 +61,14 @@ int sdl_ufunc_retval;
 
 int fullscreen=0;
 
-SDL_sem *sdl_init_complete;
 int	sdl_init_good=0;
 SDL_mutex *sdl_keylock;
 SDL_sem *sdl_key_pending;
 static unsigned int sdl_pending_mousekeys=0;
 Uint32	sdl_dac_default[sizeof(dac_default)/sizeof(struct dac_colors)];
+SDL_Rect	*upd_rects=NULL;
+int			rectspace=0;
+int			rectsused=0;
 
 struct sdl_keyvals {
 	int	keysym
@@ -86,6 +88,7 @@ struct update_rect {
 
 enum {
 	 SDL_USEREVENT_UPDATERECT
+	,SDL_USEREVENT_FLUSH
 	,SDL_USEREVENT_SETTITLE
 	,SDL_USEREVENT_SETNAME
 	,SDL_USEREVENT_SETICON
@@ -258,25 +261,11 @@ void sdl_user_func(int func, ...)
 			}
 			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
 			break;
-		case SDL_USEREVENT_SETVIDMODE:
-			if((ev.user.data1=(void *)malloc(sizeof(int)))==NULL) {
-				va_end(argptr);
-				return;
-			}
-			*((int *)ev.user.data1)=va_arg(argptr, int);
-			if((ev.user.data2=(void *)malloc(sizeof(int)))==NULL) {
-				free(ev.user.data1);
-				va_end(argptr);
-				return;
-			}
-			*((int *)ev.user.data2)=va_arg(argptr, int);
-			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
-			break;
 		case SDL_USEREVENT_COPY:
 		case SDL_USEREVENT_PASTE:
 		case SDL_USEREVENT_SHOWMOUSE:
 		case SDL_USEREVENT_HIDEMOUSE:
-		case SDL_USEREVENT_INIT:
+		case SDL_USEREVENT_FLUSH:
 			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
 			break;
 	}
@@ -300,6 +289,8 @@ int sdl_user_func_ret(int func, ...)
 	ev.user.code=func;
 	va_start(argptr, func);
 	switch(func) {
+		case SDL_USEREVENT_SETVIDMODE:
+		case SDL_USEREVENT_INIT:
 		case SDL_USEREVENT_QUIT:
 			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
 			passed=TRUE;
@@ -435,6 +426,11 @@ void sdl_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *da
 	}
 }
 
+void sdl_flush(void)
+{
+	sdl_user_func(SDL_USEREVENT_FLUSH);
+}
+
 int sdl_init_mode(int mode)
 {
     struct video_params vmode;
@@ -455,7 +451,7 @@ int sdl_init_mode(int mode)
 	if(vstat.scaling < 1)
 		vstat.scaling = 1;
 
-	sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols*vstat.scaling, vstat.charheight*vstat.rows*vstat.scaling);
+	sdl_user_func_ret(SDL_USEREVENT_SETVIDMODE);
 
     return(0);
 }
@@ -470,14 +466,13 @@ int sdl_init(int mode)
 	if(init_sdl_video())
 		return(-1);
 
-	bitmap_init(sdl_drawrect);
+	bitmap_init(sdl_drawrect, sdl_flush);
 
 	if(mode==CIOLIB_MODE_SDL_FULLSCREEN)
 		fullscreen=1;
 	sdl_init_mode(3);
-	sdl_user_func(SDL_USEREVENT_INIT);
+	sdl_user_func_ret(SDL_USEREVENT_INIT);
 
-	sdl.SemWait(sdl_init_complete);
 	if(sdl_init_good) {
 		cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
 #ifdef _WIN32
@@ -621,7 +616,7 @@ void sdl_add_key(unsigned int keyval)
 	if(keyval==0xa600) {
 		fullscreen=!fullscreen;
 		cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
-		sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols, vstat.charheight*vstat.rows);
+		sdl_user_func_ret(SDL_USEREVENT_SETVIDMODE);
 		return;
 	}
 	if(keyval <= 0xffff) {
@@ -1164,6 +1159,9 @@ int sdl_video_event_thread(void *data)
 									SDL_Rect r;
 									SDL_Rect dst;
 									int x,y,offset;
+
+									if(!win)
+										break;
 #ifndef DOUBLE_BUFFER
 									for(y=0; y<rect->height; y++) {
 										offset=y*rect->width;
@@ -1175,7 +1173,15 @@ int sdl_video_event_thread(void *data)
 											sdl.FillRect(win, &r, sdl_dac_default[rect->data[offset++]]);
 										}
 									}
-									sdl.UpdateRect(win,rect->x*vstat.scaling,rect->y*vstat.scaling,rect->width*vstat.scaling,rect->height*vstat.scaling);
+									upd_rects[rectsused].x=rect->x*vstat.scaling;
+									upd_rects[rectsused].y=rect->y*vstat.scaling;
+									upd_rects[rectsused].w=rect->width*vstat.scaling;
+									upd_rects[rectsused].h=rect->height*vstat.scaling;
+									rectsused++;
+									if(rectsused==rectspace) {
+										sdl.UpdateRects(win,rectsused,upd_rects);
+										rectsused=0;
+									}
 #else
 									for(y=0; y<rect->height; y++) {
 										for(x=0; x<rect->width; x++) {
@@ -1197,12 +1203,22 @@ int sdl_video_event_thread(void *data)
 									dst.w=rect->width*vstat.scaling;
 									dst.h=rect->height*vstat.scaling;
 									sdl.BlitSurface(new_rect, &r, win, &dst);
-									sdl.UpdateRects(win,1,&dst);
+									upd_rects[rectsused++]=dst;
+									if(rectsused==rectspace) {
+										sdl.UpdateRects(win,rectsused,upd_rects);
+										rectsused=0;
+									}
 #endif
 									free(rect->data);
 									free(rect);
 									break;
 								}
+							case SDL_USEREVENT_FLUSH:
+								if(win && upd_rects) {
+									sdl.UpdateRects(win,rectsused,upd_rects);
+									rectsused=0;
+								}
+								break;
 							case SDL_USEREVENT_SETNAME:
 								sdl.WM_SetCaption((char *)ev.user.data1,(char *)ev.user.data1);
 								free(ev.user.data1);
@@ -1229,6 +1245,15 @@ int sdl_video_event_thread(void *data)
 								break;
 							case SDL_USEREVENT_SETVIDMODE:
 								pthread_mutex_lock(&vstatlock);
+								rectspace=vstat.cols*vstat.rows+vstat.cols;
+								rectsused=0;
+								upd_rects=(SDL_Rect *)malloc(sizeof(SDL_Rect)*rectspace);
+								if(upd_rects==NULL) {
+									pthread_mutex_unlock(&vstatlock);
+									ev.type=SDL_QUIT;
+									sdl_exitcode=1;
+									sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff);
+								}
 								if(fullscreen)
 									win=sdl.SetVideoMode(
 										 vstat.charwidth*vstat.cols*vstat.scaling
@@ -1278,8 +1303,8 @@ int sdl_video_event_thread(void *data)
 								}
 								else
 									pthread_mutex_unlock(&vstatlock);
-								free(ev.user.data1);
-								free(ev.user.data2);
+								sdl_ufunc_retval=0;
+								sdl.SemPost(sdl_ufunc_ret);
 								break;
 							case SDL_USEREVENT_HIDEMOUSE:
 								sdl.ShowCursor(SDL_DISABLE);
@@ -1298,7 +1323,8 @@ int sdl_video_event_thread(void *data)
 										}
 									}
 								}
-								sdl.SemPost(sdl_init_complete);
+								sdl_ufunc_retval=0;
+								sdl.SemPost(sdl_ufunc_ret);
 								break;
 							case SDL_USEREVENT_COPY:
 	#if (defined(__MACH__) && defined(__APPLE__))
@@ -1493,7 +1519,6 @@ int sdl_initciolib(int mode)
 	if(init_sdl_video()==-1)
 		return(-1);
 	sdl_key_pending=sdl.SDL_CreateSemaphore(0);
-	sdl_init_complete=sdl.SDL_CreateSemaphore(0);
 	sdl_ufunc_ret=sdl.SDL_CreateSemaphore(0);
 	sdl_keylock=sdl.SDL_CreateMutex();
 	sdl_ufunc_lock=sdl.SDL_CreateMutex();