diff --git a/src/xpdev/SDLMain.h b/src/xpdev/SDLMain.h
new file mode 100644
index 0000000000000000000000000000000000000000..4683df57a5e61fc41b189e67245f4a0a32d7552d
--- /dev/null
+++ b/src/xpdev/SDLMain.h
@@ -0,0 +1,11 @@
+/*   SDLMain.m - main entry point for our Cocoa-ized SDL app
+       Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
+       Non-NIB-Code & other changes: Max Horn <max@quendi.de>
+
+    Feel free to customize this file to suit your needs
+*/
+
+#import <Cocoa/Cocoa.h>
+
+@interface SDLMain : NSObject
+@end
diff --git a/src/xpdev/SDL_win32_main.c b/src/xpdev/SDL_win32_main.c
new file mode 100644
index 0000000000000000000000000000000000000000..fdbc7c498567757aad60986ecfa9ca547ce522a5
--- /dev/null
+++ b/src/xpdev/SDL_win32_main.c
@@ -0,0 +1,357 @@
+/*
+    SDL_main.c, placed in the public domain by Sam Lantinga  4/13/98
+
+    The WinMain function -- calls your program's main() function
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <windows.h>
+#include <malloc.h>			/* For _alloca() */
+
+#ifdef _WIN32_WCE
+# define DIR_SEPERATOR TEXT("\\")
+# undef _getcwd
+# define _getcwd(str,len)	wcscpy(str,TEXT(""))
+# define setbuf(f,b)
+# define setvbuf(w,x,y,z)
+# define fopen		_wfopen
+# define freopen	_wfreopen
+# define remove(x)	DeleteFile(x)
+# define strcat		wcscat
+#else
+# define DIR_SEPERATOR TEXT("/")
+# include <direct.h>
+#endif
+
+/* Include the SDL main definition header */
+#include "SDL.h"
+#include "SDL_main.h"
+extern C_LINKAGE int SDL_main_env(int argc, char *argv[], char **env);
+
+#ifdef main
+# ifndef _WIN32_WCE_EMULATION
+#  undef main
+# endif /* _WIN32_WCE_EMULATION */
+#endif /* main */
+
+#define NO_STDIO_REDIRECT
+
+/* The standard output files */
+#define STDOUT_FILE	TEXT("stdout.txt")
+#define STDERR_FILE	TEXT("stderr.txt")
+
+#ifndef NO_STDIO_REDIRECT
+# ifdef _WIN32_WCE
+  static wchar_t stdoutPath[MAX_PATH];
+  static wchar_t stderrPath[MAX_PATH];
+# else
+  static char stdoutPath[MAX_PATH];
+  static char stderrPath[MAX_PATH];
+# endif
+#endif
+
+/* Special Dynamic/Static hackery */
+#include "sdlfuncs.h"
+struct sdlfuncs sdl;
+
+#if defined(_WIN32_WCE) && _WIN32_WCE < 300
+/* seems to be undefined in Win CE although in online help */
+#define isspace(a) (((CHAR)a == ' ') || ((CHAR)a == '\t'))
+
+/* seems to be undefined in Win CE although in online help */
+char *strrchr(char *str, int c)
+{
+	char *p;
+
+	/* Skip to the end of the string */
+	p=str;
+	while (*p)
+		p++;
+
+	/* Look for the given character */
+	while ( (p >= str) && (*p != (CHAR)c) )
+		p--;
+
+	/* Return NULL if character not found */
+	if ( p < str ) {
+		p = NULL;
+	}
+	return p;
+}
+#endif /* _WIN32_WCE < 300 */
+
+/* Parse a command line buffer into arguments */
+static int ParseCommandLine(char *cmdline, char **argv)
+{
+	char *bufp;
+	int argc;
+
+	argc = 0;
+	for ( bufp = cmdline; *bufp; ) {
+		/* Skip leading whitespace */
+		while ( isspace(*bufp) ) {
+			++bufp;
+		}
+		/* Skip over argument */
+		if ( *bufp == '"' ) {
+			++bufp;
+			if ( *bufp ) {
+				if ( argv ) {
+					argv[argc] = bufp;
+				}
+				++argc;
+			}
+			/* Skip over word */
+			while ( *bufp && (*bufp != '"') ) {
+				++bufp;
+			}
+		} else {
+			if ( *bufp ) {
+				if ( argv ) {
+					argv[argc] = bufp;
+				}
+				++argc;
+			}
+			/* Skip over word */
+			while ( *bufp && ! isspace(*bufp) ) {
+				++bufp;
+			}
+		}
+		if ( *bufp ) {
+			if ( argv ) {
+				*bufp = '\0';
+			}
+			++bufp;
+		}
+	}
+	if ( argv ) {
+		argv[argc] = NULL;
+	}
+	return(argc);
+}
+
+/* Show an error message */
+static void ShowError(const char *title, const char *message)
+{
+/* If USE_MESSAGEBOX is defined, you need to link with user32.lib */
+#ifdef USE_MESSAGEBOX
+	MessageBox(NULL, message, title, MB_ICONEXCLAMATION|MB_OK);
+#else
+	fprintf(stderr, "%s: %s\n", title, message);
+#endif
+}
+
+/* Pop up an out of memory message, returns to Windows */
+static BOOL OutOfMemory(void)
+{
+	ShowError("Fatal Error", "Out of memory - aborting");
+	return FALSE;
+}
+
+/* Remove the output files if there was no output written */
+static void __cdecl cleanup_output(void)
+{
+#ifndef NO_STDIO_REDIRECT
+	FILE *file;
+	int empty;
+#endif
+
+	/* Flush the output in case anything is queued */
+	fclose(stdout);
+	fclose(stderr);
+
+#ifndef NO_STDIO_REDIRECT
+	/* See if the files have any output in them */
+	if ( stdoutPath[0] ) {
+		file = fopen(stdoutPath, TEXT("rb"));
+		if ( file ) {
+			empty = (fgetc(file) == EOF) ? 1 : 0;
+			fclose(file);
+			if ( empty ) {
+				remove(stdoutPath);
+			}
+		}
+	}
+	if ( stderrPath[0] ) {
+		file = fopen(stderrPath, TEXT("rb"));
+		if ( file ) {
+			empty = (fgetc(file) == EOF) ? 1 : 0;
+			fclose(file);
+			if ( empty ) {
+				remove(stderrPath);
+			}
+		}
+	}
+#endif
+}
+
+#if (defined(__BORLANDC__) || defined(_MSC_VER)) && !defined(_WIN32_WCE)
+/* The VC++ compiler needs main defined */
+#define console_main main
+#endif
+
+/* This is where execution begins [console apps] */
+int console_main(int argc, char *argv[], char **env)
+{
+	int n;
+	char *bufp, *appname;
+
+	/* Get the class name from argv[0] */
+	appname = argv[0];
+	if ( (bufp=strrchr(argv[0], '\\')) != NULL ) {
+		appname = bufp+1;
+	} else
+	if ( (bufp=strrchr(argv[0], '/')) != NULL ) {
+		appname = bufp+1;
+	}
+
+	if ( (bufp=strrchr(appname, '.')) == NULL )
+		n = strlen(appname);
+	else
+		n = (bufp-appname);
+
+	bufp = (char *)alloca(n+1);
+	if ( bufp == NULL ) {
+		return OutOfMemory();
+	}
+	strncpy(bufp, appname, n);
+	bufp[n] = '\0';
+	appname = bufp;
+
+	/* Load SDL dynamic link library */
+	if(!load_sdl_funcs(&sdl)) {
+		if ( sdl.Init(SDL_INIT_NOPARACHUTE) < 0 ) {
+			return(FALSE);
+		}
+		atexit(cleanup_output);
+		atexit(sdl.Quit);
+
+#ifndef DISABLE_VIDEO
+		/* Sam:
+		   We still need to pass in the application handle so that
+		   DirectInput will initialize properly when SDL_RegisterApp()
+		   is called later in the video initialization.
+		 */
+		sdl.SetModuleHandle(GetModuleHandle(NULL));
+#endif /* !DISABLE_VIDEO */
+	}
+
+	/* Run the application main() code */
+	n=SDL_main_env(argc, argv, env);
+
+	/* Exit cleanly, calling atexit() functions */
+	exit(n);
+
+	/* Hush little compiler, don't you cry... */
+	return(n);
+}
+
+/* This is where execution begins [windowed apps] */
+#ifdef _WIN32_WCE
+int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int sw)
+#else
+int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
+#endif
+{
+	HINSTANCE handle;
+	char **argv;
+	int argc;
+	char *cmdline;
+#ifdef _WIN32_WCE
+	wchar_t *bufp;
+	int nLen;
+#else
+	char *bufp;
+#endif
+#ifndef NO_STDIO_REDIRECT
+	FILE *newfp;
+#endif
+
+	/* Start up DDHELP.EXE before opening any files, so DDHELP doesn't
+	   keep them open.  This is a hack.. hopefully it will be fixed 
+	   someday.  DDHELP.EXE starts up the first time DDRAW.DLL is loaded.
+	 */
+	handle = LoadLibrary(TEXT("DDRAW.DLL"));
+	if ( handle != NULL ) {
+		FreeLibrary(handle);
+	}
+
+#ifndef NO_STDIO_REDIRECT
+	_getcwd( stdoutPath, sizeof( stdoutPath ) );
+	strcat( stdoutPath, DIR_SEPERATOR STDOUT_FILE );
+    
+	/* Redirect standard input and standard output */
+	newfp = freopen(stdoutPath, TEXT("w"), stdout);
+
+#ifndef _WIN32_WCE
+	if ( newfp == NULL ) {	/* This happens on NT */
+#if !defined(stdout)
+		stdout = fopen(stdoutPath, TEXT("w"));
+#else
+		newfp = fopen(stdoutPath, TEXT("w"));
+		if ( newfp ) {
+			*stdout = *newfp;
+		}
+#endif
+	}
+#endif /* _WIN32_WCE */
+
+	_getcwd( stderrPath, sizeof( stderrPath ) );
+	strcat( stderrPath, DIR_SEPERATOR STDERR_FILE );
+
+	newfp = freopen(stderrPath, TEXT("w"), stderr);
+#ifndef _WIN32_WCE
+	if ( newfp == NULL ) {	/* This happens on NT */
+#if !defined(stderr)
+		stderr = fopen(stderrPath, TEXT("w"));
+#else
+		newfp = fopen(stderrPath, TEXT("w"));
+		if ( newfp ) {
+			*stderr = *newfp;
+		}
+#endif
+	}
+#endif /* _WIN32_WCE */
+
+	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);	/* Line buffered */
+	setbuf(stderr, NULL);			/* No buffering */
+#endif /* !NO_STDIO_REDIRECT */
+
+#ifdef _WIN32_WCE
+	nLen = wcslen(szCmdLine)+128+1;
+	bufp = (wchar_t *)alloca(nLen*2);
+	wcscpy (bufp, TEXT("\""));
+	GetModuleFileName(NULL, bufp+1, 128-3);
+	wcscpy (bufp+wcslen(bufp), TEXT("\" "));
+	wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp));
+	nLen = wcslen(bufp)+1;
+	cmdline = (char *)alloca(nLen);
+	if ( cmdline == NULL ) {
+		return OutOfMemory();
+	}
+	WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL);
+#else
+	/* Grab the command line (use alloca() on Windows) */
+	bufp = GetCommandLine();
+	cmdline = (char *)alloca(strlen(bufp)+1);
+	if ( cmdline == NULL ) {
+		return OutOfMemory();
+	}
+	strcpy(cmdline, bufp);
+#endif
+
+	/* Parse it into argv and argc */
+	argc = ParseCommandLine(cmdline, NULL);
+	argv = (char **)alloca((argc+1)*(sizeof *argv));
+	if ( argv == NULL ) {
+		return OutOfMemory();
+	}
+	ParseCommandLine(cmdline, argv);
+
+	/* Run the main program (after a little SDL initialization) */
+	return(console_main(argc, argv, _environ));
+}
diff --git a/src/xpdev/sdlfuncs.c b/src/xpdev/sdlfuncs.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e1fdb8352b0a76ca656b4623314c668709394a3
--- /dev/null
+++ b/src/xpdev/sdlfuncs.c
@@ -0,0 +1,418 @@
+#include <stdio.h>	/* NULL */
+
+#include "gen_defs.h"
+#include "sdlfuncs.h"
+
+#ifndef _WIN32
+struct sdlfuncs sdl;
+#endif
+
+static int sdl_funcs_loaded=0;
+static int sdl_initialized=0;
+static int sdl_audio_initialized=0;
+static int sdl_video_initialized=0;
+
+#ifdef STATIC_SDL
+int load_sdl_funcs(struct sdlfuncs *sdlf)
+{
+	sdlf->gotfuncs=0;
+	sdlf->Init=SDL_Init;
+	sdlf->Quit=SDL_Quit;
+#ifdef _WIN32
+	sdlf->SetModuleHandle=SDL_SetModuleHandle;
+#endif
+	sdlf->mutexP=SDL_mutexP;
+	sdlf->mutexV=SDL_mutexV;
+	sdlf->PeepEvents=SDL_PeepEvents;
+	sdlf->VideoDriverName=SDL_VideoDriverName;
+	sdlf->SemWait=SDL_SemWait;
+	sdlf->SemPost=SDL_SemPost;
+	sdlf->EventState=SDL_EventState;
+	sdlf->CreateRGBSurface=SDL_CreateRGBSurface;
+	sdlf->FillRect=SDL_FillRect;
+	sdlf->SetColors=SDL_SetColors;
+	sdlf->BlitSurface=SDL_UpperBlit;
+	sdlf->UpdateRects=SDL_UpdateRects;
+	sdlf->SDL_CreateSemaphore=SDL_CreateSemaphore;
+	sdlf->SDL_CreateMutex=SDL_CreateMutex;
+	sdlf->CreateThread=SDL_CreateThread;
+	sdlf->WaitEvent=SDL_WaitEvent;
+	sdlf->SetVideoMode=SDL_SetVideoMode;
+	sdlf->FreeSurface=SDL_FreeSurface;
+	sdlf->WM_SetCaption=SDL_WM_SetCaption;
+	sdlf->ShowCursor=SDL_ShowCursor;
+	sdlf->WasInit=SDL_WasInit;
+	sdlf->EnableUNICODE=SDL_EnableUNICODE;
+	sdlf->EnableKeyRepeat=SDL_EnableKeyRepeat;
+	sdlf->GetWMInfo=SDL_GetWMInfo;
+	sdlf->GetError=SDL_GetError;
+	sdlf->InitSubSystem=SDL_InitSubSystem;
+	sdlf->QuitSubSystem=SDL_QuitSubSystem;
+	sdlf->gotfuncs=1;
+	sdl_funcs_loaded=1;
+	return(0);
+}
+#else
+
+#if defined(_WIN32)
+#include <Windows.h>
+
+int load_sdl_funcs(struct sdlfuncs *sdlf)
+{
+	HMODULE	sdl_dll;
+
+	sdlf->gotfuncs=0;
+	if((sdl_dll=LoadLibrary("SDL.dll"))==NULL)
+		if((sdl_dll=LoadLibrary("SDL-1.2.dll"))==NULL)
+			if((sdl_dll=LoadLibrary("SDL-1.1.dll"))==NULL)
+				return(-1);
+
+	if((sdlf->Init=GetProcAddress(sdl_dll, "SDL_Init"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->Quit=GetProcAddress(sdl_dll, "SDL_Quit"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SetModuleHandle=GetProcAddress(sdl_dll, "SDL_SetModuleHandle"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->mutexP=GetProcAddress(sdl_dll, "SDL_mutexP"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->mutexV=GetProcAddress(sdl_dll, "SDL_mutexV"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->PeepEvents=GetProcAddress(sdl_dll, "SDL_PeepEvents"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->VideoDriverName=GetProcAddress(sdl_dll, "SDL_VideoDriverName"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SemWait=GetProcAddress(sdl_dll, "SDL_SemWait"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SemPost=GetProcAddress(sdl_dll, "SDL_SemPost"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->EventState=GetProcAddress(sdl_dll, "SDL_EventState"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->CreateRGBSurface=GetProcAddress(sdl_dll, "SDL_CreateRGBSurface"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->FillRect=GetProcAddress(sdl_dll, "SDL_FillRect"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SetColors=GetProcAddress(sdl_dll, "SDL_SetColors"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->BlitSurface=GetProcAddress(sdl_dll, "SDL_UpperBlit"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->UpdateRects=GetProcAddress(sdl_dll, "SDL_UpdateRects"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SDL_CreateSemaphore=GetProcAddress(sdl_dll, "SDL_CreateSemaphore"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SDL_CreateMutex=GetProcAddress(sdl_dll, "SDL_CreateMutex"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->CreateThread=GetProcAddress(sdl_dll, "SDL_CreateThread"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->WaitEvent=GetProcAddress(sdl_dll, "SDL_WaitEvent"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SetVideoMode=GetProcAddress(sdl_dll, "SDL_SetVideoMode"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->FreeSurface=GetProcAddress(sdl_dll, "SDL_FreeSurface"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->WM_SetCaption=GetProcAddress(sdl_dll, "SDL_WM_SetCaption"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->ShowCursor=GetProcAddress(sdl_dll, "SDL_ShowCursor"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->WasInit=GetProcAddress(sdl_dll, "SDL_WasInit"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->EnableUNICODE=GetProcAddress(sdl_dll, "SDL_EnableUNICODE"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->EnableKeyRepeat=GetProcAddress(sdl_dll, "SDL_EnableKeyRepeat"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->GetWMInfo=GetProcAddress(sdl_dll, "SDL_GetWMInfo"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->GetError=GetProcAddress(sdl_dll, "SDL_GetError"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->InitSubSystem=GetProcAddress(sdl_dll, "SDL_InitSubSystem"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->QuitSubSystem=GetProcAddress(sdl_dll, "SDL_QuitSubSystem"))==NULL) {
+		FreeLibrary(sdl_dll);
+		return(-1);
+	}
+	sdlf->gotfuncs=1;
+	sdl_funcs_loaded=1;
+	return(0);
+}
+#elif defined(__unix__)
+#include <dlfcn.h>
+
+int load_sdl_funcs(struct sdlfuncs *sdlf)
+{
+	void	*sdl_dll;
+
+	sdlf->gotfuncs=0;
+	if((sdl_dll=dlopen("libSDL.so",RTLD_LAZY|RTLD_GLOBAL))==NULL)
+		if((sdl_dll=dlopen("libSDL-1.2.so",RTLD_LAZY|RTLD_GLOBAL))==NULL)
+			if((sdl_dll=dlopen("libSDL-1.1.so",RTLD_LAZY|RTLD_GLOBAL))==NULL)
+				return(-1);
+
+	if((sdlf->Init=dlsym(sdl_dll, "SDL_Init"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->Quit=dlsym(sdl_dll, "SDL_Quit"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->mutexP=dlsym(sdl_dll, "SDL_mutexP"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->mutexV=dlsym(sdl_dll, "SDL_mutexV"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->PeepEvents=dlsym(sdl_dll, "SDL_PeepEvents"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->VideoDriverName=dlsym(sdl_dll, "SDL_VideoDriverName"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SemWait=dlsym(sdl_dll, "SDL_SemWait"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SemPost=dlsym(sdl_dll, "SDL_SemPost"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->EventState=dlsym(sdl_dll, "SDL_EventState"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->CreateRGBSurface=dlsym(sdl_dll, "SDL_CreateRGBSurface"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->FillRect=dlsym(sdl_dll, "SDL_FillRect"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SetColors=dlsym(sdl_dll, "SDL_SetColors"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->BlitSurface=dlsym(sdl_dll, "SDL_UpperBlit"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->UpdateRects=dlsym(sdl_dll, "SDL_UpdateRects"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SDL_CreateSemaphore=dlsym(sdl_dll, "SDL_CreateSemaphore"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SDL_CreateMutex=dlsym(sdl_dll, "SDL_CreateMutex"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->CreateThread=dlsym(sdl_dll, "SDL_CreateThread"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->WaitEvent=dlsym(sdl_dll, "SDL_WaitEvent"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->SetVideoMode=dlsym(sdl_dll, "SDL_SetVideoMode"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->FreeSurface=dlsym(sdl_dll, "SDL_FreeSurface"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->WM_SetCaption=dlsym(sdl_dll, "SDL_WM_SetCaption"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->ShowCursor=dlsym(sdl_dll, "SDL_ShowCursor"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->WasInit=dlsym(sdl_dll, "SDL_WasInit"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->EnableUNICODE=dlsym(sdl_dll, "SDL_EnableUNICODE"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->EnableKeyRepeat=dlsym(sdl_dll, "SDL_EnableKeyRepeat"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->GetWMInfo=dlsym(sdl_dll, "SDL_GetWMInfo"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	if((sdlf->GetError=dlsym(sdl_dll, "SDL_GetError"))==NULL) {
+		dlclose(sdl_dll);
+		return(-1);
+	}
+	sdlf->gotfuncs=1;
+	sdl_funcs_loaded=1;
+	return(0);
+}
+#endif
+
+#endif
+
+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);
+}
+
+/* atexit() function */
+static void sdl_exit(void)
+{
+	sdl.Quit();
+}
+
+#ifndef main
+int main(int argc, char **argv, char **env)
+#else
+int SDL_main_env(int argc, char **argv, char **env)
+#endif
+{
+	unsigned int i;
+	SDL_Event	ev;
+	char	drivername[64];
+
+#ifndef _WIN32
+	load_sdl_funcs(&sdl);
+#endif
+
+	if(sdl.gotfuncs) {
+#ifdef _WIN32
+		/* Fail to windib (ie: No mouse attached) */
+		if(sdl.Init(SDL_INIT_VIDEO)) {
+			if(getenv("SDL_VIDEODRIVER")==NULL) {
+				putenv("SDL_VIDEODRIVER=windib");
+				WinExec(GetCommandLine(), SW_SHOWDEFAULT);
+				exit(0);
+			}
+			sdl.gotfuncs=FALSE;
+		}
+		else {
+			sdl_video_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(getenv("REMOTEHOST")!=NULL && getenv("DISPLAY")==NULL) {
+			/* Sure ,we can't use video, but audio is still valid! */
+			if(sdl.Init(0)==0)
+				sdl_initialized=TRUE;
+			sdl.gotfuncs=FALSE;
+		}
+		else {
+			if(sdl.Init(SDL_INIT_VIDEO))
+				sdl.gotfuncs=FALSE;
+			else {
+				sdl_initialized=TRUE;
+				sdl_video_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.gotfuncs=FALSE;
+				sdl.QuitSubSystem(SDL_INIT_VIDEO);
+				sdl_video_initialized=FALSE;
+			}
+			else {
+				sdl_video_initialized=TRUE;
+			}
+		}
+	}
+	if(sdl_initialized)
+		atexit(sdl_exit);
+	return(CIOLIB_main(argc, argv, env));
+}
diff --git a/src/xpdev/sdlfuncs.h b/src/xpdev/sdlfuncs.h
new file mode 100644
index 0000000000000000000000000000000000000000..fb1a6a3b23552d4f4120e8757b992f5c97cf007a
--- /dev/null
+++ b/src/xpdev/sdlfuncs.h
@@ -0,0 +1,58 @@
+#ifndef _SDLFUNCS_H_
+#define _SDLFUNCS_H_
+
+#include "SDL.h"
+#include "SDL_thread.h"
+#include "SDL_syswm.h"
+
+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	(*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);
+	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);
+	SDL_sem *(*SDL_CreateSemaphore)	(Uint32 initial_value);
+	SDL_mutex	*(*SDL_CreateMutex)	(void);
+	struct SDL_Thread	*(*CreateThread)	(int (*fn)(void *), void *data);
+	int	(*WaitEvent)	(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);
+	int	(*ShowCursor)	(int toggle);
+	Uint32	(*WasInit)	(Uint32 flags);
+	int	(*EnableUNICODE)	(int enable);
+	int	(*EnableKeyRepeat)	(int delay, int interval);
+	int	(*GetWMInfo)	(struct SDL_SysWMinfo *info);
+	char	*(*GetError)	(void);
+	int (*InitSubSystem)(Uint32 flags);
+	void (*QuitSubSystem)(Uint32 flags);
+	int	gotfuncs;
+};
+
+/* Defined in SDL_win32_main.c for Win32 */
+extern struct sdlfuncs	sdl;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int load_sdl_funcs(struct sdlfuncs *sdlf);
+int init_sdl_audio(void);
+int init_sdl_video(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif