From 7c52c97d18acabddcdc7532c25d8ea1c8d929dda Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Mon, 22 Feb 2021 07:20:24 +0300
Subject: [PATCH] Windows and a few other OS-specific updates:
MSVC now builds and links without libc. Both MSVC and MinGW builds
run, at least the testplatform.exe and loopwave.exe example programs
built _without_ SDL_main.
- Added NMakefile for MSVC for convenience - tested with VS2017 and
VS2005.
- Renamed DllMain to _DllMainCRTStartup (as it should be) and added
_fltused for MSVC.
- Changed FIXME prints from fprintf to SDL_Log().
- Added simple error dialog windows for windows and macosx for SDL2
load failures. others simply use fprintf().
- Added runtime checks for minimum required SDL2 versions: Windows
builds need 2.0.12 SDL_CreateThread binary compatibility. Others
need at least 2.0.9 to access the SDL2 functions used here.
- Changed the SEEK_??? macros to RW_SEEK_??? in RWops12to20_size():
they are the same in SDL-1.2 and 2.0, and the RW_ ones don't need
stdio.h.
- Moved Makefile.os2 to the src directory.
---
Makefile.os2 => src/Makefile.os2 | 2 -
src/NMakefile | 36 ++++++++++++++
src/SDL12_compat.c | 80 +++++++++++++++++++++++++-------
src/SDL20_include_wrapper.h | 4 ++
src/SDL20_syms.h | 2 +
5 files changed, 106 insertions(+), 18 deletions(-)
rename Makefile.os2 => src/Makefile.os2 (99%)
create mode 100644 src/NMakefile
diff --git a/Makefile.os2 b/src/Makefile.os2
similarity index 99%
rename from Makefile.os2
rename to src/Makefile.os2
index 4ebd8f5..c9d39e6 100644
--- a/Makefile.os2
+++ b/src/Makefile.os2
@@ -32,8 +32,6 @@ object_files= SDL12_compat.obj
.extensions:
.extensions: .lib .dll .obj .c .asm
-.c: src;
-
.c.obj:
wcc386 $(CFLAGS) -fo=$^@ $<
diff --git a/src/NMakefile b/src/NMakefile
new file mode 100644
index 0000000..5d7b9ad
--- /dev/null
+++ b/src/NMakefile
@@ -0,0 +1,36 @@
+# Makefile for Win32 using MSVC:
+# nmake /f NMakefile
+
+# change INCLUDES so it points to SDL2 headers directory:
+INCLUDES = -Iinclude
+
+CPPFLAGS = -DNDEBUG -DDLL_EXPORT
+
+CC = cl
+LD = link
+RC = rc
+
+CFLAGS = /nologo /O2 /MD /W3 /GS-
+LDFLAGS = /nologo /DLL /NODEFAULTLIB /RELEASE
+LDLIBS = kernel32.lib user32.lib
+
+DLLNAME = SDL.dll
+IMPNAME = SDL.lib
+
+COMPILE=$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES)
+
+OBJ = SDL12_compat.obj
+
+all: $(DLLNAME)
+
+$(DLLNAME): $(OBJ)
+ $(LD) /OUT:$@ $(LDFLAGS) $(OBJ) $(LDLIBS)
+
+.c.obj:
+ $(COMPILE) -Fo$@ -c $<
+
+distclean: clean
+ -del $(DLLNAME)
+ -del $(IMPNAME)
+clean:
+ -del *.obj *.exp *.manifest
diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index 890e398..3369d32 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -38,8 +38,11 @@
#define SDL12_COMPAT_VERSION 50
#include <stdarg.h>
+#ifndef _WIN32
#include <stdio.h> /* fprintf(), etc. */
#include <stdlib.h> /* for abort() */
+#include <string.h>
+#endif
/* mingw headers may define these ... */
#undef strtod
@@ -113,7 +116,7 @@
do { \
static SDL_bool seen = SDL_FALSE; \
if (!seen) { \
- fprintf(stderr, "FIXME: %s (%s, %s:%d)\n", x, __FUNCTION__, __FILE__, __LINE__); \
+ SDL20_Log("FIXME: %s (%s:%d)\n", x, __FUNCTION__, __LINE__); \
seen = SDL_TRUE; \
} \
} while (0)
@@ -770,16 +773,21 @@ static EventQueueType *EventQueueAvailable = NULL;
/* Obviously we can't use SDL_LoadObject() to load SDL2. :) */
+static char loaderror[256];
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#define SDL20_LIBNAME "SDL2.dll"
+ /* require SDL2 >= 2.0.12 for SDL_CreateThread binary compatibility */
+ #define SDL20_REQUIRED_VER SDL_VERSIONNUM(2,0,12)
static HANDLE Loaded_SDL20 = NULL;
#define LoadSDL20Library() ((Loaded_SDL20 = LoadLibraryA(SDL20_LIBNAME)) != NULL)
#define LookupSDL20Sym(sym) GetProcAddress(Loaded_SDL20, sym)
#define CloseSDL20Library() { if (Loaded_SDL20) { FreeLibrary(Loaded_SDL20); Loaded_SDL20 = NULL; } }
+ #define strcpy_fn lstrcpyA
+ #define sprintf_fn wsprintfA
#elif defined(__unix__) || defined(__APPLE__)
#include <dlfcn.h>
#ifdef __APPLE__
@@ -787,13 +795,19 @@ static EventQueueType *EventQueueAvailable = NULL;
#else
#define SDL20_LIBNAME "libSDL2-2.0.so.0"
#endif
+ #define SDL20_REQUIRED_VER SDL_VERSIONNUM(2,0,9)
static void *Loaded_SDL20 = NULL;
#define LoadSDL20Library() ((Loaded_SDL20 = dlopen(SDL20_LIBNAME, RTLD_LOCAL|RTLD_NOW)) != NULL)
#define LookupSDL20Sym(sym) dlsym(Loaded_SDL20, sym)
#define CloseSDL20Library() { if (Loaded_SDL20) { dlclose(Loaded_SDL20); Loaded_SDL20 = NULL; } }
+ #define strcpy_fn strcpy
+ #define sprintf_fn sprintf
#elif defined(__OS2__)
#include <os2.h>
#define SDL20_LIBNAME "SDL2.dll"
+ #define SDL20_REQUIRED_VER SDL_VERSIONNUM(2,0,9)
+ #define strcpy_fn strcpy
+ #define sprintf_fn sprintf
static HMODULE Loaded_SDL20 = NULLHANDLE;
static SDL_bool LoadSDL20Library(void) {
char err[256];
@@ -824,12 +838,8 @@ LoadSDL20Symbol(const char *fn, int *okay)
if (*okay) { /* only bother trying if we haven't previously failed. */
retval = LookupSDL20Sym(fn);
if (retval == NULL) {
- /* Flip to 1 to warn but maybe work if nothing calls that function, flip to zero to fail out. */
- #if 0
- fprintf(stderr, "WARNING: LOAD FAILED: %s\n", fn);
- #else
+ sprintf_fn(loaderror, "%s missing in SDL2 library.", fn);
*okay = 0;
- #endif
}
}
return retval;
@@ -850,22 +860,56 @@ LoadSDL20(void)
if (!Loaded_SDL20)
{
okay = LoadSDL20Library();
+ if (!okay) {
+ strcpy_fn(loaderror, "Failed loading SDL2 library.");
+ }
#define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = (SDL20_##fn##_t) LoadSDL20Symbol("SDL_" #fn, &okay);
#include "SDL20_syms.h"
if (!okay)
UnloadSDL20();
+ else {
+ SDL_version v;
+ SDL20_GetVersion(&v);
+ okay = (SDL_VERSIONNUM(v.major,v.minor,v.patch) >= SDL20_REQUIRED_VER);
+ if (!okay) {
+ sprintf_fn(loaderror, "SDL2 %d.%d.%d library is too old.", v.major, v.minor, v.patch);
+ UnloadSDL20();
+ }
+ }
}
return okay;
}
+#if defined(_WIN32)
+static void error_dialog(const char *errorMsg)
+{
+ MessageBoxA(NULL, errorMsg, "Error", MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
+}
+#elif defined(__APPLE__)
+static void error_dialog(const char *errorMsg)
+{
+ NSString* msg = [NSString stringWithCString:errorMsg encoding:NSASCIIStringEncoding];
+ NSRunCriticalAlertPanel (@"Error", @"%@", @"OK", nil, nil, msg);
+}
+#else
+static void error_dialog(const char *errorMsg)
+{
+ fprintf(stderr, "%s\n", errorMsg);
+}
+#endif
+
#if defined(__GNUC__)
static void dllinit(void) __attribute__((constructor));
static void dllinit(void)
{
if (!LoadSDL20()) {
- fprintf(stderr, "ERROR: sdl12-compat failed to load SDL 2.0! Aborting!\n");
- fflush(stderr);
+ error_dialog(loaderror);
+ #ifdef _WIN32
+ TerminateProcess(GetCurrentProcess(), 42);
+ ExitProcess(42);
+ #else
abort();
+ #endif
}
}
static void dllquit(void) __attribute__((destructor));
@@ -875,7 +919,11 @@ static void dllquit(void)
}
#elif defined(_MSC_VER) && defined(_WIN32)
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
+#ifndef __FLTUSED__
+#define __FLTUSED__
+__declspec(selectany) int _fltused = 1;
+#endif
+BOOL WINAPI _DllMainCRTStartup(HANDLE dllhandle, DWORD reason, LPVOID reserved)
{
switch (reason) {
case DLL_PROCESS_DETACH:
@@ -884,6 +932,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
case DLL_PROCESS_ATTACH: /* init once for each new process */
if (!LoadSDL20()) {
+ error_dialog(loaderror);
return FALSE;
}
break;
@@ -902,7 +951,7 @@ unsigned _System LibMain(unsigned hmod, unsigned termination)
if (termination) {
UnloadSDL20();
} else if (!LoadSDL20()) {
- fprintf(stderr, "ERROR: SDL12-compat failed to load SDL2.dll\n");
+ error_dialog(loaderror);
return 0;
}
return 1;
@@ -3968,9 +4017,8 @@ DECLSPEC void SDLCALL
SDL_KillThread(SDL_Thread *thread)
{
FIXME("Removed from 2.0; do nothing. We can't even report failure.");
- fprintf(stderr,
- "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
- "This program should be fixed. No thread was actually harmed.\n");
+ SDL20_Log("WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
+ "This program should be fixed. No thread was actually harmed.\n");
}
typedef struct SDL12_TimerID_Data
@@ -4173,15 +4221,15 @@ RWops12to20_size(struct SDL_RWops *rwops20)
if (size != -1)
return size;
- pos = rwops12->seek(rwops12, 0, SEEK_CUR);
+ pos = rwops12->seek(rwops12, 0, RW_SEEK_CUR);
if (pos == -1)
return -1;
- size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
+ size = (Sint64) rwops12->seek(rwops12, 0, RW_SEEK_END);
if (size == -1)
return -1;
- rwops12->seek(rwops12, pos, SEEK_SET); FIXME("...and if this fails?");
+ rwops12->seek(rwops12, pos, RW_SEEK_SET); FIXME("...and if this fails?");
rwops20->hidden.unknown.data2 = (void *) ((size_t) size);
return size;
}
diff --git a/src/SDL20_include_wrapper.h b/src/SDL20_include_wrapper.h
index 2be86ab..b3816a7 100644
--- a/src/SDL20_include_wrapper.h
+++ b/src/SDL20_include_wrapper.h
@@ -28,6 +28,8 @@
#ifndef _INCL_SDL20_INCLUDE_WRAPPER_H_
#define _INCL_SDL20_INCLUDE_WRAPPER_H_
+#define SDL_GetVersion IGNORE_THIS_VERSION_OF_SDL_GetVersion
+#define SDL_Log IGNORE_THIS_VERSION_OF_SDL_Log
#define SDL_ReportAssertion IGNORE_THIS_VERSION_OF_SDL_ReportAssertion
#define SDL_SetError IGNORE_THIS_VERSION_OF_SDL_SetError
#define SDL_PollEvent IGNORE_THIS_VERSION_OF_SDL_PollEvent
@@ -129,6 +131,8 @@ typedef void (__cdecl *pfnSDL_CurrentEndThread) (unsigned);
#undef CreateMutex
#endif /* _WIN32 */
+#undef SDL_Log
+#undef SDL_GetVersion
#undef SDL_ReportAssertion
#undef SDL_SetError
#undef SDL_PollEvent
diff --git a/src/SDL20_syms.h b/src/SDL20_syms.h
index 4287602..752cc4f 100644
--- a/src/SDL20_syms.h
+++ b/src/SDL20_syms.h
@@ -33,6 +33,8 @@
#define SDL20_SYM_VARARGS(rc,fn,params) SDL20_SYM(rc,fn,params,unused,unused)
#endif
+SDL20_SYM(void,GetVersion,(SDL_version *a),(a),)
+SDL20_SYM_VARARGS(void,Log,(const char *fmt, ...))
SDL20_SYM(int,Init,(Uint32 a),(a),return)
SDL20_SYM(int,InitSubSystem,(Uint32 a),(a),return)
SDL20_SYM(Uint32,WasInit,(Uint32 a),(a),return)