From a30008d6b89774292984d3a788bd656e3299901d Mon Sep 17 00:00:00 2001 From: Andrei Drexler Date: Wed, 15 Nov 2023 20:48:16 +0100 Subject: [PATCH] Add basic support for KEX (version 6) savefiles --- Quake/common.c | 114 +++++++++++++++++++++++++++-------------------- Quake/common.h | 3 +- Quake/host_cmd.c | 33 ++++++++++++-- Quake/progs.h | 3 +- 4 files changed, 100 insertions(+), 53 deletions(-) diff --git a/Quake/common.c b/Quake/common.c index be7d53c4c..bd680cffb 100644 --- a/Quake/common.c +++ b/Quake/common.c @@ -2375,9 +2375,9 @@ void COM_AddGameDirectory (const char *dir) } } -void COM_ResetGameDirectories(char *newgamedirs) +void COM_ResetGameDirectories(const char *newgamedirs) { - char *newpath, *path; + const char *newpath, *path; searchpath_t *search; //Kill the extra game if it is loaded while (com_searchpaths != com_base_searchpaths) @@ -2424,11 +2424,73 @@ void COM_ResetGameDirectories(char *newgamedirs) //============================================================================== //johnfitz -- dynamic gamedir stuff -- modified by QuakeSpasm team. //============================================================================== + +/* +================= +COM_SwitchGame +================= +*/ +void COM_SwitchGame (const char *paths) +{ + extern cvar_t max_edicts; + if (!q_strcasecmp(paths, COM_GetGameNames(true))) + { + Con_Printf("\"game\" is already \"%s\"\n", COM_GetGameNames(true)); + return; + } + + Host_WaitForSaveThread (); + + com_modified = true; + + //Kill the server + CL_Disconnect (); + Host_ShutdownServer(true); + + //Write config file + Host_WriteConfiguration (); + + // stop parsing map files before changing file system search paths + ExtraMaps_Clear (); + + COM_ResetGameDirectories(paths); + + //clear out and reload appropriate data + Cache_Flush (); + Mod_ResetAll(); + Sky_ClearAll(); + if (!isDedicated) + { + TexMgr_NewGame (); + Draw_NewGame (); + R_NewGame (); + } + ExtraMaps_Init (); + Host_Resetdemos (); + DemoList_Rebuild (); + SaveList_Rebuild (); + SkyList_Rebuild (); + M_CheckMods (); + Cvar_SetQuick (&max_edicts, max_edicts.default_string); + + Con_Printf("\n%s\n\"game\" changed to \"%s\"\n", Con_Quakebar (40), COM_GetGameNames(true)); + + VID_Lock (); + Cbuf_AddText ("unaliasall\n"); + Cbuf_AddText ("exec quake.rc\n"); + Cbuf_AddText ("vid_unlock\n"); +} + + +/* +================= +COM_Game_f +================= +*/ static void COM_Game_f (void) { if (Cmd_Argc() > 1) { - extern cvar_t max_edicts; int i, pri; char paths[1024]; @@ -2471,52 +2533,8 @@ static void COM_Game_f (void) } } - if (!q_strcasecmp(paths, COM_GetGameNames(true))) - { - Con_Printf("\"game\" is already \"%s\"\n", COM_GetGameNames(true)); - return; - } + COM_SwitchGame (paths); - Host_WaitForSaveThread (); - - com_modified = true; - - //Kill the server - CL_Disconnect (); - Host_ShutdownServer(true); - - //Write config file - Host_WriteConfiguration (); - - // stop parsing map files before changing file system search paths - ExtraMaps_Clear (); - - COM_ResetGameDirectories(paths); - - //clear out and reload appropriate data - Cache_Flush (); - Mod_ResetAll(); - Sky_ClearAll(); - if (!isDedicated) - { - TexMgr_NewGame (); - Draw_NewGame (); - R_NewGame (); - } - ExtraMaps_Init (); - Host_Resetdemos (); - DemoList_Rebuild (); - SaveList_Rebuild (); - SkyList_Rebuild (); - M_CheckMods (); - Cvar_SetQuick (&max_edicts, max_edicts.default_string); - - Con_Printf("\n%s\n\"game\" changed to \"%s\"\n", Con_Quakebar (40), COM_GetGameNames(true)); - - VID_Lock (); - Cbuf_AddText ("unaliasall\n"); - Cbuf_AddText ("exec quake.rc\n"); - Cbuf_AddText ("vid_unlock\n"); } else //Diplay the current gamedir Con_Printf("\"game\" is \"%s\"\n", COM_GetGameNames(true)); diff --git a/Quake/common.h b/Quake/common.h index 010b912fd..8d84d2ce7 100644 --- a/Quake/common.h +++ b/Quake/common.h @@ -296,8 +296,9 @@ void COM_Init (void); void COM_InitArgv (int argc, char **argv); void COM_InitFilesystem (void); -void COM_ResetGameDirectories (char *newgamedirs); +void COM_ResetGameDirectories (const char *newgamedirs); void COM_AddGameDirectory (const char *dir); +void COM_SwitchGame (const char *paths); const char *COM_SkipPath (const char *pathname); void COM_StripExtension (const char *in, char *out, size_t outsize); diff --git a/Quake/host_cmd.c b/Quake/host_cmd.c index 9eafbbea0..78c968d58 100644 --- a/Quake/host_cmd.c +++ b/Quake/host_cmd.c @@ -1306,6 +1306,15 @@ void Modlist_ShutDown (void) } } +qboolean Modlist_IsInstalled (const char *game) +{ + filelist_item_t *item; + for (item = modlist; item; item = item->next) + if (q_strcasecmp (item->name, game) == 0 && Modlist_GetStatus (item) == MODSTATUS_INSTALLED) + return true; + return false; +} + //============================================================================== //ericw -- demo list management //============================================================================== @@ -2519,14 +2528,32 @@ static void Host_Loadgame_f (void) data = start; data = COM_ParseIntNewline (data, &version); - if (version != SAVEGAME_VERSION) + if (version == SAVEGAME_VERSION_KEX) + { + extern char com_gamenames[]; + const char *game = *com_gamenames ? com_gamenames : GAMENAME; + data = COM_ParseStringNewline (data); + if (strcmp (game, com_token) != 0) + { + if (!Modlist_IsInstalled (com_token)) + { + Con_Printf ("ERROR: mod \"%s\" is not installed.\n"); + return; + } + COM_SwitchGame (com_token); + Cbuf_Execute (); + if (key_dest == key_menu) + M_ToggleMenu_f (); + } + } + else if (version != SAVEGAME_VERSION) { free (start); start = NULL; if (sv.autoloading) - Con_Printf ("ERROR: Savegame is version %i, not %i\n", version, SAVEGAME_VERSION); + Con_Printf ("ERROR: Savegame is version %i, not %i or %i\n", version, SAVEGAME_VERSION, SAVEGAME_VERSION_KEX); else - Host_Error ("Savegame is version %i, not %i", version, SAVEGAME_VERSION); + Host_Error ("Savegame is version %i, not %i or %i", version, SAVEGAME_VERSION, SAVEGAME_VERSION_KEX); Host_InvalidateSave (relname); SCR_EndLoadingPlaque (); return; diff --git a/Quake/progs.h b/Quake/progs.h index 9d9c2a176..7e2b4a4cc 100644 --- a/Quake/progs.h +++ b/Quake/progs.h @@ -279,7 +279,8 @@ typedef struct savedata_s int buffersize; } savedata_t; -#define SAVEGAME_VERSION 5 +#define SAVEGAME_VERSION 5 +#define SAVEGAME_VERSION_KEX 6 extern THREAD_LOCAL globalvars_t *pr_global_struct; extern THREAD_LOCAL qcvm_t *qcvm;