From 07a9c4602daa8527e8b52456ce3a2072004a8e6c Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 9 Jun 2022 13:42:16 +0300 Subject: [PATCH] game_launch: change game with execve on supported platforms --- engine/common/launcher.c | 77 +++++++++++++++++++++++++--------------- game_launch/game.cpp | 69 ++++++++++++++++++++++------------- 2 files changed, 93 insertions(+), 53 deletions(-) diff --git a/engine/common/launcher.c b/engine/common/launcher.c index 7f85ff06..85e71d6a 100644 --- a/engine/common/launcher.c +++ b/engine/common/launcher.c @@ -25,63 +25,82 @@ GNU General Public License for more details. #include #endif -#if XASH_WIN32 -#define XASH_NOCONHOST 1 -#endif - static char szGameDir[128]; // safe place to keep gamedir static int g_iArgc; static char **g_pszArgv; +#if XASH_WIN32 || XASH_POSIX +#define USE_EXECVE_FOR_CHANGE_GAME 1 +#else +#define USE_EXECVE_FOR_CHANGE_GAME 0 +#endif + +#define E_GAME "XASH3D_GAME" // default env dir to start from +#define GAME_PATH "valve" // default dir to start from + void Launcher_ChangeGame( const char *progname ) { +#if USE_EXECVE_FOR_CHANGE_GAME + Host_Shutdown(); + +#if XASH_WIN32 + _putenv_s( E_GAME, progname ); + _execve( szArgv[0], szArgv, environ ); +#else + char envstr[256]; + snprintf( envstr, sizeof( envstr ), E_GAME "=%s", progname ); + putenv( envstr ); + execve( szArgv[0], szArgv, environ ); +#endif + +#else Q_strncpy( szGameDir, progname, sizeof( szGameDir ) - 1 ); Host_Shutdown( ); exit( Host_Main( g_iArgc, g_pszArgv, szGameDir, 1, &Launcher_ChangeGame ) ); +#endif } -#if XASH_NOCONHOST +#if XASH_WIN32 #include #include // CommandLineToArgvW int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int nShow) { - int szArgc; - char **szArgv; - LPWSTR* lpArgv = CommandLineToArgvW(GetCommandLineW(), &szArgc); - int i = 0; + LPWSTR* lpArgv; + int ret, i; - szArgv = (char**)malloc(szArgc*sizeof(char*)); - for (; i < szArgc; ++i) + lpArgv = CommandLineToArgvW( GetCommandLineW(), &szArgc ); + szArgv = ( char** )malloc( (szArgc + 1) * sizeof( char* )); + + for( i = 0; i < szArgc; ++i ) { size_t size = wcslen(lpArgv[i]) + 1; - szArgv[i] = (char*)malloc(size); - wcstombs(szArgv[i], lpArgv[i], size); + + // just in case, allocate some more memory + szArgv[i] = ( char * )malloc( size * sizeof( wchar_t )); + wcstombs( szArgv[i], lpArgv[i], size ); } - szArgv[i] = NULL; + szArgv[szArgc] = 0; - LocalFree(lpArgv); + LocalFree( lpArgv ); - main( szArgc, szArgv ); + ret = main( szArgc, szArgv ); for( i = 0; i < szArgc; ++i ) free( szArgv[i] ); free( szArgv ); + + return ret; } -#endif +#endif // XASH_WIN32 + int main( int argc, char** argv ) { - char gamedir_buf[32] = ""; - const char *gamedir = getenv( "XASH3D_GAMEDIR" ); + const char *game = getenv( E_GAME ); - if( !COM_CheckString( gamedir ) ) - { - gamedir = "valve"; - } - else - { - Q_strncpy( gamedir_buf, gamedir, 32 ); - gamedir = gamedir_buf; - } + if( !game ) + game = GAME_PATH; + + Q_strncpy( szGameDir, gamedir, sizeof( szGameDir )); #if XASH_EMSCRIPTEN #ifdef EMSCRIPTEN_LIB_FS @@ -108,7 +127,7 @@ int main( int argc, char** argv ) IOS_LaunchDialog(); } #endif - return Host_Main( g_iArgc, g_pszArgv, gamedir, 0, &Launcher_ChangeGame ); + return Host_Main( g_iArgc, g_pszArgv, szGameDir, 0, &Launcher_ChangeGame ); } #endif diff --git a/game_launch/game.cpp b/game_launch/game.cpp index 7b637989..78d53b84 100644 --- a/game_launch/game.cpp +++ b/game_launch/game.cpp @@ -14,24 +14,25 @@ GNU General Public License for more details. */ #include "port.h" +#include "build.h" #include #include #include #include +#include -#if defined(__APPLE__) || defined(__unix__) || defined(__HAIKU__) - #define XASHLIB "libxash." OS_LIB_EXT -#elif _WIN32 - #if !__MINGW32__ && _MSC_VER >= 1200 - #define USE_WINMAIN - #endif - #define XASHLIB "xash.dll" - #define dlerror() GetStringLastError() - #include // CommandLineToArgvW +#if XASH_POSIX +#define XASHLIB "libxash." OS_LIB_EXT +#elif XASH_WIN32 +#define XASHLIB "xash.dll" +#define dlerror() GetStringLastError() +#include // CommandLineToArgvW +#else +#error // port me! #endif -#ifdef WIN32 +#ifdef XASH_WIN32 extern "C" { // Enable NVIDIA High Performance Graphics while using Integrated Graphics. @@ -42,6 +43,12 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } #endif +#if XASH_WIN32 || XASH_POSIX +#define USE_EXECVE_FOR_CHANGE_GAME 1 +#else +#define USE_EXECVE_FOR_CHANGE_GAME 0 +#endif + #define E_GAME "XASH3D_GAME" // default env dir to start from #define GAME_PATH "valve" // default dir to start from @@ -54,7 +61,7 @@ static pfnShutdown Xash_Shutdown = NULL; static char szGameDir[128]; // safe place to keep gamedir static int szArgc; static char **szArgv; -static HINSTANCE hEngine; +static HINSTANCE hEngine; static void Xash_Error( const char *szFmt, ... ) { @@ -70,6 +77,7 @@ static void Xash_Error( const char *szFmt, ... ) #else fprintf( stderr, "Xash Error: %s\n", buffer ); #endif + exit( 1 ); } @@ -116,32 +124,44 @@ static void Sys_ChangeGame( const char *progname ) if( !progname || !progname[0] ) Xash_Error( "Sys_ChangeGame: NULL gamedir" ); +#if USE_EXECVE_FOR_CHANGE_GAME +#if XASH_WIN32 + _putenv_s( E_GAME, progname ); + + Sys_UnloadEngine(); + _execve( szArgv[0], szArgv, environ ); +#else + char envstr[256]; + snprintf( envstr, sizeof( envstr ), E_GAME "=%s", progname ); + putenv( envstr ); + + Sys_UnloadEngine(); + execve( szArgv[0], szArgv, environ ); +#endif +#else if( Xash_Shutdown == NULL ) Xash_Error( "Sys_ChangeGame: missed 'Host_Shutdown' export\n" ); + Sys_UnloadEngine(); strncpy( szGameDir, progname, sizeof( szGameDir ) - 1 ); - - Sys_UnloadEngine (); Sys_LoadEngine (); - Xash_Main( szArgc, szArgv, szGameDir, 1, Sys_ChangeGame ); +#endif } _inline int Sys_Start( void ) { int ret; pfnChangeGame changeGame = NULL; + const char *game = getenv( E_GAME ); + + if( !game ) + game = GAME_PATH; Sys_LoadEngine(); -#ifndef XASH_DISABLE_MENU_CHANGEGAME if( Xash_Shutdown ) changeGame = Sys_ChangeGame; -#endif - - const char *game = getenv( E_GAME ); - if( !game ) - game = GAME_PATH; ret = Xash_Main( szArgc, szArgv, game, 0, changeGame ); @@ -150,7 +170,7 @@ _inline int Sys_Start( void ) return ret; } -#ifndef USE_WINMAIN +#if !XASH_WIN32 int main( int argc, char **argv ) { szArgc = argc; @@ -159,7 +179,6 @@ int main( int argc, char **argv ) return Sys_Start(); } #else -//#pragma comment(lib, "shell32.lib") int __stdcall WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int nShow ) { LPWSTR* lpArgv; @@ -170,8 +189,10 @@ int __stdcall WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int for( i = 0; i < szArgc; ++i ) { - int size = wcslen(lpArgv[i]) + 1; - szArgv[i] = ( char* )malloc( size ); + size_t size = wcslen(lpArgv[i]) + 1; + + // just in case, allocate some more memory + szArgv[i] = ( char * )malloc( size * sizeof( wchar_t )); wcstombs( szArgv[i], lpArgv[i], size ); } szArgv[szArgc] = 0;