From 57dd04d1c9d5435915301bb88891b8ae63af5ab2 Mon Sep 17 00:00:00 2001
From: deuce <>
Date: Tue, 31 Mar 2020 22:51:33 +0000
Subject: [PATCH] Initial SDL2 work.  This is rough and only lightly tested.

It's not unlikely that any utilities using SDL will have new issues... you
may want to hold off on updates for a bit until this settles unless you
don't use SDL mode.
---
 src/conio/Common.bmake  |    4 +-
 src/conio/Common.gmake  |   23 +-
 src/conio/GNUmakefile   |    6 -
 src/conio/ciolib.h      |    5 -
 src/conio/sdl_con.c     | 1131 ++++++++++++++-------------------------
 src/conio/sdl_con.h     |    1 +
 src/conio/sdlfuncs.c    |  309 ++++-------
 src/conio/sdlfuncs.h    |   46 +-
 src/odoors/GNUmakefile  |   11 +-
 src/syncterm/Manual.txt |    4 -
 src/syncterm/bbslist.c  |    7 -
 src/syncterm/syncterm.c |    7 -
 src/xpdev/Common.bmake  |    4 +-
 src/xpdev/Common.gmake  |   16 +-
 src/xpdev/GNUmakefile   |   14 -
 src/xpdev/gen_defs.h    |    6 -
 src/xpdev/sdlfuncs.c    |  335 +-----------
 src/xpdev/sdlfuncs.h    |   51 +-
 src/xpdev/xpbeep.c      |   25 +-
 19 files changed, 576 insertions(+), 1429 deletions(-)

diff --git a/src/conio/Common.bmake b/src/conio/Common.bmake
index 477c848ac9..ba3dab8068 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 d504deba23..37fa053f07 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 368fabd08d..1e06199b46 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 bb8bc3591d..9300c46b80 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 35af80de6a..bc62aba05a 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 1fe5817afc..c61a4d5e5c 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 6e2cad06e0..c4b26ad29a 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 384c14ec06..635d389921 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 6958d8a85f..a85e3004af 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 92330a4c94..58ce281321 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 07a10fedb5..809404c4ac 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 82cc288de5..c6e09f5ca3 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 36aed7f28b..cadd73e5b5 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 865280d3f7..8c0667a4f6 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 5b2f005469..e56a44f81a 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 4658ee06b0..88d4fb9905 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 7da02038b8..597a21fc6a 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 ceaaec5fd3..aa61d64c4a 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 1e4fb59c0d..6a3c4c1957 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();
-- 
GitLab