engine: implement change game with execv in-engine. For now it enabled for all platforms, will probably disabled selectively

This commit is contained in:
Alibek Omarov 2022-06-13 03:42:20 +03:00
parent df83b155a1
commit e6a2c207de
2 changed files with 73 additions and 2 deletions

View File

@ -305,7 +305,9 @@ void Host_NewInstance( const char *name, const char *finalmsg )
host.change_game = true;
Q_strncpy( host.finalmsg, finalmsg, sizeof( host.finalmsg ));
pChangeGame( name ); // call from hl.exe
if( !Platform_ChangeGame( name ))
pChangeGame( name ); // call from hl.exe
}
/*
@ -868,7 +870,7 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
host.enabledll = !Sys_CheckParm( "-nodll" );
host.change_game = bChangeGame;
host.change_game = bChangeGame || Sys_CheckParm( "-changegame" );
host.config_executed = false;
host.status = HOST_INIT; // initialzation started

View File

@ -32,9 +32,14 @@ GNU General Public License for more details.
#endif
#endif
#if XASH_WIN32
#include <process.h>
#endif
#include "menu_int.h" // _UPDATE_PAGE macro
#include "library.h"
#include "whereami.h"
qboolean error_on_exit = false; // arg for exit();
#define DEBUG_BREAK
@ -539,3 +544,67 @@ void Sys_Print( const char *pMsg )
Rcon_Print( pMsg );
}
/*
==================
Sys_ChangeGame
This is a special function
Here we restart engine with new -game parameter
but since engine will be unloaded during this call
it explicitly doesn't use internal allocation or string copy utils
==================
*/
qboolean Sys_ChangeGame( const char *gamedir )
{
int i = 0;
qboolean replacedArg = false;
size_t exelen;
char *exe, **newargs;
// don't use engine allocation utils here
// they will be freed after Host_Shutdown
newargs = calloc( host.argc + 4, sizeof( *newargs ));
while( i < host.argc )
{
newargs[i] = strdup( host.argv[i] );
// replace existing -game argument
if( !Q_stricmp( newargs[i], "-game" ))
{
newargs[i + 1] = strdup( gamedir );
replacedArg = true;
i += 2;
}
else i++;
}
if( !replacedArg )
{
newargs[i++] = strdup( "-game" );
newargs[i++] = strdup( gamedir );
}
newargs[i++] = strdup( "-changegame" );
newargs[i] = NULL;
exelen = wai_getExecutablePath( NULL, 0, NULL );
exe = malloc( exelen + 1 );
wai_getExecutablePath( exe, exelen, NULL );
exe[exelen] = 0;
Host_Shutdown();
execv( exe, newargs );
// if execv returned, it's probably an error
printf( "execv failed: %s", strerror( errno ));
for( ; i >= 0; i-- )
free( newargs[i] );
free( newargs );
free( exe );
return false;
}