diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index f63b74bd2..b07baa6da 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -1274,52 +1274,56 @@ static int STACK_ARGS sortcvars (const void *a, const void *b) void FilterCompactCVars (TArray &cvars, DWORD filter) { - FBaseCVar *cvar = CVars; - while (cvar) + // Accumulate all cvars that match the filter flags. + for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->m_Next) { if (cvar->Flags & filter) - cvars.Push (cvar); - cvar = cvar->m_Next; + cvars.Push(cvar); } - if (cvars.Size () > 0) + // Now sort them, so they're in a deterministic order and not whatever + // order the linker put them in. + if (cvars.Size() > 0) { - cvars.ShrinkToFit (); - qsort (&cvars[0], cvars.Size(), sizeof(FBaseCVar *), sortcvars); + qsort(&cvars[0], cvars.Size(), sizeof(FBaseCVar *), sortcvars); } } void C_WriteCVars (BYTE **demo_p, DWORD filter, bool compact) { - FBaseCVar *cvar = CVars; - BYTE *ptr = *demo_p; + FString dump = C_GetMassCVarString(filter, compact); + size_t dumplen = dump.Len() + 1; // include terminating \0 + memcpy(*demo_p, dump.GetChars(), dumplen); + *demo_p += dumplen; +} + +FString C_GetMassCVarString (DWORD filter, bool compact) +{ + FBaseCVar *cvar; + FString dump; if (compact) { TArray cvars; - ptr += sprintf ((char *)ptr, "\\\\%ux", filter); - FilterCompactCVars (cvars, filter); + dump.AppendFormat("\\\\%ux", filter); + FilterCompactCVars(cvars, filter); while (cvars.Pop (cvar)) { - UCVarValue val = cvar->GetGenericRep (CVAR_String); - ptr += sprintf ((char *)ptr, "\\%s", val.String); + UCVarValue val = cvar->GetGenericRep(CVAR_String); + dump << '\\' << val.String; } } else { - cvar = CVars; - while (cvar) + for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) { if ((cvar->Flags & filter) && !(cvar->Flags & CVAR_NOSAVE)) { - UCVarValue val = cvar->GetGenericRep (CVAR_String); - ptr += sprintf ((char *)ptr, "\\%s\\%s", - cvar->GetName (), val.String); + UCVarValue val = cvar->GetGenericRep(CVAR_String); + dump << '\\' << cvar->GetName() << '\\' << val.String; } - cvar = cvar->m_Next; } } - - *demo_p = ptr + 1; + return dump; } void C_ReadCVars (BYTE **demo_p) diff --git a/src/c_cvars.h b/src/c_cvars.h index b5b0c6ccf..9c7873802 100644 --- a/src/c_cvars.h +++ b/src/c_cvars.h @@ -150,7 +150,7 @@ private: static bool m_UseCallback; static bool m_DoNoSet; - friend void C_WriteCVars (BYTE **demo_p, uint32 filter, bool compact); + friend FString C_GetMassCVarString (uint32 filter, bool compact); friend void C_ReadCVars (BYTE **demo_p); friend void C_BackupCVars (void); friend FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev); @@ -162,6 +162,10 @@ private: friend void C_DeinitConsole(); }; +// Returns a string with all cvars whose flags match filter. In compact mode, +// the cvar names are omitted to save space. +FString C_GetMassCVarString (uint32 filter, bool compact=false); + // Writes all cvars that could effect demo sync to *demo_p. These are // cvars that have either CVAR_SERVERINFO or CVAR_DEMOSAVE set. void C_WriteCVars (BYTE **demo_p, uint32 filter, bool compact=false); diff --git a/src/g_game.cpp b/src/g_game.cpp index 1f039763b..e9d11151c 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2096,11 +2096,8 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio G_WriteHubInfo(stdfile); { - BYTE vars[4096], *vars_p; - vars_p = vars; - C_WriteCVars (&vars_p, CVAR_SERVERINFO); - *vars_p = 0; - M_AppendPNGText (stdfile, "Important CVARs", (char *)vars); + FString vars = C_GetMassCVarString(CVAR_SERVERINFO); + M_AppendPNGText (stdfile, "Important CVARs", vars.GetChars()); } if (level.time != 0 || level.maptime != 0)