diff --git a/src/conio/Common.bmake b/src/conio/Common.bmake
index 477c848ac9c7bf2ee16afc0a260ea3dbcf08b76e..ba3dab80680eb187702ccaeb29b15b07c49ff282 100644
--- a/src/conio/Common.bmake
+++ b/src/conio/Common.bmake
@@ -1,6 +1,6 @@
 !ifdef USE_SDL
-CIOLIB-MT_CFLAGS = $(CIOLIB-MT_CFLAGS) -DHAS_VSTAT -DWITH_SDL -DWIN32 -I${SRC_ROOT}/../include/sdl
-CIOLIB_CFLAGS = $(CIOLIB_CFLAGS) -DHAS_VSTAT -DWITH_SDL -DWIN32 -I${SRC_ROOT}/../include/sdl
+CIOLIB-MT_CFLAGS = $(CIOLIB-MT_CFLAGS) -DHAS_VSTAT -DWITH_SDL -DWIN32 -I${3RDP_ROOT}/win32.release/sdl2/include
+CIOLIB_CFLAGS = $(CIOLIB_CFLAGS) -DHAS_VSTAT -DWITH_SDL -DWIN32 -I${3RDP_ROOT}/win32.release/sdl2/include
 !ifdef STATIC_SDL
 CIOLIB-MT_CFLAGS = $(CIOLIB-MT_CFLAGS) -DSTATIC_SDL
 CIOLIB_CFLAGS = $(CIOLIB_CFLAGS) -DSTATIC_SDL
diff --git a/src/conio/Common.gmake b/src/conio/Common.gmake
index d504deba2391ac4d0b623a19d04a745863d93bf3..37fa053f079b447dad8e1a36d7e2dc7887dbef40 100644
--- a/src/conio/Common.gmake
+++ b/src/conio/Common.gmake
@@ -21,7 +21,7 @@ ifeq ($(os),openbsd)
  CFLAGS += -DHAVE_VASPRINTF
 endif
 ifeq ($(os),win32)
- CFLAGS += -I${SRC_ROOT}/../include/sdl
+ CFLAGS += -I${3RDP_ROOT}/win32.release/sdl2/include
 endif
 
 ifneq ($(os),win32)
@@ -60,33 +60,28 @@ endif
 ifdef USE_SDL
  ifndef WITH_SDL_AUDIO
   ifdef SDL_CONFIG
-   ifeq ($(shell ${SDL_CONFIG} --cflags > /dev/null 2>&1 && echo YES),YES)
-	WITH_SDL	:=	1
+   ifeq ($(shell if [ `${SDL_CONFIG} --version | sed -E 's/\..*$$//'` -ge 2 ] ; then echo 'YES' ; fi),YES)
+    WITH_SDL	:=	1
    endif
   else
    ifeq ($(os),darwin)
-	ifeq ($(shell if [ -d /Library/Frameworks/SDL.framework ] ; then echo YES ; fi),YES)
+    ifeq ($(shell if [ -d /Library/Frameworks/SDL.framework ] ; then echo YES ; fi),YES)
      SDL_FRAMEWORK_PATH ?= /Library/Frameworks
-	endif
+    endif
     ifdef SDL_FRAMEWORK_PATH
      WITH_SDL	:=	1
      CIOLIB-MT_LDFLAGS += -Wl,-rpath,@executable_path/../Frameworks
     endif
    else
-    ifeq ($(shell sdl12-config --cflags > /dev/null 2>&1 && echo YES),YES)
-     SDL_CONFIG := sdl12-config
+    ifeq ($(shell sdl2-config --cflags > /dev/null 2>&1 && echo YES),YES)
+     SDL_CONFIG := sdl2-config
      WITH_SDL	:=	1
     else
-	 ifeq ($(shell sdl-config --cflags > /dev/null 2>&1 && echo YES),YES)
+     ifeq ($(shell if [ `sdl-config --version | sed -E 's/\..*$$//'` -ge 2 ] ; then echo 'YES' ; fi),YES)
       SDL_CONFIG := sdl-config
       WITH_SDL	:=	1
-	 else
-      ifeq ($(shell sdl11-config --cflags > /dev/null 2>&1 && echo YES),YES)
-       SDL_CONFIG := sdl11-config
-       WITH_SDL	:=	1
-      endif
      endif
-	endif
+    endif
    endif
   endif
  endif
diff --git a/src/conio/GNUmakefile b/src/conio/GNUmakefile
index 368fabd08d81f778c9b23cf5a7b9ead1cf91bce6..1e06199b468a08c7299c3080d6e19735aa27a1ae 100644
--- a/src/conio/GNUmakefile
+++ b/src/conio/GNUmakefile
@@ -5,7 +5,6 @@ include $(SRC_ROOT)/build/Common.gmake	# defines clean and output directory rule
 CFLAGS += $(XPDEV-MT_CFLAGS) $(ENCODE_CFLAGS) $(CIOLIB-MT_CFLAGS)
 
 ifeq ($(os),win32)
- OBJS	+=	$(MTOBJODIR)$(DIRSEP)SDL_win32_main$(OFILE)
  OBJS	+=	$(MTOBJODIR)$(DIRSEP)win32cio$(OFILE)
  OBJS	+=	$(MTOBJODIR)$(DIRSEP)ciolib_res$(OFILE)
 else
@@ -31,7 +30,6 @@ else
   OBJS	+=	$(MTOBJODIR)$(DIRSEP)sdl_con$(OFILE)
   OBJS	+=      $(MTOBJODIR)$(DIRSEP)sdlfuncs$(OFILE)
   ifeq ($(os),darwin)
-   OBJS 	+=      $(MTOBJODIR)$(DIRSEP)SDLMain$(OFILE)
    OBJS 	+=      $(MTOBJODIR)$(DIRSEP)pasteboard$(OFILE)
   endif
  endif
@@ -58,10 +56,6 @@ $(CIOLIB-MT_SHLIB_BUILD): $(MTOBJODIR) $(OBJS)
 	$(QUIET)$(MKSHLIB) $(LDFLAGS) $(OBJS) $(SHLIBOPTS) -o $@
 
 ifeq ($(os),darwin)
-$(MTOBJODIR)$(DIRSEP)SDLMain$(OFILE): SDLMain.m
-	@echo $(COMPILE_MSG) $<
-	$(QUIET)$(CC) $(CFLAGS) $(CCFLAGS) -o $@ -c $<
-
 $(MTOBJODIR)$(DIRSEP)pasteboard$(OFILE): pasteboard.m
 	@echo $(COMPILE_MSG) $<
 	$(QUIET)$(CC) $(CFLAGS) $(CCFLAGS) -o $@ -c $<
diff --git a/src/conio/ciolib.h b/src/conio/ciolib.h
index bb8bc3591d715e50a415a48fff92596205c1aa3b..9300c46b80043162f46f1cd79ee5156c525b173c 100644
--- a/src/conio/ciolib.h
+++ b/src/conio/ciolib.h
@@ -544,11 +544,6 @@ CIOLIBEXPORT void CIOLIBCALL ansi_ciolib_setdoorway(int enable);
 #ifdef WITH_SDL
 	#include <gen_defs.h>
 	#include <SDL.h>
-
-	#ifdef main
-		#undef main
-	#endif
-	#define	main	CIOLIB_main
 #endif
 
 #define CIOLIB_BUTTON_1	1
diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c
index 35af80de6a2dd52595d41dda7b138c24dfeb9b40..bc62aba05af63cb4d061ada6c7d3691b3ebde1ba 100644
--- a/src/conio/sdl_con.c
+++ b/src/conio/sdl_con.c
@@ -44,13 +44,11 @@ unsigned char		sdl_keynext=0;			/* Index into keybuf for next free position */
 
 int sdl_exitcode=0;
 
-SDL_Surface	*win=NULL;
+SDL_Window	*win=NULL;
+SDL_Renderer	*renderer=NULL;
+SDL_Texture	*texture=NULL;
 SDL_mutex	*win_mutex;
 SDL_Surface	*sdl_icon=NULL;
-SDL_Surface	*new_rect=NULL;
-SDL_mutex	*newrect_mutex;
-SDL_mutex	*bitmap_init_mutex;
-static int bitmap_initialized = 0;
 
 /* *nix copy/paste stuff */
 int paste_needs_events;
@@ -83,19 +81,6 @@ static int sdl_x11available=0;
 
 static struct video_stats cvstat;
 
