dhewm3/neo/sys/win32/SDL_win32_main.c
Daniel Gibson 6181f24c44 SDL3: Now works on Windows as well
Refactored the pseudo-custom SDL_main code a bit: SDL_win32_main.c
is now only used for SDL1.2, SDL2 and SDL3 have a WinMain() function
in win_main.cpp that works pretty much like the SDL2 SDL_main or SDL3
SDL_RunApp() code - except that the argv[] strings passed to the Doom3
main() function (now renamed to SDL_main()) are encoded in ANSI instead
of UTF-8, so paths passed as commandline arguments, like
 dhewm3 +set fs_basepath C:\SüperGämes\Doom3
work with the Win32 ANSI function used by Doom3 to handle paths and files.

For this I also moved the stdout/stderr redirection code from
SDL_win32_main.c to win_main.cpp and cleaned it up a bit
2024-10-09 17:37:08 +02:00

303 lines
6.6 KiB
C

/*
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 <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <sys/stat.h>
#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)
#else
# define DIR_SEPERATOR TEXT("/")
# include <direct.h>
#endif
/* Include the SDL main definition header */
#include "SDL.h"
#include "SDL_main.h"
#ifdef main
# ifndef _WIN32_WCE_EMULATION
# undef main
# endif /* _WIN32_WCE_EMULATION */
#endif /* main */
/* The standard output files */
#define STDOUT_FILE TEXT("dhewm3log.txt") /* DG: renamed this */
#define STDERR_FILE TEXT("stderr.txt")
/* Set a variable to tell if the stdio redirect has been enabled. */
static int stdioRedirectEnabled = 0;
#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
#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'))
#endif /* _WIN32_WCE < 300 */
static void UnEscapeQuotes( char *arg )
{
char *last = NULL;
while( *arg ) {
if( *arg == '"' && *last == '\\' ) {
char *c_curr = arg;
char *c_last = last;
while( *c_curr ) {
*c_last = *c_curr;
c_last = c_curr;
c_curr++;
}
*c_last = '\0';
}
last = arg;
arg++;
}
}
/* Parse a command line buffer into arguments */
static int ParseCommandLine(char *cmdline, char **argv)
{
char *bufp;
char *lastp = NULL;
int argc, last_argc;
argc = last_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 != '"' || *lastp == '\\' ) ) {
lastp = 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;
}
/* Strip out \ from \" sequences */
if( argv && last_argc != argc ) {
UnEscapeQuotes( argv[last_argc] );
}
last_argc = argc;
}
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;
}
/* SDL_Quit() shouldn't be used with atexit() directly because
calling conventions may differ... */
static void cleanup(void)
{
SDL_Quit();
}
#if 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[])
{
size_t n;
char *bufp, *appname;
int status;
/* Get the class name from argv[0] */
appname = argv[0];
if ( (bufp=SDL_strrchr(argv[0], '\\')) != NULL ) {
appname = bufp+1;
} else
if ( (bufp=SDL_strrchr(argv[0], '/')) != NULL ) {
appname = bufp+1;
}
if ( (bufp=SDL_strrchr(appname, '.')) == NULL )
n = SDL_strlen(appname);
else
n = (bufp-appname);
bufp = SDL_stack_alloc(char, n+1);
if ( bufp == NULL ) {
return OutOfMemory();
}
SDL_strlcpy(bufp, appname, n+1);
appname = bufp;
/* Load SDL dynamic link library */
if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) {
ShowError("WinMain() error", SDL_GetError());
return(FALSE);
}
atexit(cleanup_output);
atexit(cleanup);
#if !SDL_VERSION_ATLEAST(2, 0, 0)
/* 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
/* Run the application main() code */
status = SDL_main(argc, argv);
/* Exit cleanly, calling atexit() functions */
exit(status);
/* Hush little compiler, don't you cry... */
return 0;
}
/* 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;
char *env_str;
#ifdef _WIN32_WCE
wchar_t *bufp;
int nLen;
#else
char *bufp;
size_t nLen;
#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);
}
#if 0 // DG: output redirection is now done in dhewm3's main() aka SDL_main()
/* Check for stdio redirect settings and do the redirection */
if ((env_str = SDL_getenv("SDL_STDIO_REDIRECT"))) {
if (SDL_atoi(env_str)) {
redirect_output();
}
}
#ifndef NO_STDIO_REDIRECT
else {
redirect_output();
}
#endif
#endif // 0
#ifdef _WIN32_WCE
nLen = wcslen(szCmdLine)+128+1;
bufp = SDL_stack_alloc(wchar_t, 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 = SDL_stack_alloc(char, nLen);
if ( cmdline == NULL ) {
return OutOfMemory();
}
WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL);
#else
/* Grab the command line */
bufp = GetCommandLine();
nLen = SDL_strlen(bufp)+1;
cmdline = SDL_stack_alloc(char, nLen);
if ( cmdline == NULL ) {
return OutOfMemory();
}
SDL_strlcpy(cmdline, bufp, nLen);
#endif
/* Parse it into argv and argc */
argc = ParseCommandLine(cmdline, NULL);
argv = SDL_stack_alloc(char*, argc+1);
if ( argv == NULL ) {
return OutOfMemory();
}
ParseCommandLine(cmdline, argv);
/* Run the main program (after a little SDL initialization) */
console_main(argc, argv);
/* Hush little compiler, don't you cry... */
return 0;
}