-struct yuv_settings {
-	int			enabled;
-	int			win_width;
-	int			win_height;
-	int			screen_width;
-	int			screen_height;
-	int			changed;
-	int			best_format;
-	SDL_Overlay	*overlay;
-};
-
-static struct yuv_settings yuv={0,0,0,0,0,0,0,NULL};
-
 struct sdl_keyvals {
 	int	keysym
 		,key
@@ -175,16 +160,16 @@ const struct sdl_keyvals sdl_keyval[] =
 	{SDLK_DOWN, 0x5000, 0x5000, 0x9100, 0xa000},
 	{SDLK_INSERT, 0x5200, 0x5200, 0x9200, 0xa200},
 	{SDLK_DELETE, 0x5300, 0x5300, 0x9300, 0xa300},
-	{SDLK_KP0, 0x5200, 0x5200, 0x9200, 0},
-	{SDLK_KP1, 0x4f00, 0x4f00, 0x7500, 0},
-	{SDLK_KP2, 0x5000, 0x5000, 0x9100, 0},
-	{SDLK_KP3, 0x5100, 0x5100, 0x7600, 0},
-	{SDLK_KP4, 0x4b00, 0x4b00, 0x7300, 0},
-	{SDLK_KP5, 0x4c00, 0x4c00, 0x8f00, 0},
-	{SDLK_KP6, 0x4d00, 0x4d00, 0x7400, 0},
-	{SDLK_KP7, 0x4700, 0x4700, 0x7700, 0},
-	{SDLK_KP8, 0x4800, 0x4800, 0x8d00, 0},
-	{SDLK_KP9, 0x4900, 0x4900, 0x8400, 0},
+	{SDLK_KP_0, 0x5200, 0x5200, 0x9200, 0},
+	{SDLK_KP_1, 0x4f00, 0x4f00, 0x7500, 0},
+	{SDLK_KP_2, 0x5000, 0x5000, 0x9100, 0},
+	{SDLK_KP_3, 0x5100, 0x5100, 0x7600, 0},
+	{SDLK_KP_4, 0x4b00, 0x4b00, 0x7300, 0},
+	{SDLK_KP_5, 0x4c00, 0x4c00, 0x8f00, 0},
+	{SDLK_KP_6, 0x4d00, 0x4d00, 0x7400, 0},
+	{SDLK_KP_7, 0x4700, 0x4700, 0x7700, 0},
+	{SDLK_KP_8, 0x4800, 0x4800, 0x8d00, 0},
+	{SDLK_KP_9, 0x4900, 0x4900, 0x8400, 0},
 	{SDLK_KP_MULTIPLY, '*', '*', 0x9600, 0x3700},
 	{SDLK_KP_PLUS, '+', '+', 0x9000, 0x4e00},
 	{SDLK_KP_MINUS, '-', '-', 0x8e00, 0x4a00},
@@ -242,127 +227,7 @@ struct x11 {
 struct x11 sdl_x11;
 #endif
 
-static void RGBtoYUV(Uint8 r, Uint8 g, Uint8 b, Uint8 *yuv_array)
-{
-	int i;
-
-	//yuv_array[0] = (Uint8)((0.257 * r) + (0.504 * g) + (0.098 * b) + 16);
-	i = (r*263+g*516+b*100+16384);
-	yuv_array[0] = i >> 10;
-	//yuv_array[1] = (Uint8)(128 - (0.148 * r) - (0.291 * g) + (0.439 * b));
-	i = 131072 - 152*r - 298*g + 450*b;
-	yuv_array[1] = i >> 10;
-	//yuv_array[2] = (Uint8)(128 + (0.439 * r) - (0.368 * g) - (0.071 * b));
-	i = 131072 + 450*r - 377*g - 73*b;
-	yuv_array[2] = i >> 10;
-}
-
-static void yuv_fillrect(SDL_Overlay *restrict overlay, SDL_Rect *restrict r, Uint8 *restrict yuvc)
-{
-	int uplane,vplane;					/* Planar formats */
-	int y0pack, y1pack, u0pack, v0pack;	/* Packed formats */
-
-	if(!overlay)
-		return;
-	if(r->x > overlay->w || r->y > overlay->h)
-		return;
-	if(r->x + r->w > overlay->w)
-		r->w=overlay->w-r->x;
-	if(r->y + r->h > overlay->h)
-		r->h=overlay->h-r->y;
-	yuv.changed=1;
-	switch(overlay->format) {
-		case SDL_IYUV_OVERLAY:
-			/* YUV 4:2:0 NxM Y followed by (N/2)x(M/2) U and V (12bpp) */
-			uplane=1;
-			vplane=2;
-			goto planar;
-		case SDL_YV12_OVERLAY:
-			/* YUV 4:2:0 NxM Y followed by (N/2)x(M/2) V and U (12bpp) */
-			vplane=1;
-			uplane=2;
-			goto planar;
-		case SDL_YUY2_OVERLAY:
-			/* YUV 4:2:2 Y0,U0,Y1,V0 (16bpp) */
-			y0pack=0;
-			u0pack=1;
-			y1pack=2;
-			v0pack=3;
-			goto packed;
-		case SDL_UYVY_OVERLAY:
-			/* YUV 4:2:2 U0,Y0,V0,Y1 (16bpp)  */
-			u0pack=0;
-			y0pack=1;
-			v0pack=2;
-			y1pack=3;
-			goto packed;
-		case SDL_YVYU_OVERLAY:
-			/* YUV 4:2:2 Y0,V0,Y1,U0 (16bpp)  */
-			y0pack=0;
-			v0pack=1;
-			y1pack=2;
-			u0pack=3;
-			goto packed;
-	}
-	return;
-
-planar:
-	sdl.LockYUVOverlay(overlay);
-	{
-		int y;
-		Uint8 *Y,*U,*V;
-		int odd_line;
-		int uvlen=(r->w)>>1;
-		int uvoffset=overlay->pitches[1]*((r->y+1)>>1)+((r->x+1)>>1);
-
-		odd_line=(r->y)&1;
-		Y=overlay->pixels[0]+overlay->pitches[0]*(r->y)+(r->x);
-		U=overlay->pixels[uplane]+uvoffset;
-		V=overlay->pixels[vplane]+uvoffset;
-
-		for(y=0; y<r->h; y++)
-		{
-			memset(Y, yuvc[0], r->w);
-			/* Increment every line */
-			Y+=overlay->pitches[0];
-			if(odd_line) {
-				/* Increment on odd lines */
-				U+=overlay->pitches[uplane];
-				V+=overlay->pitches[vplane];
-			}
-			else {
-				memset(U, yuvc[1], uvlen);
-				memset(V, yuvc[2], uvlen);
-			}
-			odd_line = !odd_line;
-		}
-	}
-	sdl.UnlockYUVOverlay(overlay);
-	return;
-packed:
-	sdl.LockYUVOverlay(overlay);
-	{
-		int x,y;
-		Uint32 colour;
-		Uint8 *colour_array=(Uint8 *)&colour;
-		Uint32 *offset;
-
-		colour_array[y0pack]=yuvc[0];
-		colour_array[y1pack]=yuvc[0];
-		colour_array[u0pack]=yuvc[1];
-		colour_array[v0pack]=yuvc[2];
-		offset=(Uint32 *)(overlay->pixels[0]+overlay->pitches[0]*(r->y));
-		offset+=(r->x>>1);
-		for(y=0; y<r->h; y++)
-		{
-			for(x=0; x<r->w; x+=2)
-				offset[x>>1]=colour;
-			offset+=overlay->pitches[0]>>2;
-		}
-	}
-	sdl.UnlockYUVOverlay(overlay);
-	return;
-}
+static int sdl_video_event_thread(void *data);
 
 static void sdl_user_func(int func, ...)
 {
@@ -450,15 +315,6 @@ static int sdl_user_func_ret(int func, ...)
 				va_end(argptr);
 				return -1;
 		}
-		/*
-		 * This is needed for lost event detection.
-		 * Lost events only occur on SYSWMEVENT which is what
-		 * we need for copy/paste on X11.
-		 * This hack can be removed for SDL2
-		 */
-		if(sdl_x11available && sdl_using_x11)
-			if((rv = sdl.SemWaitTimeout(sdl_ufunc_rec, 2000))!=0)
-				continue;
 		rv = sdl.SemWait(sdl_ufunc_ret);
 		if(rv==0)
 			break;
@@ -468,9 +324,9 @@ static int sdl_user_func_ret(int func, ...)
 	return(sdl_ufunc_retval);
 }
 
-static void exit_sdl_con(void)
+void exit_sdl_con(void)
 {
-	sdl_user_func_ret(SDL_USEREVENT_QUIT);
+	sdl_user_func(SDL_USEREVENT_QUIT);
 }
 
 void sdl_copytext(const char *text, size_t buflen)
@@ -597,6 +453,15 @@ static int sdl_init_mode(int mode)
 {
 	int oldcols;
 
+	if (mode != CIOLIB_MODE_CUSTOM) {
+		pthread_mutex_lock(&vstatlock);
+		if (mode == vstat.mode) {
+			pthread_mutex_unlock(&vstatlock);
+			return 0;
+		}
+		pthread_mutex_unlock(&vstatlock);
+	}
+
 	oldcols = cvstat.cols;
 
 	sdl_user_func(SDL_USEREVENT_FLUSH);
@@ -604,16 +469,11 @@ static int sdl_init_mode(int mode)
 	pthread_mutex_lock(&blinker_lock);
 	pthread_mutex_lock(&vstatlock);
 	bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height);
-	if(yuv.enabled)
-		vstat.scaling = 2;
-	/* Deal with 40 col doubling */
-	else {
-		if(oldcols != vstat.cols) {
-			if(oldcols == 40)
-				vstat.scaling /= 2;
-			if(vstat.cols == 40)
-				vstat.scaling *= 2;
-		}
+	if(oldcols != vstat.cols) {
+		if(oldcols == 40)
+			vstat.scaling /= 2;
+		if(vstat.cols == 40)
+			vstat.scaling *= 2;
 	}
 	if(vstat.scaling < 1)
 		vstat.scaling = 1;
@@ -637,39 +497,14 @@ int sdl_init(int mode)
 	const char *libnames[2]={"X11", NULL};
 #endif
 
-	if(init_sdl_video()) {
-		fprintf(stderr, "SDL Video Init Failed\n");
-		return(-1);
-	}
-
 	bitmap_drv_init(sdl_drawrect, sdl_flush);
-	sdl.mutexP(bitmap_init_mutex);
-	bitmap_initialized=1;
-	sdl.mutexV(bitmap_init_mutex);
 
 	if(mode==CIOLIB_MODE_SDL_FULLSCREEN)
 		fullscreen=1;
-	if(mode==CIOLIB_MODE_SDL_YUV)
-		yuv.enabled=1;
-	if(mode==CIOLIB_MODE_SDL_YUV_FULLSCREEN) {
-		yuv.enabled=1;
-		fullscreen=1;
-	}
-#if (SDL_MAJOR_VERSION > 1) || (SDL_MINOR_VERSION > 2) || (SDL_PATCHLEVEL > 9)
-	if(yuv.enabled) {
-		const SDL_version	*linked=sdl.Linked_Version();
-		if(linked->major > 1 || linked->minor > 2 || linked->patch > 9) {
-			yuv.screen_width=sdl.initial_videoinfo.current_w;
-			yuv.screen_height=sdl.initial_videoinfo.current_h;
-		}
-	}
-#endif
-	sdl_init_mode(3);
-	if(yuv.enabled && yuv.overlay==NULL) {
-		fprintf(stderr, "YUV Enabled, but overlay is NULL\n");
-		sdl_init_good=0;
-	}
+	// Needs to be *after* bitmap_drv_init()
+	sdl.CreateThread(sdl_video_event_thread, NULL);
 	sdl_user_func_ret(SDL_USEREVENT_INIT);
+	sdl_init_mode(3);
 
 	if(sdl_init_good) {
 		cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
@@ -716,13 +551,12 @@ int sdl_init(int mode)
 		return(0);
 	}
 
+	sdl_user_func_ret(SDL_USEREVENT_QUIT);
 	return(-1);
 }
 
 void sdl_setscaling(int new_value)
 {
-	if (yuv.enabled)
-		return;
 	pthread_mutex_lock(&vstatlock);
 	cvstat.scaling = vstat.scaling = new_value;
 	pthread_mutex_unlock(&vstatlock);
@@ -730,8 +564,6 @@ void sdl_setscaling(int new_value)
 
 int sdl_getscaling(void)
 {
-	if (yuv.enabled)
-		return 1;
 	return cvstat.scaling;
 }
 
@@ -810,11 +642,14 @@ int sdl_hidemouse(void)
 
 int sdl_get_window_info(int *width, int *height, int *xpos, int *ypos)
 {
+	int ww, wh;
+
 	sdl.mutexP(win_mutex);
+	sdl.GetWindowSize(win, &ww, &wh);
 	if(width)
-		*width=win->h;
+		*width=ww;
 	if(height)
-		*height=win->h;
+		*height=wh;
 	if(xpos)
 		*xpos=-1;
 	if(ypos)
@@ -828,15 +663,14 @@ static void setup_surfaces(void)
 {
 	int		char_width;
 	int		char_height;
-	int		flags=SDL_HWSURFACE|SDL_ANYFORMAT;
-	SDL_Surface	*tmp_rect;
+	int		flags=0;
 	SDL_Event	ev;
 	int charwidth, charheight, cols, scaling, rows, vmultiplier;
 
 	if(fullscreen)
-		flags |= SDL_FULLSCREEN;
+		flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
 	else
-		flags |= SDL_RESIZABLE;
+		flags |= SDL_WINDOW_RESIZABLE;
 
 	sdl.mutexP(win_mutex);
 	charwidth = cvstat.charwidth;
@@ -849,110 +683,19 @@ static void setup_surfaces(void)
 	char_width=charwidth*cols*scaling;
 	char_height=charheight*rows*scaling*vmultiplier;
 
-	if(yuv.enabled) {
-		if(!yuv.win_width)
-			yuv.win_width=charwidth*cols;
-		if(!yuv.win_height)
-			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
-			win=sdl.SetVideoMode(yuv.win_width,yuv.win_height,0,flags);
-	}
-	else {
-		if (win != NULL) {
-			if (!yuv.enabled) {
-				if (new_rect->w != char_width || new_rect->h != char_height) {
-					SDL_Rect	upd_rect;
-					upd_rect.x = 0;
-					upd_rect.y = 0;
-					sdl.mutexP(newrect_mutex);
-					upd_rect.w=new_rect->w;
-					upd_rect.h=new_rect->h;
-					sdl.FillRect(new_rect, &upd_rect, sdl.MapRGB(win->format, 0, 0, 0));
-					sdl.BlitSurface(new_rect, &upd_rect, win, &upd_rect);
-					sdl.mutexV(newrect_mutex);
-					sdl.Flip(win);
-				}
-			}
+	if (win == NULL) {
+		// SDL2: This is slow sometimes... not sure why.
+		if (sdl.CreateWindowAndRenderer(char_width, char_height, flags, &win, &renderer) == 0) {
+			sdl.RenderClear(renderer);
+			texture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, charwidth*cols, charheight*rows);
+		}
+		else {
+			win = NULL;
+			renderer = NULL;
 		}
-		win=sdl.SetVideoMode(char_width,char_height,0,flags);
-	}
-
-#if !defined(NO_X) && defined(__unix__)
-	if(sdl_x11available && sdl_using_x11) {
-		XEvent respond;
-		SDL_SysWMinfo	wmi;
-		SDL_VERSION(&(wmi.version));
-		sdl.GetWMInfo(&wmi);
-		respond.type=ConfigureNotify;
-		respond.xconfigure.height = win->h;
-		respond.xconfigure.width = win->w;
-		sdl_x11.XSendEvent(wmi.info.x11.display,wmi.info.x11.window,0,0,&respond);
 	}
-#endif
 
 	if(win!=NULL) {
-		sdl.mutexP(newrect_mutex);
-		if(new_rect)
-			sdl.FreeSurface(new_rect);
-		new_rect=NULL;
-		tmp_rect=sdl.CreateRGBSurface(SDL_HWSURFACE
-				, char_width
-				, char_height
-				, 32, 0, 0, 0, 0);
-		if(tmp_rect) {
-			if(yuv.enabled) {
-				new_rect=tmp_rect;
-			}
-			else {
-				new_rect=sdl.DisplayFormat(tmp_rect);
-				sdl.FreeSurface(tmp_rect);
-			}
-		}
-		sdl.mutexV(newrect_mutex);
-		if(yuv.enabled) {
-			if(yuv.overlay)
-				sdl.FreeYUVOverlay(yuv.overlay);
-			if(yuv.best_format==0) {
-				yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_YV12_OVERLAY, win);
-				if(yuv.overlay)
-					yuv.best_format=yuv.overlay->format;
-				if(yuv.overlay==NULL || !yuv.overlay->hw_overlay) {
-					if (yuv.overlay)
-						sdl.FreeYUVOverlay(yuv.overlay);
-					yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_YUY2_OVERLAY, win);
-					if(yuv.overlay)
-						yuv.best_format=yuv.overlay->format;
-					if(yuv.overlay==NULL || !yuv.overlay->hw_overlay) {
-						if (yuv.overlay)
-							sdl.FreeYUVOverlay(yuv.overlay);
-						yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_YVYU_OVERLAY, win);
-						if(yuv.overlay)
-							yuv.best_format=yuv.overlay->format;
-						if(yuv.overlay==NULL || !yuv.overlay->hw_overlay) {
-							if (yuv.overlay)
-								sdl.FreeYUVOverlay(yuv.overlay);
-							yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_UYVY_OVERLAY, win);
-							if(yuv.overlay)
-								yuv.best_format=yuv.overlay->format;
-							if(yuv.overlay==NULL || !yuv.overlay->hw_overlay) {
-								if (yuv.overlay)
-									sdl.FreeYUVOverlay(yuv.overlay);
-								yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_IYUV_OVERLAY, win);
-								if(yuv.overlay)
-									yuv.best_format=yuv.overlay->format;
-							}
-						}
-					}
-				}
-				if(yuv.overlay)
-					sdl.FreeYUVOverlay(yuv.overlay);
-			}
-			yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, yuv.best_format, win);
-		}
-		sdl.mutexP(newrect_mutex);
-		sdl.mutexV(newrect_mutex);
 		bitmap_drv_request_pixels();
 	}
 	else if(sdl_init_good) {
@@ -968,10 +711,7 @@ static void sdl_add_key(unsigned int keyval)
 {
 	if(keyval==0xa600) {
 		fullscreen=!fullscreen;
-		if(yuv.enabled)
-			cio_api.mode=fullscreen?CIOLIB_MODE_SDL_YUV_FULLSCREEN:CIOLIB_MODE_SDL_YUV;
-		else
-			cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
+		cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
 		setup_surfaces();
 		return;
 	}
@@ -1266,14 +1006,14 @@ static unsigned int cp437_convert(unsigned int unicode)
 }
 
 /* Called from event thread only */
-static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, unsigned int unicode)
+static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod)
 {
 	int expect;
 	int i;
 
 #ifdef __DARWIN__
-	if(unicode==0x7f && !(mod & KMOD_CTRL)) {
-		unicode=0x08;
+	if(keysym==0x7f && !(mod & KMOD_CTRL)) {
+		keysym=0x08;
 		keysym=SDLK_BACKSPACE;
 	}
 #endif
@@ -1281,9 +1021,10 @@ static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, uns
 	/*
 	 * No Unicode translation available.
 	 * Or there *IS* an SDL keysym.
-	 * Or ALT (Meta) pressed
+	 * Or ALT (GUI) pressed
 	 */
-	if((!unicode) || (keysym > SDLK_FIRST && keysym < SDLK_LAST) || (mod & (KMOD_META|KMOD_ALT))) {
+	// SDL2: This needs to be replaced with... betterness.
+	if((keysym > SDLK_UNKNOWN) || (mod & (KMOD_GUI|KMOD_ALT))) {
 
 		/* Find the SDL keysym */
 		for(i=0;sdl_keyval[i].keysym;i++) {
@@ -1315,23 +1056,23 @@ static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, uns
 				 * Now handle the ALT case so that expect will
 				 * be what we expect to return
 				 */
-				if(mod & (KMOD_META|KMOD_ALT)) {
+				if(mod & (KMOD_GUI|KMOD_ALT)) {
 
 					/* Yes, this is a "normal" ALT combo */
-					if(unicode==expect || unicode == 0)
+					if(keysym==expect || keysym == 0)
 						return(sdl_keyval[i].alt);
 
 					/* AltGr apparently... translate unicode or give up */
-					return(cp437_convert(unicode));
+					return(cp437_convert(keysym));
 				}
 
 				/*
 				 * If the keysym is a keypad one
 				 * AND numlock is locked
-				 * AND none of Control, Shift, ALT, or Meta are pressed
+				 * AND none of Control, Shift, ALT, or GUI are pressed
 				 */
-				if(keysym >= SDLK_KP0 && keysym <= SDLK_KP_EQUALS && 
-						(!(mod & (KMOD_CTRL|KMOD_SHIFT|KMOD_ALT|KMOD_META) ))) {
+				if(keysym >= SDLK_KP_0 && keysym <= SDLK_KP_EQUALS && 
+						(!(mod & (KMOD_CTRL|KMOD_SHIFT|KMOD_ALT|KMOD_GUI) ))) {
 #if defined(_WIN32)
 					/*
 					 * Apparently, Win32 SDL doesn't interpret keypad with numlock...
@@ -1345,25 +1086,25 @@ static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, uns
 #endif
 					if (mod & KMOD_NUM) {
 						switch(keysym) {
-							case SDLK_KP0:
+							case SDLK_KP_0:
 								return('0');
-							case SDLK_KP1:
+							case SDLK_KP_1:
 								return('1');
-							case SDLK_KP2:
+							case SDLK_KP_2:
 								return('2');
-							case SDLK_KP3:
+							case SDLK_KP_3:
 								return('3');
-							case SDLK_KP4:
+							case SDLK_KP_4:
 								return('4');
-							case SDLK_KP5:
+							case SDLK_KP_5:
 								return('5');
-							case SDLK_KP6:
+							case SDLK_KP_6:
 								return('6');
-							case SDLK_KP7:
+							case SDLK_KP_7:
 								return('7');
-							case SDLK_KP8:
+							case SDLK_KP_8:
 								return('8');
-							case SDLK_KP9:
+							case SDLK_KP_9:
 								return('9');
 							case SDLK_KP_PERIOD:
 								return('.');
@@ -1396,7 +1137,7 @@ static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, uns
 				 * no other data to use.  This is apparently
 				 * never true on OS X.
 				 */
-				if(!unicode)
+				if(!keysym)
 					return(expect);
 
 				/*
@@ -1404,7 +1145,7 @@ static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, uns
 				 * unicode mapping.  If we can coerce it into CP437, we will.
 				 * If we can't, just give up.
 				 */
-				return(cp437_convert(unicode));
+				return(cp437_convert(expect));
 			}
 		}
 	}
@@ -1412,8 +1153,8 @@ static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, uns
 	 * Well, we can't find it in our table...
 	 * If there's a unicode character, use that if possible.
 	 */
-	if(unicode)
-		return(cp437_convert(unicode));
+	if(keysym)
+		return(cp437_convert(keysym));
 
 	/*
 	 * No unicode... perhaps it's ASCII?
@@ -1424,7 +1165,7 @@ static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, uns
 	 * we're not going to trust the keysym
 	 * value since we can't.
 	 */
-	if(keysym <= 127 && !(mod & (KMOD_META|KMOD_ALT|KMOD_CTRL|KMOD_SHIFT)))
+	if(keysym <= 127 && !(mod & (KMOD_GUI|KMOD_ALT|KMOD_CTRL|KMOD_SHIFT)))
 		return(keysym);
 
 	/* Give up.  It's not working out for us. */
@@ -1446,33 +1187,16 @@ static int win_to_text_xpos(int winpos)
 {
 	int ret;
 
-	if(yuv.enabled) {
-
-		sdl.mutexP(win_mutex);
-		ret = winpos*cvstat.cols/win->w+1;
-		sdl.mutexV(win_mutex);
-		return(ret);
-	}
-	else {
-		ret = winpos/(cvstat.charwidth*cvstat.scaling)+1;
-		return ret;
-	}
+	ret = winpos/(cvstat.charwidth*cvstat.scaling)+1;
+	return ret;
 }
 
 static int win_to_text_ypos(int winpos)
 {
 	int ret;
 
-	if(yuv.enabled) {
-		sdl.mutexP(win_mutex);
-		ret = winpos*cvstat.rows/win->h+1;
-		sdl.mutexV(win_mutex);
-		return(ret);
-	}
-	else {
-		ret = winpos/(cvstat.charheight*cvstat.scaling*cvstat.vmultiplier)+1;
-		return ret;
-	}
+	ret = winpos/(cvstat.charheight*cvstat.scaling*cvstat.vmultiplier)+1;
+	return ret;
 }
 
 static int sdl_video_event_thread(void *data)
@@ -1480,441 +1204,363 @@ static int sdl_video_event_thread(void *data)
 	SDL_Event	ev;
 	int			new_scaling = -1;
 	int			old_scaling;
-	SDL_Rect	upd_rect;
 
-	while(1) {
-		sdl.mutexP(bitmap_init_mutex);
-		if(bitmap_initialized) {
-			sdl.mutexV(bitmap_init_mutex);
-			break;
-		}
-		sdl.mutexV(bitmap_init_mutex);
-		SLEEP(1);
-	}
 	old_scaling = cvstat.scaling;
-	
-	if(!init_sdl_video()) {
-		char	driver[16];
-		if(sdl.VideoDriverName(driver, sizeof(driver))!=NULL) {
+
+	char	*driver;
+	if((driver = sdl.GetCurrentVideoDriver())!=NULL) {
 #if defined(_WIN32)
-			if(!strcmp(driver,"directx"))
-				sdl_using_directx=TRUE;
+		if(!strcmp(driver,"directx"))
+			sdl_using_directx=TRUE;
 #else
-			sdl_using_directx=FALSE;
+		sdl_using_directx=FALSE;
 #endif
 #if (defined(__MACH__) && defined(__APPLE__))
-			if(!strcmp(driver,"Quartz"))
-				sdl_using_quartz=TRUE;
+		if(!strcmp(driver,"Quartz"))
+			sdl_using_quartz=TRUE;
 #else
-			sdl_using_quartz=FALSE;
+		sdl_using_quartz=FALSE;
 #endif
 #if !defined(NO_X) && defined(__unix__)
-			if(!strcmp(driver,"x11"))
-				sdl_using_x11=TRUE;
-			if(!strcmp(driver,"dga"))
-				sdl_using_x11=TRUE;
+		if(!strcmp(driver,"x11"))
+			sdl_using_x11=TRUE;
+		if(!strcmp(driver,"dga"))
+			sdl_using_x11=TRUE;
 #else
-			sdl_using_x11=FALSE;
+		sdl_using_x11=FALSE;
 #endif
-		}
+	}
 
-		while(1) {
-			if(sdl.PollEvent(&ev)!=1) {
-				if (new_scaling != -1 || cvstat.scaling != old_scaling) {
-					if (new_scaling == -1)
-						new_scaling = cvstat.scaling;
-					sdl_setscaling(new_scaling);
-					new_scaling = -1;
-					if(cvstat.scaling < 1)
-						sdl_setscaling(1);
-					setup_surfaces();
-					old_scaling = cvstat.scaling;
-				}
-				SLEEP(1);
+	while(1) {
+		if(sdl.WaitEventTimeout(&ev, 1)!=1) {
+			if (new_scaling != -1 || cvstat.scaling != old_scaling) {
+				if (new_scaling == -1)
+					new_scaling = cvstat.scaling;
+				sdl_setscaling(new_scaling);
+				new_scaling = -1;
+				if(cvstat.scaling < 1)
+					sdl_setscaling(1);
+				setup_surfaces();
+				old_scaling = cvstat.scaling;
 			}
-			else {
-				switch (ev.type) {
-					case SDL_ACTIVEEVENT:		/* Focus change */
-						break;
-					case SDL_KEYDOWN:			/* Keypress */
-						sdl_add_key(sdl_get_char_code(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode));
+		}
+		else {
+			switch (ev.type) {
+				case SDL_KEYDOWN:			/* Keypress */
+					sdl_add_key(sdl_get_char_code(ev.key.keysym.sym, ev.key.keysym.mod));
+					break;
+				case SDL_KEYUP:				/* Ignored (handled in KEYDOWN event) */
+					break;
+				case SDL_MOUSEMOTION:
+					if(!ciolib_mouse_initialized)
 						break;
-					case SDL_KEYUP:				/* Ignored (handled in KEYDOWN event) */
+					ciomouse_gotevent(CIOLIB_MOUSE_MOVE,win_to_text_xpos(ev.motion.x),win_to_text_ypos(ev.motion.y));
+					break;
+				case SDL_MOUSEBUTTONDOWN:
+					if(!ciolib_mouse_initialized)
 						break;
-					case SDL_MOUSEMOTION:
-						if(!ciolib_mouse_initialized)
+					switch(ev.button.button) {
+						case SDL_BUTTON_LEFT:
+							ciomouse_gotevent(CIOLIB_BUTTON_PRESS(1),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
 							break;
-						ciomouse_gotevent(CIOLIB_MOUSE_MOVE,win_to_text_xpos(ev.motion.x),win_to_text_ypos(ev.motion.y));
-						break;
-					case SDL_MOUSEBUTTONDOWN:
-						if(!ciolib_mouse_initialized)
+						case SDL_BUTTON_MIDDLE:
+							ciomouse_gotevent(CIOLIB_BUTTON_PRESS(2),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
 							break;
-						switch(ev.button.button) {
-							case SDL_BUTTON_LEFT:
-								ciomouse_gotevent(CIOLIB_BUTTON_PRESS(1),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
-								break;
-							case SDL_BUTTON_MIDDLE:
-								ciomouse_gotevent(CIOLIB_BUTTON_PRESS(2),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
-								break;
-							case SDL_BUTTON_RIGHT:
-								ciomouse_gotevent(CIOLIB_BUTTON_PRESS(3),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
-								break;
-						}
-						break;
-					case SDL_MOUSEBUTTONUP:
-						if(!ciolib_mouse_initialized)
+						case SDL_BUTTON_RIGHT:
+							ciomouse_gotevent(CIOLIB_BUTTON_PRESS(3),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
 							break;
-						switch(ev.button.button) {
-							case SDL_BUTTON_LEFT:
-								ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(1),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
-								break;
-							case SDL_BUTTON_MIDDLE:
-								ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(2),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
-								break;
-							case SDL_BUTTON_RIGHT:
-								ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(3),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
-								break;
-						}
-						break;
-					case SDL_QUIT:
-						if (ciolib_reaper)
-							exit(0);
-						else
-							sdl_add_key(CIO_KEY_QUIT);
-						break;
-					case SDL_VIDEORESIZE:
-						if(ev.resize.w > 0 && ev.resize.h > 0) {
-							if(yuv.enabled) {
-								yuv.win_width=ev.resize.w;
-								yuv.win_height=ev.resize.h;
-								new_scaling = 2;
-							}
-							else {
-								new_scaling = (int)(ev.resize.w/(cvstat.charwidth*cvstat.cols));
-							}
-						}
+					}
+					break;
+				case SDL_MOUSEBUTTONUP:
+					if(!ciolib_mouse_initialized)
 						break;
-					case SDL_VIDEOEXPOSE:
-						{
-							if(yuv.enabled) {
-								bitmap_drv_request_pixels();
+					switch(ev.button.button) {
+						case SDL_BUTTON_LEFT:
+							ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(1),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
+							break;
+						case SDL_BUTTON_MIDDLE:
+							ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(2),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
+							break;
+						case SDL_BUTTON_RIGHT:
+							ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(3),win_to_text_xpos(ev.button.x),win_to_text_ypos(ev.button.y));
+							break;
+					}
+					break;
+				case SDL_QUIT:
+					/*
+					 * SDL2: Do we still need the reaper?
+					 * This is what exit()s programs when the
+					 * X is hit.
+					 */
+					if (ciolib_reaper)
+						exit(0);
+					else
+						sdl_add_key(CIO_KEY_QUIT);
+					break;
+				case SDL_WINDOWEVENT:
+					switch(ev.window.event) {
+						case SDL_WINDOWEVENT_SIZE_CHANGED:
+							// SDL2: User resized window
+							break;
+						case SDL_WINDOWEVENT_RESIZED:
+							// SDL2: Something resized window
+							if(ev.window.data1 > 0 && ev.window.data2 > 0) {
+								new_scaling = (int)(ev.window.data1/(cvstat.charwidth*cvstat.cols));
 							}
-							else {
-								upd_rect.x=0;
-								upd_rect.y=0;
+							break;
+						case SDL_WINDOWEVENT_EXPOSED:
+							{
 								sdl.mutexP(win_mutex);
-								sdl.mutexP(newrect_mutex);
-								upd_rect.w=new_rect->w;
-								upd_rect.h=new_rect->h;
-								sdl.BlitSurface(new_rect, &upd_rect, win, &upd_rect);
-								sdl.mutexV(newrect_mutex);
-								sdl.Flip(win);
+								sdl.RenderCopy(renderer, texture, NULL, NULL);
+								sdl.RenderPresent(renderer);
 								sdl.mutexV(win_mutex);
 							}
-						}
-						break;
-					case SDL_USEREVENT: {
-						struct rectlist *list;
-						struct rectlist *list_tail;
-						struct rectlist *old_next;
-						/* Tell SDL to do various stuff... */
-						if (ev.user.code != SDL_USEREVENT_FLUSH)
-							if(sdl_x11available && sdl_using_x11)
-								sdl.SemPost(sdl_ufunc_rec);
-						switch(ev.user.code) {
-							case SDL_USEREVENT_QUIT:
-								sdl_ufunc_retval=0;
-								sdl.SemPost(sdl_ufunc_ret);
-								return(0);
-							case SDL_USEREVENT_FLUSH:
+							break;
+					}
+					break;
+				case SDL_USEREVENT: {
+					struct rectlist *list;
+					struct rectlist *list_tail;
+					struct rectlist *old_next;
+					/* Tell SDL to do various stuff... */
+					if (ev.user.code != SDL_USEREVENT_FLUSH)
+						if(sdl_x11available && sdl_using_x11)
+							sdl.SemPost(sdl_ufunc_rec);
+					switch(ev.user.code) {
+						case SDL_USEREVENT_QUIT:
+							sdl_ufunc_retval=0;
+							sdl.SemPost(sdl_ufunc_ret);
+							return(0);
+						case SDL_USEREVENT_FLUSH:
+							sdl.mutexP(win_mutex);
+							if (win != NULL) {
 								sdl.mutexP(sdl_headlock);
 								list = update_list;
 								update_list = update_list_tail = NULL;
 								sdl.mutexV(sdl_headlock);
-								/* Old SDL_USEREVENT_UPDATERECT */
 								for (; list; list = old_next) {
-									SDL_Rect r;
-									int x,y,offset;
-									int scaling, vmultiplier;
+									SDL_Rect src;
 
 									old_next = list->next;
-									sdl.mutexP(win_mutex);
-									if(!win) {
-										sdl.mutexV(win_mutex);
-										/* Put it back at the start of the list... */
-										sdl.mutexP(sdl_headlock);
-										for (list_tail = list; list_tail->next; list_tail = list_tail->next);
-										list_tail->next = update_list;
-										update_list = list;
-										sdl.mutexV(sdl_headlock);
-										break;
+									if (list->next == NULL) {
+										sdl.UpdateTexture(texture, NULL, list->data, list->rect.width * sizeof(uint32_t));
+										src.x = 0;
+										src.y = 0;
+										src.w = list->rect.width;
+										src.h = list->rect.height;
+										sdl.RenderCopy(renderer, texture, &src, NULL);
 									}
-									sdl.mutexP(newrect_mutex);
-									scaling = cvstat.scaling;
-									vmultiplier = cvstat.vmultiplier;
-									r.w=scaling;
-									r.h=scaling*vmultiplier;
-									for(y=0; y<list->rect.height; y++) {
-										offset=y*list->rect.width;
-										r.y=(list->rect.y+y)*scaling*vmultiplier;
-										for(x=0; x<list->rect.width; x++) {
-											r.x=(list->rect.x+x)*scaling;
-											if(yuv.enabled) {
-												Uint8 yuvc[3];
-
-												RGBtoYUV(list->data[offset] >> 16 & 0xff, list->data[offset] >> 8 & 0xff, list->data[offset] & 0xff, yuvc);
-												yuv_fillrect(yuv.overlay, &r, yuvc);
-											}
-											else {
-												sdl.FillRect(new_rect, &r, sdl.MapRGB(win->format, list->data[offset] >> 16 & 0xff, list->data[offset] >> 8 & 0xff, list->data[offset] & 0xff));
-											}
-											offset++;
-										}
-									}
-									if(!yuv.enabled) {
-										upd_rect.x=list->rect.x*scaling;
-										upd_rect.y=list->rect.y*scaling*vmultiplier;
-										upd_rect.w=list->rect.width*scaling;
-										upd_rect.h=list->rect.height*scaling*vmultiplier;
-										sdl.BlitSurface(new_rect, &upd_rect, win, &upd_rect);
-									}
-									sdl.mutexV(newrect_mutex);
-									sdl.mutexV(win_mutex);
 									bitmap_drv_free_rect(list);
 								}
-
-								/* Old flush function */
-								sdl.mutexP(win_mutex);
-								sdl.mutexP(newrect_mutex);
-								if(win && new_rect) {
-									if(yuv.enabled) {
-										if(yuv.overlay && yuv.changed) {
-											SDL_Rect	dstrect;
-	
-											yuv.changed=0;
-											dstrect.w=win->w;
-											dstrect.h=win->h;
-											dstrect.x=0;
-											dstrect.y=0;
-											sdl.DisplayYUVOverlay(yuv.overlay, &dstrect);
-										}
-									}
-									else {
-										sdl.Flip(win);
-									}
+								sdl.RenderPresent(renderer);
+							}
+							sdl.mutexV(win_mutex);
+							break;
+						case SDL_USEREVENT_SETNAME:
+							sdl.SetWindowTitle(win, (char *)ev.user.data1);
+							free(ev.user.data1);
+							break;
+						case SDL_USEREVENT_SETICON:
+							if(sdl_icon != NULL)
+								sdl.FreeSurface(sdl_icon);
+							sdl_icon=sdl.CreateRGBSurfaceFrom(ev.user.data1
+									, *(unsigned long *)ev.user.data2
+									, *(unsigned long *)ev.user.data2
+									, 32
+									, *(unsigned long *)ev.user.data2*4
+									, *(DWORD *)"\377\0\0\0"
+									, *(DWORD *)"\0\377\0\0"
+									, *(DWORD *)"\0\0\377\0"
+									, *(DWORD *)"\0\0\0\377"
+							);
+							sdl.SetWindowIcon(win, sdl_icon);
+							free(ev.user.data2);
+							break;
+						case SDL_USEREVENT_SETTITLE:
+							sdl.SetWindowTitle(win, (char *)ev.user.data1);
+							free(ev.user.data1);
+							break;
+						case SDL_USEREVENT_SETVIDMODE:
+							new_scaling = -1;
+							old_scaling = cvstat.scaling;
+							setup_surfaces();
+							sdl_ufunc_retval=0;
+							sdl.SemPost(sdl_ufunc_ret);
+							break;
+						case SDL_USEREVENT_HIDEMOUSE:
+							sdl.ShowCursor(SDL_DISABLE);
+							break;
+						case SDL_USEREVENT_SHOWMOUSE:
+							sdl.ShowCursor(SDL_ENABLE);
+							break;
+						case SDL_USEREVENT_INIT:
+							if(!sdl_init_good) {
+								if(sdl.WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO) {
+									sdl.mutexP(win_mutex);
+									mouse_thread=sdl.CreateThread(sdl_mouse_thread, NULL);
+									sdl_init_good=1;
+									sdl.mutexV(win_mutex);
 								}
-								sdl.mutexP(newrect_mutex);
-								sdl.mutexV(win_mutex);
-								break;
-							case SDL_USEREVENT_SETNAME:
-								sdl.WM_SetCaption((char *)ev.user.data1,(char *)ev.user.data1);
-								free(ev.user.data1);
-								break;
-							case SDL_USEREVENT_SETICON:
-								if(sdl_icon != NULL)
-									sdl.FreeSurface(sdl_icon);
-								sdl_icon=sdl.CreateRGBSurfaceFrom(ev.user.data1
-										, *(unsigned long *)ev.user.data2
-										, *(unsigned long *)ev.user.data2
-										, 32
-										, *(unsigned long *)ev.user.data2*4
-										, *(DWORD *)"\377\0\0\0"
-										, *(DWORD *)"\0\377\0\0"
-										, *(DWORD *)"\0\0\377\0"
-										, *(DWORD *)"\0\0\0\377"
-								);
-								sdl.WM_SetIcon(sdl_icon,NULL);
-								free(ev.user.data2);
-								break;
-							case SDL_USEREVENT_SETTITLE:
-								sdl.WM_SetCaption((char *)ev.user.data1,NULL);
-								free(ev.user.data1);
-								break;
-							case SDL_USEREVENT_SETVIDMODE:
-								new_scaling = -1;
-								old_scaling = cvstat.scaling;
-								setup_surfaces();
-								sdl_ufunc_retval=0;
-								sdl.SemPost(sdl_ufunc_ret);
-								break;
-							case SDL_USEREVENT_HIDEMOUSE:
-								sdl.ShowCursor(SDL_DISABLE);
-								break;
-							case SDL_USEREVENT_SHOWMOUSE:
-								sdl.ShowCursor(SDL_ENABLE);
-								break;
-							case SDL_USEREVENT_INIT:
-								if(!sdl_init_good) {
-									if(sdl.WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO) {
-										sdl.mutexP(win_mutex);
-										if(win != NULL) {
-											sdl.EnableUNICODE(1);
-											sdl.EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
-											mouse_thread=sdl.CreateThread(sdl_mouse_thread, NULL);
-											sdl_init_good=1;
-										}
-										sdl.mutexV(win_mutex);
+							}
+							sdl_ufunc_retval=0;
+							sdl.SemPost(sdl_ufunc_ret);
+							break;
+						case SDL_USEREVENT_COPY:
+#if !defined(NO_X) && defined(__unix__) && defined(SDL_VIDEO_DRIVER_X11)
+							if(sdl_x11available && sdl_using_x11) {
+								SDL_SysWMinfo	wmi;
+
+								SDL_VERSION(&(wmi.version));
+								sdl.GetWindowWMInfo(win, &wmi);
+								sdl.EventState(SDL_SYSWMEVENT, SDL_ENABLE);
+								copy_needs_events = 1;
+								sdl_x11.XSetSelectionOwner(wmi.info.x11.display, CONSOLE_CLIPBOARD, wmi.info.x11.window, CurrentTime);
+							}
+#endif
+							break;
+						case SDL_USEREVENT_PASTE:
+#if !defined(NO_X) && defined(__unix__) && defined(SDL_VIDEO_DRIVER_X11)
+							if(sdl_x11available && sdl_using_x11) {
+								Window sowner=None;
+								SDL_SysWMinfo	wmi;
+
+								SDL_VERSION(&(wmi.version));
+								sdl.GetWindowWMInfo(win, &wmi);
+
+								paste_needs_events = 1;
+								sdl.EventState(SDL_SYSWMEVENT, SDL_ENABLE);
+								sowner=sdl_x11.XGetSelectionOwner(wmi.info.x11.display, CONSOLE_CLIPBOARD);
+								if(sowner==wmi.info.x11.window) {
+									/* Get your own primary selection */
+									if(sdl_copybuf==NULL) {
+										FREE_AND_NULL(sdl_pastebuf);
 									}
+									else
+										sdl_pastebuf=(char *)malloc(strlen(sdl_copybuf)+1);
+									if(sdl_pastebuf!=NULL)
+										strcpy(sdl_pastebuf,sdl_copybuf);
+									/* Set paste buffer */
+									sdl.SemPost(sdl_pastebuf_set);
+									sdl.SemWait(sdl_pastebuf_copied);
+									FREE_AND_NULL(sdl_pastebuf);
+									paste_needs_events = 0;
+									if (!copy_needs_events)
+										sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
 								}
-								sdl_ufunc_retval=0;
-								sdl.SemPost(sdl_ufunc_ret);
-								break;
-							case SDL_USEREVENT_COPY:
-#if !defined(NO_X) && defined(__unix__) && defined(SDL_VIDEO_DRIVER_X11)
-								if(sdl_x11available && sdl_using_x11) {
-									SDL_SysWMinfo	wmi;
-
-									SDL_VERSION(&(wmi.version));
-									sdl.GetWMInfo(&wmi);
-									sdl.EventState(SDL_SYSWMEVENT, SDL_ENABLE);
-									copy_needs_events = 1;
-									sdl_x11.XSetSelectionOwner(wmi.info.x11.display, CONSOLE_CLIPBOARD, wmi.info.x11.window, CurrentTime);
+								else if(sowner!=None) {
+									sdl_x11.XConvertSelection(wmi.info.x11.display, CONSOLE_CLIPBOARD, XA_STRING, XA_STRING, wmi.info.x11.window, CurrentTime);
+								}
+								else {
+									/* Set paste buffer */
+									FREE_AND_NULL(sdl_pastebuf);
+									sdl.SemPost(sdl_pastebuf_set);
+									sdl.SemWait(sdl_pastebuf_copied);
+									paste_needs_events = 0;
+									if (!copy_needs_events)
+										sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
 								}
+							}
 #endif
-								break;
-							case SDL_USEREVENT_PASTE:
+							break;
+					}
+					break;
+				}
+				case SDL_SYSWMEVENT:			/* ToDo... This is where Copy/Paste needs doing */
+				// SDL2: There's a better way...
 #if !defined(NO_X) && defined(__unix__) && defined(SDL_VIDEO_DRIVER_X11)
-								if(sdl_x11available && sdl_using_x11) {
-									Window sowner=None;
+					if(sdl_x11available && sdl_using_x11) {
+						XEvent *e;
+						e=&ev.syswm.msg->msg.x11.event;
+						switch(e->type) {
+							case SelectionClear: {
+									XSelectionClearEvent *req;
+
+									req=&(e->xselectionclear);
+									sdl.mutexP(sdl_copybuf_mutex);
+									if(req->selection==CONSOLE_CLIPBOARD) {
+										FREE_AND_NULL(sdl_copybuf);
+									}
+									sdl.mutexV(sdl_copybuf_mutex);
+									copy_needs_events = 0;
+									if (!paste_needs_events)
+										sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
+									break;
+							}
+							case SelectionNotify: {
+									int format=0;
+									unsigned long len, bytes_left, dummy;
+									Atom type;
+									XSelectionEvent *req;
 									SDL_SysWMinfo	wmi;
 
 									SDL_VERSION(&(wmi.version));
-									sdl.GetWMInfo(&wmi);
-
-									paste_needs_events = 1;
-									sdl.EventState(SDL_SYSWMEVENT, SDL_ENABLE);
-									sowner=sdl_x11.XGetSelectionOwner(wmi.info.x11.display, CONSOLE_CLIPBOARD);
-									if(sowner==wmi.info.x11.window) {
-										/* Get your own primary selection */
-										if(sdl_copybuf==NULL) {
+									sdl.GetWindowWMInfo(win, &wmi);
+									req=&(e->xselection);
+									if(req->requestor!=wmi.info.x11.window)
+										break;
+									if(req->property) {
+										sdl_x11.XGetWindowProperty(wmi.info.x11.display, wmi.info.x11.window, req->property, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytes_left, (unsigned char **)(&sdl_pastebuf));
+										if(bytes_left > 0 && format==8)
+											sdl_x11.XGetWindowProperty(wmi.info.x11.display, wmi.info.x11.window, req->property,0,bytes_left,0,AnyPropertyType,&type,&format,&len,&dummy,(unsigned char **)&sdl_pastebuf);
+										else {
 											FREE_AND_NULL(sdl_pastebuf);
 										}
-										else
-											sdl_pastebuf=(char *)malloc(strlen(sdl_copybuf)+1);
-										if(sdl_pastebuf!=NULL)
-											strcpy(sdl_pastebuf,sdl_copybuf);
-										/* Set paste buffer */
-										sdl.SemPost(sdl_pastebuf_set);
-										sdl.SemWait(sdl_pastebuf_copied);
-										FREE_AND_NULL(sdl_pastebuf);
-										paste_needs_events = 0;
-										if (!copy_needs_events)
-											sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
-									}
-									else if(sowner!=None) {
-										sdl_x11.XConvertSelection(wmi.info.x11.display, CONSOLE_CLIPBOARD, XA_STRING, XA_STRING, wmi.info.x11.window, CurrentTime);
 									}
 									else {
-										/* Set paste buffer */
 										FREE_AND_NULL(sdl_pastebuf);
-										sdl.SemPost(sdl_pastebuf_set);
-										sdl.SemWait(sdl_pastebuf_copied);
-										paste_needs_events = 0;
-										if (!copy_needs_events)
-											sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
 									}
-								}
-#endif
-								break;
-						}
-						break;
-					}
-					case SDL_SYSWMEVENT:			/* ToDo... This is where Copy/Paste needs doing */
-#if !defined(NO_X) && defined(__unix__) && defined(SDL_VIDEO_DRIVER_X11)
-						if(sdl_x11available && sdl_using_x11) {
-							XEvent *e;
-							e=&ev.syswm.msg->event.xevent;
-							switch(e->type) {
-								case SelectionClear: {
-										XSelectionClearEvent *req;
-
-										req=&(e->xselectionclear);
-										sdl.mutexP(sdl_copybuf_mutex);
-										if(req->selection==CONSOLE_CLIPBOARD) {
-											FREE_AND_NULL(sdl_copybuf);
-										}
-										sdl.mutexV(sdl_copybuf_mutex);
-										copy_needs_events = 0;
-										if (!paste_needs_events)
-											sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
-										break;
-								}
-								case SelectionNotify: {
-										int format=0;
-										unsigned long len, bytes_left, dummy;
-										Atom type;
-										XSelectionEvent *req;
-										SDL_SysWMinfo	wmi;
-
-										SDL_VERSION(&(wmi.version));
-										sdl.GetWMInfo(&wmi);
-										req=&(e->xselection);
-										if(req->requestor!=wmi.info.x11.window)
-											break;
-										if(req->property) {
-											sdl_x11.XGetWindowProperty(wmi.info.x11.display, wmi.info.x11.window, req->property, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytes_left, (unsigned char **)(&sdl_pastebuf));
-											if(bytes_left > 0 && format==8)
-												sdl_x11.XGetWindowProperty(wmi.info.x11.display, wmi.info.x11.window, req->property,0,bytes_left,0,AnyPropertyType,&type,&format,&len,&dummy,(unsigned char **)&sdl_pastebuf);
-											else {
-												FREE_AND_NULL(sdl_pastebuf);
-											}
-										}
-										else {
-											FREE_AND_NULL(sdl_pastebuf);
-										}
 
-										/* Set paste buffer */
-										sdl.SemPost(sdl_pastebuf_set);
-										sdl.SemWait(sdl_pastebuf_copied);
-										paste_needs_events = 0;
-										if (!copy_needs_events)
-											sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
-										if(sdl_pastebuf!=NULL) {
-											sdl_x11.XFree(sdl_pastebuf);
-											sdl_pastebuf=NULL;
+									/* Set paste buffer */
+									sdl.SemPost(sdl_pastebuf_set);
+									sdl.SemWait(sdl_pastebuf_copied);
+									paste_needs_events = 0;
+									if (!copy_needs_events)
+										sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
+									if(sdl_pastebuf!=NULL) {
+										sdl_x11.XFree(sdl_pastebuf);
+										sdl_pastebuf=NULL;
+									}
+									break;
+							}
+							case SelectionRequest: {
+									XSelectionRequestEvent *req;
+									XEvent respond;
+
+									req=&(e->xselectionrequest);
+									sdl.mutexP(sdl_copybuf_mutex);
+									if(sdl_copybuf==NULL) {
+										respond.xselection.property=None;
+									}
+									else {
+										if(req->target==XA_STRING) {
+											sdl_x11.XChangeProperty(req->display, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char *)sdl_copybuf, strlen(sdl_copybuf));
+											respond.xselection.property=req->property;
 										}
-										break;
-								}
-								case SelectionRequest: {
-										XSelectionRequestEvent *req;
-										XEvent respond;
-
-										req=&(e->xselectionrequest);
-										sdl.mutexP(sdl_copybuf_mutex);
-										if(sdl_copybuf==NULL) {
+										else
 											respond.xselection.property=None;
-										}
-										else {
-											if(req->target==XA_STRING) {
-												sdl_x11.XChangeProperty(req->display, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char *)sdl_copybuf, strlen(sdl_copybuf));
-												respond.xselection.property=req->property;
-											}
-											else
-												respond.xselection.property=None;
-										}
-										sdl.mutexV(sdl_copybuf_mutex);
-										respond.xselection.type=SelectionNotify;
-										respond.xselection.display=req->display;
-										respond.xselection.requestor=req->requestor;
-										respond.xselection.selection=req->selection;
-										respond.xselection.target=req->target;
-										respond.xselection.time=req->time;
-										sdl_x11.XSendEvent(req->display,req->requestor,0,0,&respond);
-										break;
-								}
-							}	/* switch */
-						}	/* usingx11 */
+									}
+									sdl.mutexV(sdl_copybuf_mutex);
+									respond.xselection.type=SelectionNotify;
+									respond.xselection.display=req->display;
+									respond.xselection.requestor=req->requestor;
+									respond.xselection.selection=req->selection;
+									respond.xselection.target=req->target;
+									respond.xselection.time=req->time;
+									sdl_x11.XSendEvent(req->display,req->requestor,0,0,&respond);
+									break;
+							}
+						}	/* switch */
+					}	/* usingx11 */
 #endif
 
-					/* Ignore this stuff */
-					case SDL_JOYAXISMOTION:
-					case SDL_JOYBALLMOTION:
-					case SDL_JOYHATMOTION:
-					case SDL_JOYBUTTONDOWN:
-					case SDL_JOYBUTTONUP:
-					default:
-						break;
-				}
+				/* Ignore this stuff */
+				case SDL_JOYAXISMOTION:
+				case SDL_JOYBALLMOTION:
+				case SDL_JOYHATMOTION:
+				case SDL_JOYBUTTONDOWN:
+				case SDL_JOYBUTTONUP:
+				default:
+					break;
 			}
 		}
 	}
@@ -1932,15 +1578,12 @@ int sdl_initciolib(int mode)
 	sdl_ufunc_rec=sdl.SDL_CreateSemaphore(0);
 	sdl_ufunc_mtx=sdl.SDL_CreateMutex();
 	sdl_headlock=sdl.SDL_CreateMutex();
-	newrect_mutex=sdl.SDL_CreateMutex();
 	win_mutex=sdl.SDL_CreateMutex();
 	sdl_keylock=sdl.SDL_CreateMutex();
-	bitmap_init_mutex=sdl.SDL_CreateMutex();
 #if !defined(NO_X) && defined(__unix__)
 	sdl_pastebuf_set=sdl.SDL_CreateSemaphore(0);
 	sdl_pastebuf_copied=sdl.SDL_CreateSemaphore(0);
 	sdl_copybuf_mutex=sdl.SDL_CreateMutex();
 #endif
-	run_sdl_drawing_thread(sdl_video_event_thread, exit_sdl_con);
 	return(sdl_init(mode));
 }
diff --git a/src/conio/sdl_con.h b/src/conio/sdl_con.h
index 1fe5817afca4c253bd153ab7a42ac00d1a09502e..c61a4d5e5cd5fcce6241525586830ebb3a07bcd8 100644
--- a/src/conio/sdl_con.h
+++ b/src/conio/sdl_con.h
@@ -11,6 +11,7 @@ int sdl_init_mode(int mode);
 int sdl_setup_colours(void);
 int sdl_draw_char(unsigned short vch, int xpos, int ypos);
 int sdl_screen_redraw(void);
+void exit_sdl_con(void);
 
 /* High-level stuff */
 void sdl_setscaling(int new_value);
diff --git a/src/conio/sdlfuncs.c b/src/conio/sdlfuncs.c
index 6e2cad06e023b2ee725e34721cdcc2057665af7e..c4b26ad29a21a333029c8b7e463d6d4e7a9b733d 100644
--- a/src/conio/sdlfuncs.c
+++ b/src/conio/sdlfuncs.c
@@ -4,13 +4,8 @@
 #include "gen_defs.h"
 #include "threadwrap.h"
 #include <SDL.h>
-#ifndef main
- #define USE_REAL_MAIN
-#endif
-#ifdef USE_REAL_MAIN
- #undef main
-#endif
 #include "sdlfuncs.h"
+#include "sdl_con.h"
 extern int sdl_video_initialized;
 
 #ifndef _WIN32
@@ -26,23 +21,13 @@ struct sdlfuncs sdl;
 static int sdl_funcs_loaded=0;
 static int sdl_initialized=0;
 static int sdl_audio_initialized=0;
-static int (*sdl_drawing_thread)(void *data)=NULL;
-static void (*sdl_exit_drawing_thread)(void)=NULL;
-static int main_returned=0;
-static SDL_sem *sdl_main_sem;
-SDL_sem *sdl_exit_sem;
-
-int CIOLIB_main(int argc, char **argv, char **enviro);
-int XPDEV_main(int argc, char **argv, char **enviro)
-{
-	return CIOLIB_main(argc, argv, enviro);
-}
 
+static void QuitWrap(void);
 
 int load_sdl_funcs(struct sdlfuncs *sdlf)
 {
 	dll_handle	sdl_dll;
-	const char *libnames[]={"SDL", "SDL-1.2", "SDL-1.1", NULL};
+	const char *libnames[]={"SDL2", "SDL", NULL};
 
 	putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1");
 	sdlf->gotfuncs=0;
@@ -63,11 +48,12 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->mutexP=xp_dlsym(sdl_dll, SDL_mutexP))==NULL) {
+	// SDL2: Rename from mutexP/mutexV to LockMutex/UnlockMutex
+	if((sdlf->mutexP=xp_dlsym(sdl_dll, SDL_LockMutex))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->mutexV=xp_dlsym(sdl_dll, SDL_mutexV))==NULL) {
+	if((sdlf->mutexV=xp_dlsym(sdl_dll, SDL_UnlockMutex))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
@@ -75,7 +61,7 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->VideoDriverName=xp_dlsym(sdl_dll, SDL_VideoDriverName))==NULL) {
+	if((sdlf->GetCurrentVideoDriver=xp_dlsym(sdl_dll, SDL_GetCurrentVideoDriver))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
@@ -107,19 +93,11 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->SetColors=xp_dlsym(sdl_dll, SDL_SetColors))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
 	if((sdlf->BlitSurface=xp_dlsym(sdl_dll, SDL_UpperBlit))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->UpdateRects=xp_dlsym(sdl_dll, SDL_UpdateRects))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->UpdateRect=xp_dlsym(sdl_dll, SDL_UpdateRect))==NULL) {
+	if((sdlf->RenderPresent=xp_dlsym(sdl_dll, SDL_RenderPresent))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
@@ -139,23 +117,27 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->KillThread=xp_dlsym(sdl_dll, SDL_KillThread))==NULL) {
+	if((sdlf->WaitThread=xp_dlsym(sdl_dll, SDL_WaitThread))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->WaitThread=xp_dlsym(sdl_dll, SDL_WaitThread))==NULL) {
+	if((sdlf->WaitEventTimeout=xp_dlsym(sdl_dll, SDL_WaitEventTimeout))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->WaitEvent=xp_dlsym(sdl_dll, SDL_WaitEvent))==NULL) {
+	if((sdlf->PollEvent=xp_dlsym(sdl_dll, SDL_PollEvent))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->PollEvent=xp_dlsym(sdl_dll, SDL_PollEvent))==NULL) {
+	if((sdlf->CreateWindow=xp_dlsym(sdl_dll, SDL_CreateWindow))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->SetVideoMode=xp_dlsym(sdl_dll, SDL_SetVideoMode))==NULL) {
+	if((sdlf->CreateWindowAndRenderer=xp_dlsym(sdl_dll, SDL_CreateWindowAndRenderer))==NULL) {
+		xp_dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->CreateRenderer=xp_dlsym(sdl_dll, SDL_CreateRenderer))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
@@ -163,31 +145,31 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->WM_SetCaption=xp_dlsym(sdl_dll, SDL_WM_SetCaption))==NULL) {
+	if((sdlf->SetWindowTitle=xp_dlsym(sdl_dll, SDL_SetWindowTitle))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->WM_SetIcon=xp_dlsym(sdl_dll, SDL_WM_SetIcon))==NULL) {
+	if((sdlf->GetWindowSize=xp_dlsym(sdl_dll, SDL_GetWindowSize))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->ShowCursor=xp_dlsym(sdl_dll, SDL_ShowCursor))==NULL) {
+	if((sdlf->GetWindowSurface=xp_dlsym(sdl_dll, SDL_GetWindowSurface))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->WasInit=xp_dlsym(sdl_dll, SDL_WasInit))==NULL) {
+	if((sdlf->SetWindowIcon=xp_dlsym(sdl_dll, SDL_SetWindowIcon))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->EnableUNICODE=xp_dlsym(sdl_dll, SDL_EnableUNICODE))==NULL) {
+	if((sdlf->ShowCursor=xp_dlsym(sdl_dll, SDL_ShowCursor))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->EnableKeyRepeat=xp_dlsym(sdl_dll, SDL_EnableKeyRepeat))==NULL) {
+	if((sdlf->WasInit=xp_dlsym(sdl_dll, SDL_WasInit))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->GetWMInfo=xp_dlsym(sdl_dll, SDL_GetWMInfo))==NULL) {
+	if((sdlf->GetWindowWMInfo=xp_dlsym(sdl_dll, SDL_GetWindowWMInfo))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
@@ -239,42 +221,31 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->DisplayFormat=xp_dlsym(sdl_dll, SDL_DisplayFormat))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->Flip=xp_dlsym(sdl_dll, SDL_Flip))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->CreateYUVOverlay=xp_dlsym(sdl_dll, SDL_CreateYUVOverlay))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->DisplayYUVOverlay=xp_dlsym(sdl_dll, SDL_DisplayYUVOverlay))==NULL) {
+	if((sdlf->ConvertSurface=xp_dlsym(sdl_dll, SDL_ConvertSurface))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->FreeYUVOverlay=xp_dlsym(sdl_dll, SDL_FreeYUVOverlay))==NULL) {
+	if((sdlf->CreateTexture=xp_dlsym(sdl_dll, SDL_CreateTexture))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->LockYUVOverlay=xp_dlsym(sdl_dll, SDL_LockYUVOverlay))==NULL) {
+	if((sdlf->UpdateTexture=xp_dlsym(sdl_dll, SDL_UpdateTexture))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->UnlockYUVOverlay=xp_dlsym(sdl_dll, SDL_UnlockYUVOverlay))==NULL) {
+	if((sdlf->RenderClear=xp_dlsym(sdl_dll, SDL_RenderClear))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->GetVideoInfo=xp_dlsym(sdl_dll, SDL_GetVideoInfo))==NULL) {
+	if((sdlf->RenderCopy=xp_dlsym(sdl_dll, SDL_RenderCopy))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->Linked_Version=xp_dlsym(sdl_dll, SDL_Linked_Version))==NULL) {
+	if((sdlf->SetHint=xp_dlsym(sdl_dll, SDL_SetHint))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
+
 	sdlf->gotfuncs=1;
 	sdl_funcs_loaded=1;
 	return(0);
@@ -282,164 +253,112 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 
 int init_sdl_video(void)
 {
-	/* This is all handled in SDL_main_env() */
-	if(sdl_video_initialized)
-		return(0);
-	else
-		return(-1);
-}
-
-int init_sdl_audio(void)
-{
-	if(!sdl_initialized)
-		return(-1);
-	if(sdl_audio_initialized)
-		return(0);
-	if(sdl.InitSubSystem(SDL_INIT_AUDIO)==0) {
-		sdl_audio_initialized=TRUE;
-		return(0);
-	}
-	return(-1);
-}
-
-struct main_args {
-	int		argc;
-	char	**argv;
-	char	**enviro;
-};
-
-static int sdl_run_main(void *data)
-{
-	struct main_args	*args;
-	int	ret;
-
-	args=data;
-	ret=CIOLIB_main(args->argc, args->argv, args->enviro);
-	main_returned=1;
-	sdl.SemPost(sdl_main_sem);
-	if(sdl_exit_drawing_thread!=NULL)
-		sdl_exit_drawing_thread();
-	sdl.SemPost(sdl_exit_sem);
-	return(ret);
-}
-
-void run_sdl_drawing_thread(int (*drawing_thread)(void *data), void (*exit_drawing_thread)(void))
-{
-	sdl_drawing_thread=drawing_thread;
-	sdl_exit_drawing_thread=exit_drawing_thread;
-	sdl.SemPost(sdl_main_sem);
-}
-
-static void QuitWrap(void)
-{
-	if(sdl.Quit && sdl_initialized)
-		sdl.Quit();
-}
-
-#ifndef main
-int main(int argc, char **argv, char **env)
-#else
-int SDL_main_env(int argc, char **argv, char **env)
-#endif
-{
-	char	drivername[64];
-	struct main_args ma;
-	SDL_Thread	*main_thread;
-	int		main_ret=0;
+	char	*drivername;
 	int		use_sdl_video=FALSE;
 #ifdef _WIN32
 	char		*driver_env=NULL;
 #endif
 
-	ma.argc=argc;
-	ma.argv=argv;
-	ma.enviro=env;
+	if(sdl_video_initialized)
+		return(0);
+
 #ifndef _WIN32
 	load_sdl_funcs(&sdl);
 #endif
 
-	if(sdl.gotfuncs) {
-		use_sdl_video=TRUE;
+	if (!sdl.gotfuncs)
+		return -1;
 
+	use_sdl_video=TRUE;
+
+	sdl.SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1" );
 #ifdef _WIN32
-		/* Fail to windib (ie: No mouse attached) */
-		if(sdl.Init(SDL_INIT_VIDEO)) {
-			driver_env=getenv("SDL_VIDEODRIVER");
-			if(driver_env==NULL || strcmp(driver_env,"windib")) {
-				putenv("SDL_VIDEODRIVER=windib");
-				WinExec(GetCommandLine(), SW_SHOWDEFAULT);
-				return(0);
-			}
-			/* Sure ,we can't use video, but audio is still valid! */
-			if(sdl.Init(0)==0)
-				sdl_initialized=TRUE;
+	/* Fail to windib (ie: No mouse attached) */
+	if(sdl.Init(SDL_INIT_VIDEO)) {
+		// SDL2: We can likely do better now...
+		driver_env=getenv("SDL_VIDEODRIVER");
+		if(driver_env==NULL || strcmp(driver_env,"windib")) {
+			putenv("SDL_VIDEODRIVER=windib");
+			WinExec(GetCommandLine(), SW_SHOWDEFAULT);
+			return(0);
 		}
-		else {
-			sdl_video_initialized=TRUE;
+		/* Sure ,we can't use video, but audio is still valid! */
+		if(sdl.Init(0)==0)
 			sdl_initialized=TRUE;
-		}
+	}
+	else {
+		sdl_video_initialized=TRUE;
+		sdl_initialized=TRUE;
+	}
 #else
-		/*
-		 * On Linux, SDL doesn't properly detect availability of the
-		 * framebuffer apparently.  This results in remote connections
-		 * displaying on the local framebuffer... a definate no-no.
-		 * This ugly hack attempts to prevent this... of course, remote X11
-		 * connections must still be allowed.
-		 */
-		if((!use_sdl_video) || ((getenv("REMOTEHOST")!=NULL || getenv("SSH_CLIENT")!=NULL) && getenv("DISPLAY")==NULL)) {
-			/* Sure ,we can't use video, but audio is still valid! */
-			if(sdl.Init(0)==0)
-				sdl_initialized=TRUE;
+	/*
+	 * SDL2: Is the below comment still true for SDL2?
+	 * On Linux, SDL doesn't properly detect availability of the
+	 * framebuffer apparently.  This results in remote connections
+	 * displaying on the local framebuffer... a definate no-no.
+	 * This ugly hack attempts to prevent this... of course, remote X11
+	 * connections must still be allowed.
+	 */
+	if((!use_sdl_video) || ((getenv("REMOTEHOST")!=NULL || getenv("SSH_CLIENT")!=NULL) && getenv("DISPLAY")==NULL)) {
+		/* Sure ,we can't use video, but audio is still valid! */
+		if(sdl.Init(0)==0)
+			sdl_initialized=TRUE;
+	}
+	else {
+		if(sdl.Init(SDL_INIT_VIDEO)==0) {
+			sdl_initialized=TRUE;
+			sdl_video_initialized=TRUE;
 		}
 		else {
-			if(sdl.Init(SDL_INIT_VIDEO)==0) {
+			/* Sure ,we can't use video, but audio is still valid! */
+			if(sdl.Init(0)==0)
 				sdl_initialized=TRUE;
-				sdl_video_initialized=TRUE;
-			}
-			else {
-				/* Sure ,we can't use video, but audio is still valid! */
-				if(sdl.Init(0)==0)
-					sdl_initialized=TRUE;
-			}
 		}
+	}
 #endif
-		if(sdl_video_initialized && sdl.VideoDriverName(drivername, sizeof(drivername))!=NULL) {
-			/* Unacceptable drivers */
-			if((!strcmp(drivername, "caca")) || (!strcmp(drivername,"aalib")) || (!strcmp(drivername,"dummy"))) {
-				sdl.QuitSubSystem(SDL_INIT_VIDEO);
-				sdl_video_initialized=FALSE;
-			}
-			else {
-				const SDL_VideoInfo *initial=sdl.GetVideoInfo();
-
-				/* Save initial video mode */
-				if(initial)
-					sdl.initial_videoinfo=*initial;
-				else
-					memset(&sdl.initial_videoinfo, 0, sizeof(sdl.initial_videoinfo));
-				sdl_video_initialized=TRUE;
-			}
+	if(sdl_video_initialized && (drivername = sdl.GetCurrentVideoDriver())!=NULL) {
+		/* Unacceptable drivers */
+		if((!strcmp(drivername, "caca")) || (!strcmp(drivername,"aalib")) || (!strcmp(drivername,"dummy"))) {
+			sdl.QuitSubSystem(SDL_INIT_VIDEO);
+			sdl_video_initialized=FALSE;
+		}
+		else {
+			sdl_video_initialized=TRUE;
 		}
 	}
+
 	if(sdl_video_initialized) {
 		SetThreadName("SDL Main");
 		atexit(QuitWrap);
-		sdl_main_sem=sdl.SDL_CreateSemaphore(0);
-		sdl_exit_sem=sdl.SDL_CreateSemaphore(0);
-		main_thread=sdl.CreateThread(sdl_run_main,&ma);
-		sdl.SemWait(sdl_main_sem);
-		if(sdl_drawing_thread!=NULL) {
-			sdl_drawing_thread(NULL);
-			sdl_exit_drawing_thread=NULL;
-			if(!main_returned) {
-				main_ret=0;
-			}
-		}
-		sdl.SemWait(sdl_exit_sem);
-		if(main_returned)
-			sdl.WaitThread(main_thread, &main_ret);
+		return 0;
+	}
+
+	return(-1);
+}
+
+int init_sdl_audio(void)
+{
+	if(!sdl_initialized)
+		return(-1);
+	if(sdl_audio_initialized)
+		return(0);
+	if(sdl.InitSubSystem(SDL_INIT_AUDIO)==0) {
+		sdl_audio_initialized=TRUE;
+		return(0);
+	}
+	return(-1);
+}
+
+void run_sdl_drawing_thread(int (*drawing_thread)(void *data))
+{
+	sdl.CreateThread(drawing_thread, NULL);
+}
+
+static void QuitWrap(void)
+{
+	if (sdl_initialized) {
+		exit_sdl_con();
+		if(sdl.Quit)
+			sdl.Quit();
 	}
-	else
-		main_ret=CIOLIB_main(argc, argv, env);
-	return(main_ret);
 }
diff --git a/src/conio/sdlfuncs.h b/src/conio/sdlfuncs.h
index 384c14ec062dd439bb048051299d57e97747a2a5..635d389921c972d265c38aeabb9e4ef4f081db00 100644
--- a/src/conio/sdlfuncs.h
+++ b/src/conio/sdlfuncs.h
@@ -19,38 +19,37 @@ struct sdlfuncs {
 	int	(HACK_HACK_HACK *mutexV)	(SDL_mutex *mutex);
 	int	(HACK_HACK_HACK *PeepEvents)	(SDL_Event *events, int numevents,
 					SDL_eventaction action, Uint32 mask);
-	char	*(HACK_HACK_HACK *VideoDriverName)	(char *namebuf, int maxlen);
+	char	*(HACK_HACK_HACK *GetCurrentVideoDriver)	(void);
 	int	(HACK_HACK_HACK *SemWait)	(SDL_sem *sem);
 	int	(HACK_HACK_HACK *SemWaitTimeout)(SDL_sem *sem, Uint32 timeout);
 	int	(HACK_HACK_HACK *SemPost)	(SDL_sem *sem);
-	Uint8	(HACK_HACK_HACK *EventState)	(Uint8 type, int state);
+	Uint8	(HACK_HACK_HACK *EventState)	(Uint32 type, int state);
 	SDL_Surface	*(HACK_HACK_HACK *CreateRGBSurface)	(Uint32 flags, int width, int height, int depth,
 							Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
 	SDL_Surface *(HACK_HACK_HACK *CreateRGBSurfaceFrom)(void *pixels, int width, int height, int depth, int pitch,
 							Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
 	int	(HACK_HACK_HACK *FillRect)	(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
-	int	(HACK_HACK_HACK *SetColors)	(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors);
 	int	(HACK_HACK_HACK *BlitSurface)	(SDL_Surface *src, SDL_Rect *srcrect,
 								SDL_Surface *dst, SDL_Rect *dstrect);
-	void	(HACK_HACK_HACK *UpdateRects)	(SDL_Surface *screen, int numrects, SDL_Rect *rects);
-	void	(HACK_HACK_HACK *UpdateRect)	(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h);
+	void	(HACK_HACK_HACK *RenderPresent)	(SDL_Renderer *renderer);
 	SDL_sem *(HACK_HACK_HACK *SDL_CreateSemaphore)	(Uint32 initial_value);
 	void (HACK_HACK_HACK *SDL_DestroySemaphore)	(SDL_sem *semaphore);
 	SDL_mutex	*(HACK_HACK_HACK *SDL_CreateMutex)	(void);
 	struct SDL_Thread	*(HACK_HACK_HACK *CreateThread)	(int (*fn)(void *), void *data);
-	void	(HACK_HACK_HACK *KillThread)	(SDL_Thread *thread);
 	void	(HACK_HACK_HACK *WaitThread)	(SDL_Thread *thread, int *status);
-	int	(HACK_HACK_HACK *WaitEvent)	(SDL_Event *event);
+	int	(HACK_HACK_HACK *WaitEventTimeout)	(SDL_Event *event, int timeout);
 	int	(HACK_HACK_HACK *PollEvent)	(SDL_Event *event);
-	SDL_Surface	*(HACK_HACK_HACK *SetVideoMode)	(int width, int height, int bpp, Uint32 flags);
+	SDL_Window *(HACK_HACK_HACK *CreateWindow)	(const char *title, int x, int y, int w, int h, Uint32 flags);
+	int (HACK_HACK_HACK *CreateWindowAndRenderer)	(int w, int h, Uint32 flags, SDL_Window **win, SDL_Renderer **ren);
+	SDL_Renderer *(HACK_HACK_HACK *CreateRenderer)	(SDL_Window* window, int index, Uint32 flags);
 	void	(HACK_HACK_HACK *FreeSurface)	(SDL_Surface *surface);
-	void	(HACK_HACK_HACK *WM_SetCaption)	(const char *title, const char *icon);
-	void	(HACK_HACK_HACK *WM_SetIcon)	(SDL_Surface *icon, Uint8 *mask);
+	void	(HACK_HACK_HACK *SetWindowTitle)	(SDL_Window *window, const char *title);
+	void	(HACK_HACK_HACK *GetWindowSize)	(SDL_Window *window, int *w, int *h);
+	SDL_Surface	*(HACK_HACK_HACK *GetWindowSurface)	(SDL_Window *window);
+	void	(HACK_HACK_HACK *SetWindowIcon)	(SDL_Window *win, SDL_Surface *icon);
 	int	(HACK_HACK_HACK *ShowCursor)	(int toggle);
 	Uint32	(HACK_HACK_HACK *WasInit)	(Uint32 flags);
-	int	(HACK_HACK_HACK *EnableUNICODE)	(int enable);
-	int	(HACK_HACK_HACK *EnableKeyRepeat)	(int delay, int interval);
-	int	(HACK_HACK_HACK *GetWMInfo)	(SDL_SysWMinfo *info);
+	int	(HACK_HACK_HACK *GetWindowWMInfo)	(SDL_Window *window, SDL_SysWMinfo *info);
 	char	*(HACK_HACK_HACK *GetError)	(void);
 	int (HACK_HACK_HACK *InitSubSystem)(Uint32 flags);
 	void (HACK_HACK_HACK *QuitSubSystem)(Uint32 flags);
@@ -59,20 +58,16 @@ struct sdlfuncs {
 	void (HACK_HACK_HACK *LockAudio)(void);
 	void (HACK_HACK_HACK *UnlockAudio)(void);
 	void (HACK_HACK_HACK *PauseAudio)(int pause_on);
-	SDL_audiostatus (HACK_HACK_HACK *GetAudioStatus)(void);
+	SDL_AudioStatus (HACK_HACK_HACK *GetAudioStatus)(void);
 	Uint32	(HACK_HACK_HACK *MapRGB)	(SDL_PixelFormat *fmt, Uint8 r, Uint8 g, Uint8 b);
 	int	(HACK_HACK_HACK *LockSurface)	(SDL_Surface *surface);
 	void (HACK_HACK_HACK *UnlockSurface)	(SDL_Surface *surface);
-	SDL_Surface	*(HACK_HACK_HACK *DisplayFormat)(SDL_Surface *surf);
-	int	(HACK_HACK_HACK *Flip)	(SDL_Surface *surface);
-	SDL_Overlay *(HACK_HACK_HACK *CreateYUVOverlay)(int width, int height, Uint32 format, SDL_Surface *display);
-	int (HACK_HACK_HACK *DisplayYUVOverlay)(SDL_Overlay *overlay, SDL_Rect *dstrect);
-	void (HACK_HACK_HACK *FreeYUVOverlay)	(SDL_Overlay *overlay);
-	int	(HACK_HACK_HACK *LockYUVOverlay)	(SDL_Overlay *overlay);
-	void (HACK_HACK_HACK *UnlockYUVOverlay)	(SDL_Overlay *overlay);
-	const SDL_VideoInfo *(HACK_HACK_HACK *GetVideoInfo)(void);
-	const SDL_version *(HACK_HACK_HACK *Linked_Version)(void);
-	SDL_VideoInfo initial_videoinfo;
+	SDL_Surface	*(HACK_HACK_HACK *ConvertSurface)(SDL_Surface *surf, const SDL_PixelFormat *fmt, Uint32 flags);
+	SDL_Texture* (HACK_HACK_HACK *CreateTexture)	(SDL_Renderer *renderer, Uint32 format, int access, int w, int h);
+	int (HACK_HACK_HACK *UpdateTexture)	(SDL_Texture *texture, const SDL_Rect * rect, const void *pixels, int pitch);
+	int (HACK_HACK_HACK *RenderClear)	(SDL_Renderer *renderer);
+	int (HACK_HACK_HACK *RenderCopy)	(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect);
+	SDL_bool (HACK_HACK_HACK *SetHint)	(const char *name, const char *value);
 	int	gotfuncs;
 };
 
@@ -86,8 +81,7 @@ extern "C" {
 int load_sdl_funcs(struct sdlfuncs *sdlf);
 int init_sdl_audio(void);
 int init_sdl_video(void);
-int SDL_main_env(int argc, char *argv[], char **env);
-void run_sdl_drawing_thread(int (*drawing_thread)(void *data), void (*exit_drawing_thread)(void));
+void run_sdl_drawing_thread(int (*drawing_thread)(void *data));
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/odoors/GNUmakefile b/src/odoors/GNUmakefile
index 6958d8a85f4f493ab282c8b8a45c7ea966fd87b5..a85e3004af934bea35f9db35d609a868de1fc5d3 100644
--- a/src/odoors/GNUmakefile
+++ b/src/odoors/GNUmakefile
@@ -37,7 +37,7 @@
 #                  bcc - For Borland C++
 #                   cl - For Microsoft compilers
 #
-CC	:=	gcc
+CC	?=	gcc
 #
 #------------------------------------------------------------------------------
 #
@@ -53,7 +53,7 @@ OBJDIR	:=	objs-$(OS)/
 LIBDIR	:=	libs-$(OS)/
 EXEDIR	:=	exe-$(OS)/
 
-LD	:=	gcc
+LD	?=	gcc
 
 ifdef DEBUG
  CFLAGS	+=	-g -DOD_DEBUG
@@ -68,13 +68,14 @@ endif
 #
 CFLAGS	+=	-fPIC
 LDFLAGS	+=	-fPIC
-CFLAGS	+=	-O2 -L${LIBDIR} -I../xpdev -Wall
+CFLAGS	+=	-O2 -L${LIBDIR} -I../xpdev
 ifeq ($(OS),Darwin)
  CFLAGS		+=	-D__unix__
- LDFLAGS	+=	$(CFLAGS) -dynamiclib -single_module
+ LDFLAGS	:=	$(CFLAGS) -dynamiclib -single_module
 else
- LDFLAGS	+=	$(CFLAGS) -shared
+ LDFLAGS	:=	$(CFLAGS) -shared
 endif
+CFLAGS	+=	-Wall
 ifeq ($(shell if [ -f /usr/include/inttypes.h ] ; then echo YES ; fi),YES)
  CFLAGS	+=	-DHAS_INTTYPES_H
 endif
diff --git a/src/syncterm/Manual.txt b/src/syncterm/Manual.txt
index 92330a4c94b8904e928145c5d95663c5b2b0774f..58ce281321da71f39f40f380bfc20c58823aa31c 100644
--- a/src/syncterm/Manual.txt
+++ b/src/syncterm/Manual.txt
@@ -141,10 +141,6 @@ options are supported (options are not case sensitive):
         default mode.  Additionally, a 'W' or 'F' can be specified to force
         windowed or full-screen mode respectively.
 
-    O[WF] - SDL Overlay output mode.  Uses the SDL library for output, and
-        supports hardware scaling if available.  Additionally, a 'W' or 'F'
-        can be specified to force windowed or full-screen mode respectively.
-
 -L##
     Specifies the number of lines on the "screen".  Supported values are:
     14, 21, 25 (default), 28, 43, 50, and 60.
diff --git a/src/syncterm/bbslist.c b/src/syncterm/bbslist.c
index 07a10fedb5b99af3ca759b62297362944472bd10..809404c4acef829fee3c22200d2c9a42237042ca 100644
--- a/src/syncterm/bbslist.c
+++ b/src/syncterm/bbslist.c
@@ -1427,13 +1427,6 @@ void change_settings(int connected)
 								"        otherwise identical to X11 mode.\n\n"
 								"~ SDL Fullscreen ~\n"
 								"        As above, but starts in full-screen mode rather than a window\n\n"
-								"~ SDL Overlay ~\n"
-								"        The most resource intensive mode.  However, unlike the other\n"
-								"        graphical modes, this window can be scaled to any size and,\n"
-								"        when switched to full screen, will always use the entire\n"
-								"        display.\n\n"
-								"~ SDL Overlay Fullscreen ~\n"
-								"        As above, but starts in full-screen mode rather than a window\n\n"
 #endif
 								;
 				switch(i=uifc.list(WIN_SAV,0,0,0,&j,NULL,"Video Output Mode",output_types)) {
diff --git a/src/syncterm/syncterm.c b/src/syncterm/syncterm.c
index 82cc288de5a9e4cd14a04307ee233699a1641da1..c6e09f5ca3da6bd6fab792bc9433d20c070bdf38 100644
--- a/src/syncterm/syncterm.c
+++ b/src/syncterm/syncterm.c
@@ -67,7 +67,6 @@ char	*usage =
         "-e# =  set escape delay to #msec\n"
 		"-iX =  set interface mode to X (default=auto) where X is one of:\n"
 		"       S[W|F] = SDL surface mode W for windowed and F for fullscreen\n"
-		"       O[W|F] = SDL overlay mode (hardware scaled)\n"
 #ifdef __unix__
 		"       X = X11 mode\n"
 		"       C = Curses mode\n"
@@ -726,8 +725,6 @@ char *output_types[]={
 #if defined(WITH_SDL) || defined(WITH_SDL_AUDIO)
 	,"SDL"
 	,"SDL Fullscreen"
-	,"SDL Overlay"
-	,"SDL Overlay Fullscreen"
 #endif
 ,NULL};
 int output_map[]={
@@ -761,8 +758,6 @@ char *output_descrs[]={
 	,"Win32 Console Fullscreen"
 	,"SDL"
 	,"SDL Fullscreen"
-	,"SDL Overlay"
-	,"SDL Overlay Fullscreen"
 ,NULL};
 
 char *output_enum[]={
@@ -775,8 +770,6 @@ char *output_enum[]={
 	,"WinConsoleFullscreen"
 	,"SDL"
 	,"SDLFullscreen"
-	,"SDLOverlay"
-	,"SDLOverlayFullscreen"
 ,NULL};
 
 BOOL check_exit(BOOL force)
diff --git a/src/xpdev/Common.bmake b/src/xpdev/Common.bmake
index 36aed7f28b419b09718cf3dace95d26fde52ccee..cadd73e5b51d8cee4d14a1b9e9190528186b2dd2 100644
--- a/src/xpdev/Common.bmake
+++ b/src/xpdev/Common.bmake
@@ -1,7 +1,7 @@
 XPDEV-MT_CFLAGS = $(XPDEV-MT_CFLAGS) -DXPDEV_THREAD_SAFE
 !ifdef USE_SDL_AUDIO
-XPDEV-MT_CFLAGS = $(XPDEV-MT_CFLAGS) -DWITH_SDL_AUDIO -DWIN32 -I../../include/sdl
-XPDEV_CFLAGS = $(XPDEV_CFLAGS) -DWITH_SDL_AUDIO -DWIN32 -I../../include/sdl
+XPDEV-MT_CFLAGS = $(XPDEV-MT_CFLAGS) -DWITH_SDL_AUDIO -DWIN32 -I${3RDP_ROOT}/win32.release/sdl2/include
+XPDEV_CFLAGS = $(XPDEV_CFLAGS) -DWITH_SDL_AUDIO -DWIN32 -I${3RDP_ROOT}/win32.release/sdl2/include
 !ifdef STATIC_SDL
 XPDEV-MT_CFLAGS = $(XPDEV-MT_CFLAGS) -DSTATIC_SDL
 XPDEV_CFLAGS = $(XPDEV_CFLAGS) -DSTATIC_SDL
diff --git a/src/xpdev/Common.gmake b/src/xpdev/Common.gmake
index 865280d3f7a940c003357b1637e38f7418bc53a6..8c0667a4f6163582891a98f85ea807b417047846 100644
--- a/src/xpdev/Common.gmake
+++ b/src/xpdev/Common.gmake
@@ -98,30 +98,26 @@ endif
 # Find SDL headers!
 ifdef USE_SDL_AUDIO
  ifdef SDL_CONFIG
-  ifeq ($(shell ${SDL_CONFIG} --cflags > /dev/null 2>&1 && echo YES),YES)
+  ifeq ($(shell if [ `${SDL_CONFIG} --version | sed -E 's/\..*$$//'` -ge 2 ] ; then echo 'YES' ; fi),YES)
    WITH_SDL_AUDIO	:=	1
   endif
  else
   ifeq ($(os),darwin)
    ifeq ($(shell if [ -d /Library/Frameworks/SDL.framework ] ; then echo YES ; fi),YES)
-    SDL_FRAMEWORK_PATH	?=	/Library/Frameworks
+    SDL_FRAMEWORK_PATH ?= /Library/Frameworks
    endif
    ifdef SDL_FRAMEWORK_PATH
     WITH_SDL_AUDIO	:=	1
+    CIOLIB-MT_LDFLAGS += -Wl,-rpath,@executable_path/../Frameworks
    endif
   else
-   ifeq ($(shell sdl12-config --cflags > /dev/null 2>&1 && echo YES),YES)
-    SDL_CONFIG := sdl12-config
+   ifeq ($(shell sdl2-config --cflags > /dev/null 2>&1 && echo YES),YES)
+    SDL_CONFIG := sdl2-config
     WITH_SDL_AUDIO	:=	1
    else
-    ifeq ($(shell sdl-config --cflags > /dev/null 2>&1 && echo YES),YES)
+    ifeq ($(shell if [ `sdl-config --version | sed -E 's/\..*$$//'` -ge 2 ] ; then echo 'YES' ; fi),YES)
      SDL_CONFIG := sdl-config
      WITH_SDL_AUDIO	:=	1
-    else
-     ifeq ($(shell sdl11-config --cflags > /dev/null 2>&1 && echo YES),YES)
-      SDL_CONFIG := sdl11-config
-      WITH_SDL_AUDIO	:=	1
-     endif
     endif
    endif
   endif
diff --git a/src/xpdev/GNUmakefile b/src/xpdev/GNUmakefile
index 5b2f0054690ede5c841df834726986ee5f163e0a..e56a44f81aa5767f1b1bfd37514c01e16ad85b43 100644
--- a/src/xpdev/GNUmakefile
+++ b/src/xpdev/GNUmakefile
@@ -17,20 +17,6 @@ MT_CFLAGS	+=	$(XPDEV-MT_CFLAGS)
 ifdef WITH_SDL_AUDIO
  MTOBJS	+=	$(MTOBJODIR)$(DIRSEP)sdlfuncs$(OFILE)
  OBJS	+=	$(OBJODIR)$(DIRSEP)sdlfuncs$(OFILE)
- ifeq ($(os),darwin)
-  MTOBJS	+=	$(MTOBJODIR)$(DIRSEP)SDLMain$(OFILE)
-  OBJS	+=	$(OBJODIR)$(DIRSEP)SDLMain$(OFILE)
- endif
-endif
-
-ifeq ($(os),darwin)
-$(MTOBJODIR)$(DIRSEP)SDLMain$(OFILE): SDLMain.m
-	@echo $(COMPILE_MSG) $<
-	$(QUIET)$(CC) $(CFLAGS) $(MT_CFLAGS) $(CCFLAGS) -o $@ -c $<
-
-$(OBJODIR)$(DIRSEP)SDLMain$(OFILE): SDLMain.m
-	@echo $(COMPILE_MSG) $<
-	$(QUIET)$(CC) $(CFLAGS) $(CCFLAGS) -o $@ -c $<
 endif
 
 # Executable Build Rule
diff --git a/src/xpdev/gen_defs.h b/src/xpdev/gen_defs.h
index 4658ee06b0eaf73d0802337505c84863d43d1787..88d4fb9905754b1aa7dbaa15de4fccd0b1746c52 100644
--- a/src/xpdev/gen_defs.h
+++ b/src/xpdev/gen_defs.h
@@ -523,14 +523,8 @@ typedef struct {
         #define LOG_DEBUG       7       /* debug-level messages */
 #endif
 
-/* Special hackery for SDL */
 #ifdef WITH_SDL_AUDIO
         #include <SDL.h>
-
-        #ifdef main
-                #undef main
-        #endif
-        #define main    XPDEV_main
 #endif
 
 #endif /* Don't add anything after this #endif statement */
diff --git a/src/xpdev/sdlfuncs.c b/src/xpdev/sdlfuncs.c
index 7da02038b876f32029e65f33a24e9f7db0bc8a5a..597a21fc6a016f6b4eb89920986acb76cac92bdc 100644
--- a/src/xpdev/sdlfuncs.c
+++ b/src/xpdev/sdlfuncs.c
@@ -25,14 +25,6 @@ struct sdlfuncs sdl;
 static int sdl_funcs_loaded=0;
 static int sdl_initialized=0;
 static int sdl_audio_initialized=0;
-static int sdl_video_initialized=0;
-static int (*sdl_drawing_thread)(void *data)=NULL;
-static void (*sdl_exit_drawing_thread)(void)=NULL;
-static int main_returned=0;
-static SDL_sem *sdl_main_sem;
-SDL_sem *sdl_exit_sem;
-
-int XPDEV_main(int argc, char **argv, char **enviro);
 
 int load_sdl_funcs(struct sdlfuncs *sdlf)
 {
@@ -44,12 +36,6 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 	if((sdl_dll=xp_dlopen(libnames,RTLD_LAZY|RTLD_GLOBAL,SDL_PATCHLEVEL))==NULL)
 		return(-1);
 
-#ifdef _WIN32
-	if((sdlf->SetModuleHandle=xp_dlsym(sdl_dll, SDL_SetModuleHandle))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-#endif
 	if((sdlf->Init=xp_dlsym(sdl_dll, SDL_Init))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
@@ -58,66 +44,14 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->mutexP=xp_dlsym(sdl_dll, SDL_mutexP))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->mutexV=xp_dlsym(sdl_dll, SDL_mutexV))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->PeepEvents=xp_dlsym(sdl_dll, SDL_PeepEvents))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->VideoDriverName=xp_dlsym(sdl_dll, SDL_VideoDriverName))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
 	if((sdlf->SemWait=xp_dlsym(sdl_dll, SDL_SemWait))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->SemWaitTimeout=xp_dlsym(sdl_dll, SDL_SemWaitTimeout))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
 	if((sdlf->SemPost=xp_dlsym(sdl_dll, SDL_SemPost))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->EventState=xp_dlsym(sdl_dll, SDL_EventState))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->CreateRGBSurface=xp_dlsym(sdl_dll, SDL_CreateRGBSurface))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->CreateRGBSurfaceFrom=xp_dlsym(sdl_dll, SDL_CreateRGBSurfaceFrom))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->FillRect=xp_dlsym(sdl_dll, SDL_FillRect))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->SetColors=xp_dlsym(sdl_dll, SDL_SetColors))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->BlitSurface=xp_dlsym(sdl_dll, SDL_UpperBlit))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->UpdateRects=xp_dlsym(sdl_dll, SDL_UpdateRects))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->UpdateRect=xp_dlsym(sdl_dll, SDL_UpdateRect))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
 	if((sdlf->SDL_CreateSemaphore=xp_dlsym(sdl_dll, SDL_CreateSemaphore))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
@@ -126,70 +60,6 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->SDL_CreateMutex=xp_dlsym(sdl_dll, SDL_CreateMutex))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->CreateThread=xp_dlsym(sdl_dll, SDL_CreateThread))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->KillThread=xp_dlsym(sdl_dll, SDL_KillThread))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->WaitThread=xp_dlsym(sdl_dll, SDL_WaitThread))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->WaitEvent=xp_dlsym(sdl_dll, SDL_WaitEvent))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->PollEvent=xp_dlsym(sdl_dll, SDL_PollEvent))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->SetVideoMode=xp_dlsym(sdl_dll, SDL_SetVideoMode))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->FreeSurface=xp_dlsym(sdl_dll, SDL_FreeSurface))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->WM_SetCaption=xp_dlsym(sdl_dll, SDL_WM_SetCaption))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->WM_SetIcon=xp_dlsym(sdl_dll, SDL_WM_SetIcon))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->ShowCursor=xp_dlsym(sdl_dll, SDL_ShowCursor))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->WasInit=xp_dlsym(sdl_dll, SDL_WasInit))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->EnableUNICODE=xp_dlsym(sdl_dll, SDL_EnableUNICODE))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->EnableKeyRepeat=xp_dlsym(sdl_dll, SDL_EnableKeyRepeat))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->GetWMInfo=xp_dlsym(sdl_dll, SDL_GetWMInfo))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->GetError=xp_dlsym(sdl_dll, SDL_GetError))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
 	if((sdlf->InitSubSystem=xp_dlsym(sdl_dll, SDL_InitSubSystem))==NULL) {
 		xp_dlclose(sdl_dll);
 		return(-1);
@@ -222,72 +92,23 @@ int load_sdl_funcs(struct sdlfuncs *sdlf)
 		xp_dlclose(sdl_dll);
 		return(-1);
 	}
-	if((sdlf->MapRGB=xp_dlsym(sdl_dll, SDL_MapRGB))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->LockSurface=xp_dlsym(sdl_dll, SDL_LockSurface))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->UnlockSurface=xp_dlsym(sdl_dll, SDL_UnlockSurface))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->DisplayFormat=xp_dlsym(sdl_dll, SDL_DisplayFormat))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->Flip=xp_dlsym(sdl_dll, SDL_Flip))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->CreateYUVOverlay=xp_dlsym(sdl_dll, SDL_CreateYUVOverlay))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->DisplayYUVOverlay=xp_dlsym(sdl_dll, SDL_DisplayYUVOverlay))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->FreeYUVOverlay=xp_dlsym(sdl_dll, SDL_FreeYUVOverlay))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->LockYUVOverlay=xp_dlsym(sdl_dll, SDL_LockYUVOverlay))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->UnlockYUVOverlay=xp_dlsym(sdl_dll, SDL_UnlockYUVOverlay))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->GetVideoInfo=xp_dlsym(sdl_dll, SDL_GetVideoInfo))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
-	if((sdlf->Linked_Version=xp_dlsym(sdl_dll, SDL_Linked_Version))==NULL) {
-		xp_dlclose(sdl_dll);
-		return(-1);
-	}
 	sdlf->gotfuncs=1;
 	sdl_funcs_loaded=1;
 	return(0);
 }
 
-int init_sdl_video(void)
-{
-	/* This is all handled in SDL_main_env() */
-	if(sdl_video_initialized)
-		return(0);
-	else
-		return(-1);
-}
-
 int init_sdl_audio(void)
 {
-	if(!sdl_initialized)
-		return(-1);
+	if (!sdl_funcs_loaded) {
+		if (load_sdl_funcs(&sdl) != 0)
+			return -1;
+	}
+	if(!sdl_initialized) {
+		if(sdl.Init(0)==0)
+			sdl_initialized=TRUE;
+		else
+			return(-1);
+	}
 	if(sdl_audio_initialized)
 		return(0);
 	if(sdl.InitSubSystem(SDL_INIT_AUDIO)==0) {
@@ -296,139 +117,3 @@ int init_sdl_audio(void)
 	}
 	return(-1);
 }
-
-struct main_args {
-	int		argc;
-	char	**argv;
-	char	**enviro;
-};
-
-static int sdl_run_main(void *data)
-{
-	struct main_args	*args;
-	int	ret;
-
-	args=data;
-	ret=XPDEV_main(args->argc, args->argv, args->enviro);
-	main_returned=1;
-	sdl.SemPost(sdl_main_sem);
-	if(sdl_exit_drawing_thread!=NULL)
-		sdl_exit_drawing_thread();
-	sdl.SemPost(sdl_exit_sem);
-	return(ret);
-}
-
-void run_sdl_drawing_thread(int (*drawing_thread)(void *data), void (*exit_drawing_thread)(void))
-{
-	sdl_drawing_thread=drawing_thread;
-	sdl_exit_drawing_thread=exit_drawing_thread;
-	sdl.SemPost(sdl_main_sem);
-}
-
-#ifndef main
-int main(int argc, char **argv, char **env)
-#else
-int SDL_main_env(int argc, char **argv, char **env)
-#endif
-{
-	char	drivername[64];
-	struct main_args ma;
-	SDL_Thread	*main_thread;
-	int		main_ret;
-	int		use_sdl_video=FALSE;
-#ifdef _WIN32
-	char		*driver_env=NULL;
-#endif
-
-	ma.argc=argc;
-	ma.argv=argv;
-	ma.enviro=env;
-#ifndef _WIN32
-	load_sdl_funcs(&sdl);
-#endif
-
-	if(sdl.gotfuncs) {
-		use_sdl_video=TRUE;
-
-#ifdef _WIN32
-		/* Fail to windib (ie: No mouse attached) */
-		if(sdl.Init(SDL_INIT_VIDEO)) {
-			driver_env=getenv("SDL_VIDEODRIVER");
-			if(driver_env==NULL || strcmp(driver_env,"windib")) {
-				putenv("SDL_VIDEODRIVER=windib");
-				WinExec(GetCommandLine(), SW_SHOWDEFAULT);
-				return(0);
-			}
-			/* Sure ,we can't use video, but audio is still valid! */
-			if(sdl.Init(0)==0)
-				sdl_initialized=TRUE;
-		}
-		else {
-			sdl_video_initialized=TRUE;
-			sdl_initialized=TRUE;
-		}
-#else
-		/*
-		 * On Linux, SDL doesn't properly detect availability of the
-		 * framebuffer apparently.  This results in remote connections
-		 * displaying on the local framebuffer... a definate no-no.
-		 * This ugly hack attempts to prevent this... of course, remote X11
-		 * connections must still be allowed.
-		 */
-		if((!use_sdl_video) || ((getenv("REMOTEHOST")!=NULL || getenv("SSH_CLIENT")!=NULL) && getenv("DISPLAY")==NULL)) {
-			/* Sure ,we can't use video, but audio is still valid! */
-			if(sdl.Init(0)==0)
-				sdl_initialized=TRUE;
-		}
-		else {
-			if(sdl.Init(SDL_INIT_VIDEO)==0) {
-				sdl_initialized=TRUE;
-				sdl_video_initialized=TRUE;
-			}
-			else {
-				/* Sure ,we can't use video, but audio is still valid! */
-				if(sdl.Init(0)==0)
-					sdl_initialized=TRUE;
-			}
-		}
-#endif
-		if(sdl_video_initialized && sdl.VideoDriverName(drivername, sizeof(drivername))!=NULL) {
-			/* Unacceptable drivers */
-			if((!strcmp(drivername, "caca")) || (!strcmp(drivername,"aalib")) || (!strcmp(drivername,"dummy"))) {
-				sdl.QuitSubSystem(SDL_INIT_VIDEO);
-				sdl_video_initialized=FALSE;
-			}
-			else {
-				const SDL_VideoInfo *initial=sdl.GetVideoInfo();
-
-				/* Save initial video mode */
-				if(initial)
-					sdl.initial_videoinfo=*initial;
-				else
-					memset(&sdl.initial_videoinfo, 0, sizeof(sdl.initial_videoinfo));
-				sdl_video_initialized=TRUE;
-			}
-		}
-	}
-	if(sdl_video_initialized) {
-		SetThreadName("SDL Main");
-		atexit(sdl.Quit);
-		sdl_main_sem=sdl.SDL_CreateSemaphore(0);
-		sdl_exit_sem=sdl.SDL_CreateSemaphore(0);
-		main_thread=sdl.CreateThread(sdl_run_main,&ma);
-		sdl.SemWait(sdl_main_sem);
-		if(sdl_drawing_thread!=NULL) {
-			sdl_drawing_thread(NULL);
-			sdl_exit_drawing_thread=NULL;
-			if(!main_returned) {
-				main_ret=0;
-			}
-		}
-		sdl.SemWait(sdl_exit_sem);
-		if(main_returned)
-			sdl.WaitThread(main_thread, &main_ret);
-	}
-	else
-		main_ret=XPDEV_main(argc, argv, env);
-	return(main_ret);
-}
diff --git a/src/xpdev/sdlfuncs.h b/src/xpdev/sdlfuncs.h
index ceaaec5fd3f9a5ad79a6888fb22021e10bdbf70f..aa61d64c4af2d167037083ec039412fc57cc70f1 100644
--- a/src/xpdev/sdlfuncs.h
+++ b/src/xpdev/sdlfuncs.h
@@ -8,44 +8,10 @@
 struct sdlfuncs {
 	int	(*Init)	(Uint32 flags);
 	void	(*Quit)	(void);
-	void	(*SetModuleHandle)	(void *hInst);
-	int	(*mutexP)	(SDL_mutex *mutex);
-	int	(*mutexV)	(SDL_mutex *mutex);
-	int	(*PeepEvents)	(SDL_Event *events, int numevents,
-					SDL_eventaction action, Uint32 mask);
-	char	*(*VideoDriverName)	(char *namebuf, int maxlen);
 	int	(*SemWait)	(SDL_sem *sem);
-	int	(*SemWaitTimeout)	(SDL_sem *sem, Uint32 timeout);
 	int	(*SemPost)	(SDL_sem *sem);
-	Uint8	(*EventState)	(Uint8 type, int state);
-	SDL_Surface	*(*CreateRGBSurface)	(Uint32 flags, int width, int height, int depth,
-							Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
-	SDL_Surface *(*CreateRGBSurfaceFrom)(void *pixels, int width, int height, int depth, int pitch,
-							Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
-	int	(*FillRect)	(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
-	int	(*SetColors)	(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors);
-	int	(*BlitSurface)	(SDL_Surface *src, SDL_Rect *srcrect,
-								SDL_Surface *dst, SDL_Rect *dstrect);
-	void	(*UpdateRects)	(SDL_Surface *screen, int numrects, SDL_Rect *rects);
-	void	(*UpdateRect)	(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h);
 	SDL_sem *(*SDL_CreateSemaphore)	(Uint32 initial_value);
 	void (*SDL_DestroySemaphore)	(SDL_sem *semaphore);
-	SDL_mutex	*(*SDL_CreateMutex)	(void);
-	struct SDL_Thread	*(*CreateThread)	(int (*fn)(void *), void *data);
-	void	(*KillThread)	(SDL_Thread *thread);
-	void	(*WaitThread)	(SDL_Thread *thread, int *status);
-	int	(*WaitEvent)	(SDL_Event *event);
-	int	(*PollEvent)	(SDL_Event *event);
-	SDL_Surface	*(*SetVideoMode)	(int width, int height, int bpp, Uint32 flags);
-	void	(*FreeSurface)	(SDL_Surface *surface);
-	void	(*WM_SetCaption)	(const char *title, const char *icon);
-	void	(*WM_SetIcon)	(SDL_Surface *icon, Uint8 *mask);
-	int	(*ShowCursor)	(int toggle);
-	Uint32	(*WasInit)	(Uint32 flags);
-	int	(*EnableUNICODE)	(int enable);
-	int	(*EnableKeyRepeat)	(int delay, int interval);
-	int	(*GetWMInfo)	(SDL_SysWMinfo *info);
-	char	*(*GetError)	(void);
 	int (*InitSubSystem)(Uint32 flags);
 	void (*QuitSubSystem)(Uint32 flags);
 	int (*OpenAudio)(SDL_AudioSpec *desired, SDL_AudioSpec *obtained);
@@ -53,20 +19,7 @@ struct sdlfuncs {
 	void (*LockAudio)(void);
 	void (*UnlockAudio)(void);
 	void (*PauseAudio)(int pause_on);
-	SDL_audiostatus (*GetAudioStatus)(void);
-	Uint32	(*MapRGB)	(SDL_PixelFormat *fmt, Uint8 r, Uint8 g, Uint8 b);
-	int	(*LockSurface)	(SDL_Surface *surface);
-	void (*UnlockSurface)	(SDL_Surface *surface);
-	SDL_Surface	*(*DisplayFormat)(SDL_Surface *surf);
-	int	(*Flip)	(SDL_Surface *surface);
-	SDL_Overlay *(*CreateYUVOverlay)(int width, int height, Uint32 format, SDL_Surface *display);
-	int (*DisplayYUVOverlay)(SDL_Overlay *overlay, SDL_Rect *dstrect);
-	void (*FreeYUVOverlay)	(SDL_Overlay *overlay);
-	int	(*LockYUVOverlay)	(SDL_Overlay *overlay);
-	void (*UnlockYUVOverlay)	(SDL_Overlay *overlay);
-	const SDL_VideoInfo *(*GetVideoInfo)(void);
-	const SDL_version *(*Linked_Version)(void);
-	SDL_VideoInfo initial_videoinfo;
+	SDL_AudioStatus (*GetAudioStatus)(void);
 	int	gotfuncs;
 };
 
@@ -79,9 +32,7 @@ extern "C" {
 #endif
 int load_sdl_funcs(struct sdlfuncs *sdlf);
 int init_sdl_audio(void);
-int init_sdl_video(void);
 int SDL_main_env(int argc, char *argv[], char **env);
-void run_sdl_drawing_thread(int (*drawing_thread)(void *data), void (*exit_drawing_thread)(void));
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/xpdev/xpbeep.c b/src/xpdev/xpbeep.c
index 1e4fb59c0dd7cfa2f18fe40dcaee0ee31d0d4bfa..6a3c4c1957a1b5d8b6e5e345f330e605e707e9ce 100644
--- a/src/xpdev/xpbeep.c
+++ b/src/xpdev/xpbeep.c
@@ -372,7 +372,7 @@ BOOL DLLCALL xptone_open(void)
 					||
 						(
 							((pa_api->active=xp_dlsym(dl,Pa_StreamActive))==NULL)
-							&& ((pa_api->active=xp_dlsym(dl,Pa_IsStreamActive))==NULL)
+							&& ((pa_api->active=xp_dlsym(dl,Pa_IsStreamStopped))==NULL)
 						)
 					|| ((pa_api->stop=xp_dlsym(dl,Pa_StopStream))==NULL)
 					) {
@@ -428,8 +428,9 @@ BOOL DLLCALL xptone_open(void)
 
 #ifdef WITH_SDL_AUDIO
 	if(!sdl_device_open_failed) {
-		if(init_sdl_audio()==-1)
+		if(init_sdl_audio()==-1) {
 			sdl_device_open_failed=TRUE;
+		}
 		else {
 			spec.freq=22050;
 			spec.format=AUDIO_U8;
@@ -470,8 +471,9 @@ BOOL DLLCALL xptone_open(void)
 		wh[0].dwBufferLength=S_RATE*15/2+1;
 		wh[1].dwBufferLength=S_RATE*15/2+1;
 		handle_type=SOUND_DEVICE_WIN32;
-		if(!sound_device_open_failed)
+		if(!sound_device_open_failed) {
 			return(TRUE);
+		}
 	}
 #endif
 
@@ -557,8 +559,9 @@ BOOL DLLCALL xptone_open(void)
 	if(sound_device_open_failed)
 		return(FALSE);
 	handle_type=SOUND_DEVICE_OSS;
-	if(!sound_device_open_failed)
+	if(!sound_device_open_failed) {
 		return(TRUE);
+	}
 #endif
 	return(FALSE);
 }
@@ -569,7 +572,7 @@ void DLLCALL xptone_complete(void)
 		return;
 #ifdef WITH_PORTAUDIO
 	else if(handle_type==SOUND_DEVICE_PORTAUDIO) {
-		while(pa_api->active(portaudio_stream))
+		while(pa_api->active(portaudio_stream) == 1)
 			SLEEP(1);
 		pa_api->stop(portaudio_stream);
 		if (pawave) {
@@ -717,6 +720,7 @@ void DLLCALL xp_play_sample_thread(void *data)
 	#ifdef WITH_PORTAUDIO
 		if(handle_type==SOUND_DEVICE_PORTAUDIO) {
 			if(pa_api->ver >= 1899) {
+				pa_api->start(portaudio_stream);
 				pa_api->write(portaudio_stream, sample, this_sample_size);
 				FREE_AND_NULL(sample);
 			}
@@ -886,8 +890,8 @@ BOOL DLLCALL xp_play_sample(const unsigned char *sample, size_t sample_size, BOO
 #ifdef WITH_PORTAUDIO
 	if(handle_type==SOUND_DEVICE_PORTAUDIO) {
 		if(pa_api->ver >= 1899) {
+			pa_api->start(portaudio_stream);
 			pa_api->write(portaudio_stream, sample, sample_size);
-			free(sample);
 		}
 		else {
 			xptone_complete();
@@ -905,7 +909,14 @@ BOOL DLLCALL xp_play_sample(const unsigned char *sample, size_t sample_size, BOO
 #ifdef WITH_SDL_AUDIO
 	if(handle_type==SOUND_DEVICE_SDL) {
 		sdl.LockAudio();
-		swave=sample;
+		swave=malloc(sample_size);
+		if (swave == NULL) {
+			sdl.UnlockAudio();
+			if(must_close)
+				xptone_close();
+			return FALSE;
+		}
+		memcpy(swave, sample, sample_size);
 		sdl_audio_buf_pos=0;
 		sdl_audio_buf_len=sample_size;
 		sdl.UnlockAudio();