From 479616a80fa1bed6e63e051749b26ee4097b7e9d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 22 Oct 2022 00:12:17 +0200 Subject: [PATCH] - got new CVar system from GZDoom. --- source/common/2d/v_draw.cpp | 2 +- source/common/audio/music/i_music.cpp | 6 +- source/common/audio/music/music.cpp | 10 +- source/common/audio/sound/i_sound.cpp | 6 +- source/common/audio/sound/s_reverbedit.cpp | 6 +- source/common/console/c_console.cpp | 19 +- source/common/console/c_cvars.cpp | 209 +++++++++++------- source/common/console/c_cvars.h | 169 ++++++++++++-- source/common/engine/m_joy.cpp | 6 +- source/common/engine/serializer.cpp | 2 +- source/common/menu/menu.cpp | 2 +- source/common/objects/autosegs.cpp | 1 + source/common/objects/autosegs.h | 4 + source/common/platform/win32/gl_sysfb.cpp | 2 +- source/common/platform/win32/i_input.cpp | 2 +- source/common/rendering/v_video.cpp | 2 +- source/common/scripting/backend/codegen.cpp | 8 +- source/common/scripting/vm/vmframe.cpp | 3 +- .../libsmackerdec/include/BitReader.h | 2 +- source/core/ct_chat.cpp | 2 +- source/core/gamecontrol.cpp | 14 +- source/core/gamecontrol.h | 2 +- source/core/savegamehelp.cpp | 4 +- source/games/duke/src/game.cpp | 2 +- source/games/duke/src/gamedef.cpp | 2 +- 25 files changed, 323 insertions(+), 164 deletions(-) diff --git a/source/common/2d/v_draw.cpp b/source/common/2d/v_draw.cpp index f78446fc8..7c1beb0c8 100644 --- a/source/common/2d/v_draw.cpp +++ b/source/common/2d/v_draw.cpp @@ -864,7 +864,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double parms->top = INT_MAX; parms->destwidth = INT_MAX; parms->destheight = INT_MAX; - parms->Alpha = type == DrawTexture_Fill ? fillalpha : 1.f; + parms->Alpha = type == DrawTexture_Fill ? (float)fillalpha : 1.f; parms->fillcolor = type == DrawTexture_Fill ? fill : PalEntry(~0u); parms->TranslationId = -1; parms->colorOverlay = 0; diff --git a/source/common/audio/music/i_music.cpp b/source/common/audio/music/i_music.cpp index 453ea7077..0bc858292 100644 --- a/source/common/audio/music/i_music.cpp +++ b/source/common/audio/music/i_music.cpp @@ -222,11 +222,11 @@ void I_InitMusic(void) { I_InitSoundFonts(); - snd_musicvolume.Callback (); + snd_musicvolume->Callback (); nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound"); - snd_mididevice.Callback(); + snd_mididevice->Callback(); ZMusicCallbacks callbacks{}; @@ -257,7 +257,7 @@ void I_SetRelativeVolume(float vol) { relative_volume = (float)vol; ChangeMusicSetting(zmusic_relative_volume, nullptr, (float)vol); - snd_musicvolume.Callback(); + snd_musicvolume->Callback(); } //========================================================================== // diff --git a/source/common/audio/music/music.cpp b/source/common/audio/music/music.cpp index 37617761e..3da91a6e9 100644 --- a/source/common/audio/music/music.cpp +++ b/source/common/audio/music/music.cpp @@ -241,15 +241,15 @@ static bool S_StartMusicPlaying(ZMusic_MusicStream song, bool loop, float rel_vo } ZMusic_Stop(song); // make sure the volume modifiers update properly in case replay gain settings have changed. - fluid_gain.Callback(); - mod_dumb_mastervolume.Callback(); + fluid_gain->Callback(); + mod_dumb_mastervolume->Callback(); if (!ZMusic_Start(song, subsong, loop)) { return false; } // Notify the sound system of the changed relative volume - snd_musicvolume.Callback(); + snd_musicvolume->Callback(); return true; } @@ -517,8 +517,8 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const { mus_playing.replayGain = 0.f; mus_playing.replayGainFactor = dBToAmplitude(mus_gainoffset); - fluid_gain.Callback(); - mod_dumb_mastervolume.Callback(); + fluid_gain->Callback(); + mod_dumb_mastervolume->Callback(); if (!mus_usereplaygain) return; FileReader reader = mus_cb.OpenMusic(musicname); diff --git a/source/common/audio/sound/i_sound.cpp b/source/common/audio/sound/i_sound.cpp index 829c942c5..efd8a06e1 100644 --- a/source/common/audio/sound/i_sound.cpp +++ b/source/common/audio/sound/i_sound.cpp @@ -99,8 +99,8 @@ CUSTOM_CVAR(Float, snd_mastervolume, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVA self = 1.f; ChangeMusicSetting(zmusic_snd_mastervolume, nullptr, self); - snd_sfxvolume.Callback(); - snd_musicvolume.Callback(); + snd_sfxvolume->Callback(); + snd_musicvolume->Callback(); } //========================================================================== @@ -283,7 +283,7 @@ void I_InitSound () GSnd = new NullSoundRenderer; Printf (TEXTCOLOR_RED"Sound init failed. Using nosound.\n"); } - snd_sfxvolume.Callback (); + snd_sfxvolume->Callback (); } diff --git a/source/common/audio/sound/s_reverbedit.cpp b/source/common/audio/sound/s_reverbedit.cpp index 9787ffa8c..a8ce5ac0d 100644 --- a/source/common/audio/sound/s_reverbedit.cpp +++ b/source/common/audio/sound/s_reverbedit.cpp @@ -469,12 +469,12 @@ static void SelectEnvironment(const char *envname) int newid = FirstFreeID(env->ID, env->Builtin); UCVarValue cv; cv.Int = HIBYTE(newid); - reverbedit_id1.ForceSet(cv, CVAR_Int); + reverbedit_id1->ForceSet(cv, CVAR_Int); cv.Int = LOBYTE(newid); - reverbedit_id2.ForceSet(cv, CVAR_Int); + reverbedit_id2->ForceSet(cv, CVAR_Int); FString selectname = SuggestNewName(env); cv.String = selectname.GetChars(); - reverbedit_name.ForceSet(cv, CVAR_String); + reverbedit_name->ForceSet(cv, CVAR_String); return; } } diff --git a/source/common/console/c_console.cpp b/source/common/console/c_console.cpp index c436ddd56..79eb18505 100644 --- a/source/common/console/c_console.cpp +++ b/source/common/console/c_console.cpp @@ -95,7 +95,6 @@ static FTextureID conflat; static uint32_t conshade; static bool conline; -extern FBaseCVar *CVars; extern FConsoleCommand *Commands[FConsoleCommand::HASH_SIZE]; int ConWidth; @@ -178,7 +177,7 @@ static void setmsgcolor (int index, int color); FILE *Logfile = NULL; -FIntCVar msglevel ("msg", 0, CVAR_ARCHIVE); +CVARD_NAMED(Int, msglevel, "msg", 0, CVAR_ARCHIVE, "Filters HUD message by importance"); CUSTOM_CVAR (Int, msg0color, CR_UNTRANSLATED, CVAR_ARCHIVE) { @@ -312,22 +311,6 @@ void C_DeinitConsole () } HistTail = HistHead = HistPos = NULL; - // Free cvars allocated at runtime - FBaseCVar *var, *next, **nextp; - for (var = CVars, nextp = &CVars; var != NULL; var = next) - { - next = var->m_Next; - if (var->GetFlags() & CVAR_UNSETTABLE) - { - delete var; - *nextp = next; - } - else - { - nextp = &var->m_Next; - } - } - // Free alias commands. (i.e. The "commands" that can be allocated // at runtime.) for (size_t i = 0; i < countof(Commands); ++i) diff --git a/source/common/console/c_cvars.cpp b/source/common/console/c_cvars.cpp index 15b2ca747..bb677d90c 100644 --- a/source/common/console/c_cvars.cpp +++ b/source/common/console/c_cvars.cpp @@ -56,8 +56,6 @@ struct FLatchedValue static TArray LatchedValues; -FBaseCVar *CVars = NULL; - int cvar_defflags; @@ -70,6 +68,74 @@ void C_InstallHandlers(ConsoleCallbacks* cb) callbacks = cb; } +void C_InitCVars(int which) +{ + AutoSegs::CVarDecl.ForEach([](FCVarDecl* cvInfo) + { + FBaseCVar* newcvar; + switch(cvInfo->type) + { + default: + return; + + case CVAR_Int: + { + using callbacktype = void (*)(FIntCVar &); + newcvar = new FIntCVar(cvInfo->name, cvInfo->defaultval.Int, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + case CVAR_Bool: + { + using callbacktype = void (*)(FBoolCVar &); + newcvar = new FBoolCVar(cvInfo->name, cvInfo->defaultval.Bool, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + case CVAR_Float: + { + using callbacktype = void (*)(FFloatCVar &); + newcvar = new FFloatCVar(cvInfo->name, cvInfo->defaultval.Float, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + case CVAR_String: + { + using callbacktype = void (*)(FStringCVar &); + newcvar = new FStringCVar(cvInfo->name, cvInfo->defaultval.String, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + case CVAR_Flag: + { + newcvar = new FFlagCVar(cvInfo->name, *cvInfo->defaultval.Pointer->get(), cvInfo->flags, cvInfo->description); + break; + } + case CVAR_Mask: + { + newcvar = new FMaskCVar(cvInfo->name, *cvInfo->defaultval.Pointer->get(), cvInfo->flags, cvInfo->description); + break; + } + case CVAR_Color: + { + using callbacktype = void (*)(FColorCVar &); + newcvar = new FColorCVar(cvInfo->name, cvInfo->defaultval.Int, cvInfo->flags, reinterpret_cast(cvInfo->callbackp), cvInfo->description); + break; + } + + } + *(void**)cvInfo->refAddr = newcvar; + }); +} + +void C_UninitCVars() +{ + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair* pair; + while (it.NextPair(pair)) + { + auto var = pair->Value; + pair->Value = nullptr; + delete var; + } +} + FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBaseCVar &), const char *descr) { if (var_name != nullptr && (flags & CVAR_SERVERINFO)) @@ -98,8 +164,7 @@ FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBa var = FindCVar(var_name, NULL); C_AddTabCommand (var_name); VarName = var_name; - m_Next = CVars; - CVars = this; + cvarMap.Insert(var_name, this); } if (var) @@ -109,11 +174,7 @@ FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBa value = var->GetFavoriteRep (&type); ForceSet (value, type); - - if (var->Flags & CVAR_AUTO) - delete var; - else - var->~FBaseCVar(); + delete var; Flags = flags; } @@ -133,13 +194,9 @@ FBaseCVar::~FBaseCVar () if (var == this) { - if (prev) - prev->m_Next = m_Next; - else - CVars = m_Next; - } - if (var->Flags & CVAR_AUTO) + cvarMap.Remove(var->VarName); C_RemoveTabCommand(VarName); + } } } @@ -522,15 +579,15 @@ void FBaseCVar::EnableNoSet () void FBaseCVar::EnableCallbacks () { m_UseCallback = true; - FBaseCVar *cvar = CVars; - - while (cvar) + CVarMap::Iterator it(cvarMap); + CVarMap::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if (!(cvar->Flags & CVAR_NOINITCALL)) { cvar->Callback (); } - cvar = cvar->m_Next; } } @@ -883,15 +940,16 @@ int FColorCVar::ToInt2 (UCVarValue value, ECVarType type) void FBaseCVar::ResetColors () { - FBaseCVar *var = CVars; - - while (var) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto var = pair->Value; + if (var->GetRealType () == CVAR_Color) { var->DoSet (var->GetGenericRep (CVAR_Int), CVAR_Int); } - var = var->m_Next; } } @@ -948,7 +1006,7 @@ BitVal (bitval) ECVarType FFlagCVar::GetRealType () const { - return CVAR_DummyBool; + return CVAR_Flag; } UCVarValue FFlagCVar::GetGenericRep (ECVarType type) const @@ -1044,7 +1102,7 @@ BitVal (bitval) ECVarType FMaskCVar::GetRealType () const { - return CVAR_DummyInt; + return CVAR_Mask; } UCVarValue FMaskCVar::GetGenericRep (ECVarType type) const @@ -1131,8 +1189,11 @@ static int sortcvars (const void *a, const void *b) void FilterCompactCVars (TArray &cvars, uint32_t filter) { // Accumulate all cvars that match the filter flags. - for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if ((cvar->Flags & filter) && !(cvar->Flags & CVAR_IGNORE)) cvars.Push(cvar); } @@ -1154,7 +1215,7 @@ void C_WriteCVars (uint8_t **demo_p, uint32_t filter, bool compact) FString C_GetMassCVarString (uint32_t filter, bool compact) { - FBaseCVar *cvar; + FBaseCVar* cvar; FString dump; if (compact) @@ -1170,8 +1231,11 @@ FString C_GetMassCVarString (uint32_t filter, bool compact) } else { - for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + cvar = pair->Value; if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE|CVAR_IGNORE))) { UCVarValue val = cvar->GetGenericRep(CVAR_String); @@ -1263,8 +1327,11 @@ void C_BackupCVars (void) FCVarBackup backup; - for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if ((cvar->Flags & (CVAR_SERVERINFO|CVAR_DEMOSAVE)) && !(cvar->Flags & CVAR_LATCH)) { backup.Name = cvar->GetName(); @@ -1290,47 +1357,24 @@ void C_ForgetCVars (void) FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev) { - FBaseCVar *var; - FBaseCVar *dummy; + if (var_name == nullptr) + return nullptr; - if (var_name == NULL) - return NULL; - - if (prev == NULL) - prev = &dummy; - - var = CVars; - *prev = NULL; - while (var) - { - if (stricmp (var->GetName (), var_name) == 0) - break; - *prev = var; - var = var->m_Next; - } - return var; + FName vname(var_name, true); + if (vname == NAME_None) return nullptr; + auto find = cvarMap.CheckKey(vname); + return find? *find : nullptr; } FBaseCVar *FindCVarSub (const char *var_name, int namelen) { - FBaseCVar *var; - if (var_name == NULL) return NULL; - var = CVars; - while (var) - { - const char *probename = var->GetName (); - - if (strnicmp (probename, var_name, namelen) == 0 && - probename[namelen] == 0) - { - break; - } - var = var->m_Next; - } - return var; + FName vname(var_name, namelen, true); + if (vname == NAME_None) return nullptr; + auto find = cvarMap.CheckKey(vname); + return find ? *find : nullptr; } FBaseCVar *GetCVar(int playernum, const char *cvarname) @@ -1395,26 +1439,24 @@ void UnlatchCVars (void) void DestroyCVarsFlagged (uint32_t flags) { - FBaseCVar *cvar = CVars; - FBaseCVar *next = cvar; - - while(cvar) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { - next = cvar->m_Next; + auto cvar = pair->Value; if(cvar->Flags & flags) delete cvar; - - cvar = next; } } void C_SetCVarsToDefaults (void) { - FBaseCVar *cvar = CVars; - - while (cvar) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; // Only default save-able cvars if (cvar->Flags & CVAR_ARCHIVE) { @@ -1423,7 +1465,6 @@ void C_SetCVarsToDefaults (void) val = cvar->GetFavoriteRepDefault (&type); cvar->SetGenericRep (val, type); } - cvar = cvar->m_Next; } } @@ -1436,18 +1477,19 @@ static int cvarcmp(const void* a, const void* b) void C_ArchiveCVars (FConfigFile *f, uint32_t filter) { - FBaseCVar *cvar = CVars; TArray cvarlist; - while (cvar) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto cvar = pair->Value; if ((cvar->Flags & (CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_MOD|CVAR_AUTO|CVAR_USERINFO|CVAR_SERVERINFO|CVAR_NOSAVE|CVAR_CONFIG_ONLY)) == filter) { cvarlist.Push(cvar); } - cvar = cvar->m_Next; } qsort(cvarlist.Data(), cvarlist.Size(), sizeof(FBaseCVar*), cvarcmp); for (auto cv : cvarlist) @@ -1591,11 +1633,13 @@ CCMD (toggle) void FBaseCVar::ListVars (const char *filter, bool plain) { - FBaseCVar *var = CVars; int count = 0; - while (var) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto var = pair->Value; if (CheckWildcards (filter, var->GetName())) { uint32_t flags = var->GetFlags(); @@ -1624,7 +1668,6 @@ void FBaseCVar::ListVars (const char *filter, bool plain) var->GetHumanString()); } } - var = var->m_Next; } Printf ("%d cvars\n", count); } @@ -1666,15 +1709,15 @@ CCMD (archivecvar) void C_ListCVarsWithoutDescription() { - FBaseCVar* var = CVars; - - while (var) + decltype(cvarMap)::Iterator it(cvarMap); + decltype(cvarMap)::Pair *pair; + while (it.NextPair(pair)) { + auto var = pair->Value; if (var->GetDescription().IsEmpty()) { Printf("%s\n", var->GetName()); } - var = var->m_Next; } } diff --git a/source/common/console/c_cvars.h b/source/common/console/c_cvars.h index cc83824e1..a4fe371d9 100644 --- a/source/common/console/c_cvars.h +++ b/source/common/console/c_cvars.h @@ -35,6 +35,8 @@ #define __C_CVARS_H__ #include "zstring.h" #include "tarray.h" +#include "autosegs.h" +#include "name.h" class FSerializer; // this needs to go away. /* @@ -72,18 +74,22 @@ enum CVAR_CONFIG_ONLY = 1 << 18, // do not save var to savegame and do not send it across network. }; +class FIntCVarRef; union UCVarValue { bool Bool; int Int; float Float; const char* String; + FIntCVarRef* Pointer; UCVarValue() = default; - UCVarValue(bool v) { Bool = v; } - UCVarValue(int v) { Int = v; } - UCVarValue(float v) { Float = v; } - UCVarValue(const char * v) { String = v; } + constexpr UCVarValue(bool v) : Bool(v) { } + constexpr UCVarValue(int v) : Int(v) { } + constexpr UCVarValue(float v) : Float(v) { } + constexpr UCVarValue(double v) : Float(float(v)) { } + constexpr UCVarValue(const char * v) : String(v) { } + constexpr UCVarValue(FIntCVarRef& v); }; enum ECVarType @@ -93,9 +99,9 @@ enum ECVarType CVAR_Float, CVAR_String, CVAR_Color, // stored as CVAR_Int - CVAR_DummyBool, // just redirects to another cvar - CVAR_DummyInt, // just redirects to another cvar - CVAR_Dummy // Unknown + CVAR_Flag, // just redirects to another cvar + CVAR_Mask, // just redirects to another cvar + CVAR_Dummy, // Unknown }; class FConfigFile; @@ -104,6 +110,9 @@ class FxCVar; class FBaseCVar; +using CVarMap = TMap; +inline CVarMap cvarMap; + // These are calls into the game code. Having these hard coded in the CVAR implementation has always been the biggest blocker // for reusing the CVAR module outside of ZDoom. So now they get called through this struct for easier reusability. struct ConsoleCallbacks @@ -134,7 +143,6 @@ public: inline const char *GetName () const { return VarName.GetChars(); } inline uint32_t GetFlags () const { return Flags; } - inline FBaseCVar *GetNext() const { return m_Next; } void CmdSet (const char *newval); void ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend=false); @@ -214,7 +222,6 @@ private: FBaseCVar (const FBaseCVar &var) = delete; FBaseCVar (const char *name, uint32_t flags); void (*m_Callback)(FBaseCVar &); - FBaseCVar *m_Next; static inline bool m_UseCallback = false; static inline bool m_DoNoSet = false; @@ -279,6 +286,8 @@ void C_SetCVarsToDefaults (void); void FilterCompactCVars (TArray &cvars, uint32_t filter); void C_DeinitConsole(); +void C_InitCVars(int which); +void C_UninitCVars(); class FBoolCVar : public FBaseCVar { @@ -465,6 +474,88 @@ protected: int BitNum; }; +class FBoolCVarRef +{ + FBoolCVar* ref; +public: + + inline bool operator= (bool val) { *ref = val; return val; } + inline operator bool () const { return **ref; } + inline bool operator *() const { return **ref; } + inline FBoolCVar* operator->() { return ref; } + inline FBoolCVar* get() { return ref; } +}; + +class FIntCVarRef +{ + FIntCVar* ref; +public: + + int operator= (int val) { *ref = val; return val; } + inline operator int () const { return **ref; } + inline int operator *() const { return **ref; } + inline FIntCVar* operator->() { return ref; } + inline FIntCVar* get() { return ref; } +}; + +class FFloatCVarRef +{ + FFloatCVar* ref; +public: + + float operator= (float val) { *ref = val; return val; } + inline operator float () const { return **ref; } + inline float operator *() const { return **ref; } + inline FFloatCVar* operator->() { return ref; } + inline FFloatCVar* get() { return ref; } +}; + +class FStringCVarRef +{ + FStringCVar* ref; +public: + + const char* operator= (const char* val) { *ref = val; return val; } + inline operator const char* () const { return **ref; } + inline const char* operator *() const { return **ref; } + inline FStringCVar* operator->() { return ref; } + inline FStringCVar* get() { return ref; } +}; + +class FColorCVarRef +{ + FColorCVar* ref; +public: + + //uint32_t operator= (uint32_t val) { *ref = val; return val; } + inline operator uint32_t () const { return **ref; } + inline uint32_t operator *() const { return **ref; } + inline FColorCVar* operator->() { return ref; } + inline FColorCVar* get() { return ref; } +}; + +class FFlagCVarRef +{ + FFlagCVar* ref; +public: + inline bool operator= (bool val) { *ref = val; return val; } + inline bool operator= (const FFlagCVar& val) { *ref = val; return val; } + inline operator int () const { return **ref; } + inline int operator *() const { return **ref; } + inline FFlagCVar& operator->() { return *ref; } +}; + +class FMaskCVarRef +{ + FMaskCVar* ref; +public: + //int operator= (int val) { *ref = val; return val; } + inline operator int () const { return **ref; } + inline int operator *() const { return **ref; } + inline FMaskCVar& operator->() { return *ref; } +}; + + extern int cvar_defflags; FBaseCVar *cvar_set (const char *var_name, const char *value); @@ -473,6 +564,18 @@ FBaseCVar *cvar_forceset (const char *var_name, const char *value); inline FBaseCVar *cvar_set (const char *var_name, const uint8_t *value) { return cvar_set (var_name, (const char *)value); } inline FBaseCVar *cvar_forceset (const char *var_name, const uint8_t *value) { return cvar_forceset (var_name, (const char *)value); } +constexpr UCVarValue::UCVarValue(FIntCVarRef& v) : Pointer(&v) { } + +struct FCVarDecl +{ + void * refAddr; + ECVarType type; + unsigned int flags; + const char * name; + UCVarValue defaultval; + const char *description; + void* callbackp; // actually a function pointer with unspecified arguments. C++ does not like that much... +}; // Restore demo cvars. Called after demo playback to restore all cvars @@ -482,35 +585,59 @@ void C_RestoreCVars (void); void C_ForgetCVars (void); +#if defined(_MSC_VER) +#pragma section(SECTION_VREG,read) + +#define MSVC_VSEG __declspec(allocate(SECTION_VREG)) +#define GCC_VSEG +#else +#define MSVC_VSEG +#define GCC_VSEG __attribute__((section(SECTION_VREG))) __attribute__((used)) +#endif + #define CUSTOM_CVAR(type,name,def,flags) \ static void cvarfunc_##name(F##type##CVar &); \ - F##type##CVar name (#name, def, flags, cvarfunc_##name); \ + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #name, def, nullptr, reinterpret_cast(cvarfunc_##name) }; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; \ static void cvarfunc_##name(F##type##CVar &self) + #define CUSTOM_CVAR_NAMED(type,name,cname,def,flags) \ static void cvarfunc_##name(F##type##CVar &); \ - F##type##CVar name (#cname, def, flags, cvarfunc_##name); \ + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #cname, def, nullptr, reinterpret_cast(cvarfunc_##name) }; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; \ static void cvarfunc_##name(F##type##CVar &self) #define CVAR(type,name,def,flags) \ - F##type##CVar name (#name, def, flags); + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #name, def, nullptr, nullptr}; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; -#define EXTERN_CVAR(type,name) extern F##type##CVar name; +#define EXTERN_CVAR(type,name) extern F##type##CVarRef name; #define CUSTOM_CVARD(type,name,def,flags,descr) \ static void cvarfunc_##name(F##type##CVar &); \ - F##type##CVar name (#name, def, flags, cvarfunc_##name, descr); \ + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #name, def, descr, reinterpret_cast(cvarfunc_##name) }; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; \ static void cvarfunc_##name(F##type##CVar &self) #define CVARD(type,name,def,flags, descr) \ - F##type##CVar name (#name, def, flags, nullptr, descr); + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #name, def, descr, nullptr}; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; #define CVARD_NAMED(type,name,varname,def,flags, descr) \ -F##type##CVar varname (#name, def, flags, nullptr, descr); - -#define CVAR_UNAMED(type,varname) \ -F##type##CVar varname (nullptr, 0, 0, nullptr, nullptr); - -extern FBaseCVar *CVars; + F##type##CVarRef name; \ + static FCVarDecl cvardecl_##name = { &name, CVAR_##type, (flags), #varname, def, descr, nullptr}; \ + extern FCVarDecl const *const cvardeclref_##name; \ + MSVC_VSEG FCVarDecl const *const cvardeclref_##name GCC_VSEG = &cvardecl_##name; #endif //__C_CVARS_H__ diff --git a/source/common/engine/m_joy.cpp b/source/common/engine/m_joy.cpp index 3c46d2527..dec49377f 100644 --- a/source/common/engine/m_joy.cpp +++ b/source/common/engine/m_joy.cpp @@ -62,9 +62,9 @@ EXTERN_CVAR(Bool, joy_xinput) CUSTOM_CVARD(Bool, use_joystick, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL, "enables input from the joystick if it is present") { #ifdef _WIN32 - joy_ps2raw.Callback(); - joy_dinput.Callback(); - joy_xinput.Callback(); + joy_ps2raw->Callback(); + joy_dinput->Callback(); + joy_xinput->Callback(); #endif } diff --git a/source/common/engine/serializer.cpp b/source/common/engine/serializer.cpp index f42289573..a024aeb4d 100644 --- a/source/common/engine/serializer.cpp +++ b/source/common/engine/serializer.cpp @@ -683,7 +683,7 @@ void FSerializer::ReadObjects(bool hubtravel) { r->mObjects.Clamp(size); // close all inner objects. // In case something in here throws an error, let's continue and deal with it later. - Printf(TEXTCOLOR_RED "'%s'\n while restoring %s\n", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); + Printf(PRINT_NONOTIFY, TEXTCOLOR_RED "'%s'\n while restoring %s\n", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); mErrors++; } } diff --git a/source/common/menu/menu.cpp b/source/common/menu/menu.cpp index 187fe5e9e..6a8ce3ddc 100644 --- a/source/common/menu/menu.cpp +++ b/source/common/menu/menu.cpp @@ -925,7 +925,7 @@ void M_Init (void) catch (CVMAbortException &err) { err.MaybePrintMessage(); - Printf("%s", err.stacktrace.GetChars()); + Printf(PRINT_NONOTIFY, "%s", err.stacktrace.GetChars()); I_FatalError("Failed to initialize menus"); } M_CreateMenus(); diff --git a/source/common/objects/autosegs.cpp b/source/common/objects/autosegs.cpp index 4d5bdba74..11fce1005 100644 --- a/source/common/objects/autosegs.cpp +++ b/source/common/objects/autosegs.cpp @@ -74,6 +74,7 @@ AUTOSEG_VARIABLE(TypeInfos, AUTOSEG_CREG) AUTOSEG_VARIABLE(ClassFields, AUTOSEG_FREG) AUTOSEG_VARIABLE(Properties, AUTOSEG_GREG) AUTOSEG_VARIABLE(MapInfoOptions, AUTOSEG_YREG) +AUTOSEG_VARIABLE(CVarDecl, AUTOSEG_VREG) #undef AUTOSEG_VARIABLE #undef AUTOSEG_STOP diff --git a/source/common/objects/autosegs.h b/source/common/objects/autosegs.h index 91b404ad4..838553dd4 100644 --- a/source/common/objects/autosegs.h +++ b/source/common/objects/autosegs.h @@ -148,6 +148,7 @@ namespace AutoSegs extern FAutoSeg ClassFields; extern FAutoSeg Properties; extern FAutoSeg MapInfoOptions; + extern FAutoSeg CVarDecl; } #define AUTOSEG_AREG areg @@ -155,6 +156,7 @@ namespace AutoSegs #define AUTOSEG_FREG freg #define AUTOSEG_GREG greg #define AUTOSEG_YREG yreg +#define AUTOSEG_VREG vreg #define AUTOSEG_STR(string) AUTOSEG_STR2(string) #define AUTOSEG_STR2(string) #string @@ -167,12 +169,14 @@ namespace AutoSegs #define SECTION_FREG AUTOSEG_MACH_SECTION(AUTOSEG_FREG) #define SECTION_GREG AUTOSEG_MACH_SECTION(AUTOSEG_GREG) #define SECTION_YREG AUTOSEG_MACH_SECTION(AUTOSEG_YREG) +#define SECTION_VREG AUTOSEG_MACH_SECTION(AUTOSEG_VREG) #else #define SECTION_AREG AUTOSEG_STR(AUTOSEG_AREG) #define SECTION_CREG AUTOSEG_STR(AUTOSEG_CREG) #define SECTION_FREG AUTOSEG_STR(AUTOSEG_FREG) #define SECTION_GREG AUTOSEG_STR(AUTOSEG_GREG) #define SECTION_YREG AUTOSEG_STR(AUTOSEG_YREG) +#define SECTION_VREG AUTOSEG_STR(AUTOSEG_VREG) #endif #endif diff --git a/source/common/platform/win32/gl_sysfb.cpp b/source/common/platform/win32/gl_sysfb.cpp index ce282c5fb..61073e968 100644 --- a/source/common/platform/win32/gl_sysfb.cpp +++ b/source/common/platform/win32/gl_sysfb.cpp @@ -112,7 +112,7 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : Syst EXTERN_CVAR(Bool, vid_vsync); CUSTOM_CVAR(Bool, gl_control_tear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { - vid_vsync.Callback(); + vid_vsync->Callback(); } void SystemGLFrameBuffer::SetVSync (bool vsync) diff --git a/source/common/platform/win32/i_input.cpp b/source/common/platform/win32/i_input.cpp index 01c4ce0be..05988060f 100644 --- a/source/common/platform/win32/i_input.cpp +++ b/source/common/platform/win32/i_input.cpp @@ -399,7 +399,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // If regional settings were changed, reget preferred languages if (wParam == 0 && lParam != 0 && strcmp ((const char *)lParam, "intl") == 0) { - language.Callback (); + language->Callback (); } return 0; diff --git a/source/common/rendering/v_video.cpp b/source/common/rendering/v_video.cpp index f87efe638..47caad55e 100644 --- a/source/common/rendering/v_video.cpp +++ b/source/common/rendering/v_video.cpp @@ -394,7 +394,7 @@ void V_Init2() UCVarValue val; val.Bool = !!Args->CheckParm("-devparm"); - ticker.SetGenericRepDefault(val, CVAR_Bool); + ticker->SetGenericRepDefault(val, CVAR_Bool); I_InitGraphics(); diff --git a/source/common/scripting/backend/codegen.cpp b/source/common/scripting/backend/codegen.cpp index de0408d05..24ce94447 100644 --- a/source/common/scripting/backend/codegen.cpp +++ b/source/common/scripting/backend/codegen.cpp @@ -6715,12 +6715,12 @@ FxExpression *FxCVar::Resolve(FCompileContext &ctx) switch (CVar->GetRealType()) { case CVAR_Bool: - case CVAR_DummyBool: + case CVAR_Flag: ValueType = TypeBool; break; case CVAR_Int: - case CVAR_DummyInt: + case CVAR_Mask: ValueType = TypeSInt32; break; @@ -6776,7 +6776,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) build->Emit(OP_LS, dest.RegNum, addr.RegNum, nul); break; - case CVAR_DummyBool: + case CVAR_Flag: { int *pVal; auto cv = static_cast(CVar); @@ -6789,7 +6789,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) break; } - case CVAR_DummyInt: + case CVAR_Mask: { auto cv = static_cast(CVar); build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value)); diff --git a/source/common/scripting/vm/vmframe.cpp b/source/common/scripting/vm/vmframe.cpp index 476b945c2..8a4b87458 100644 --- a/source/common/scripting/vm/vmframe.cpp +++ b/source/common/scripting/vm/vmframe.cpp @@ -682,8 +682,7 @@ void CVMAbortException::MaybePrintMessage() auto m = GetMessage(); if (m != nullptr) { - Printf(TEXTCOLOR_RED); - Printf("%s\n", m); + Printf(PRINT_NONOTIFY, TEXTCOLOR_RED "%s\n", m); SetMessage(""); } } diff --git a/source/common/thirdparty/libsmackerdec/include/BitReader.h b/source/common/thirdparty/libsmackerdec/include/BitReader.h index ebc60a560..1bf12b2ca 100644 --- a/source/common/thirdparty/libsmackerdec/include/BitReader.h +++ b/source/common/thirdparty/libsmackerdec/include/BitReader.h @@ -47,4 +47,4 @@ class BitReader } // close namespace SmackerCommon -#endif \ No newline at end of file +#endif diff --git a/source/core/ct_chat.cpp b/source/core/ct_chat.cpp index 714022fa5..ec353c377 100644 --- a/source/core/ct_chat.cpp +++ b/source/core/ct_chat.cpp @@ -84,7 +84,7 @@ static bool DoSubstitution (FString &out, const char *in); static TArray ChatQueue; -extern FStringCVar* const CombatMacros[]; +extern FStringCVarRef* const CombatMacros[]; CVAR (Bool, chat_substitution, false, CVAR_ARCHIVE) diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index e9e03fb53..d55965cf4 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -555,6 +555,7 @@ int GameMain() { int r; I_InitTime(); + C_InitCVars(0); SetConsoleNotifyBuffer(); sysCallbacks = { @@ -638,6 +639,7 @@ int GameMain() } DeleteStartupScreen(); PClass::StaticShutdown(); + C_UninitCVars(); if (Args) delete Args; return r; } @@ -1025,17 +1027,17 @@ int RunGame() // Handle CVARs with game specific defaults here. if (isBlood()) { - mus_redbook.SetGenericRepDefault(false, CVAR_Bool); // Blood should default to CD Audio off - all other games must default to on. - am_showlabel.SetGenericRepDefault(true, CVAR_Bool); + mus_redbook->SetGenericRepDefault(false, CVAR_Bool); // Blood should default to CD Audio off - all other games must default to on. + am_showlabel->SetGenericRepDefault(true, CVAR_Bool); } if (isSWALL()) { - cl_weaponswitch.SetGenericRepDefault(1, CVAR_Int); + cl_weaponswitch->SetGenericRepDefault(1, CVAR_Int); if (cl_weaponswitch > 1) cl_weaponswitch = 1; } if (g_gameType & (GAMEFLAG_BLOOD|GAMEFLAG_RR)) { - am_nameontop.SetGenericRepDefault(true, CVAR_Bool); // Blood and RR show the map name on the top of the screen by default. + am_nameontop->SetGenericRepDefault(true, CVAR_Bool); // Blood and RR show the map name on the top of the screen by default. } G_ReadConfig(currentGame); @@ -1217,7 +1219,7 @@ CVAR(String, combatmacro6, "", CVAR_ARCHIVE | CVAR_USERINFO) CVAR(String, combatmacro7, "", CVAR_ARCHIVE | CVAR_USERINFO) CVAR(String, combatmacro8, "", CVAR_ARCHIVE | CVAR_USERINFO) CVAR(String, combatmacro9, "", CVAR_ARCHIVE | CVAR_USERINFO) -FStringCVar* const CombatMacros[] = { &combatmacro0, &combatmacro1, &combatmacro2, &combatmacro3, &combatmacro4, &combatmacro5, &combatmacro6, &combatmacro7, &combatmacro8, &combatmacro9}; +FStringCVarRef* const CombatMacros[] = { &combatmacro0, &combatmacro1, &combatmacro2, &combatmacro3, &combatmacro4, &combatmacro5, &combatmacro6, &combatmacro7, &combatmacro8, &combatmacro9}; void CONFIG_ReadCombatMacros() { @@ -1230,7 +1232,7 @@ void CONFIG_ReadCombatMacros() sc.MustGetToken(TK_StringConst); UCVarValue val; val.String = sc.String; - s->SetGenericRepDefault(val, CVAR_String); + s->get()->SetGenericRepDefault(val, CVAR_String); } } catch (const CRecoverableError &) diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 0c7d33481..1c0708754 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -34,7 +34,7 @@ extern MapRecord* g_nextmap; extern int g_nextskill; extern int g_bossexit; -extern FStringCVar* const CombatMacros[]; +extern FStringCVarRef* const CombatMacros[]; void CONFIG_ReadCombatMacros(); int GameMain(); diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index 6e5be9fdc..92257b4f4 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -879,7 +879,7 @@ static int nextquicksave = -1; } num.Int = nextautosave; - autosavenum.ForceSet(num, CVAR_Int); + autosavenum->ForceSet(num, CVAR_Int); auto Filename = G_BuildSaveName(FStringf("auto%04d", nextautosave)); readableTime = myasctime(); @@ -909,7 +909,7 @@ CCMD(rotatingquicksave) } num.Int = nextquicksave; - quicksavenum.ForceSet(num, CVAR_Int); + quicksavenum->ForceSet(num, CVAR_Int); FSaveGameNode sg; auto Filename = G_BuildSaveName(FStringf("quick%04d", nextquicksave)); diff --git a/source/games/duke/src/game.cpp b/source/games/duke/src/game.cpp index e10aafa39..31d59af35 100644 --- a/source/games/duke/src/game.cpp +++ b/source/games/duke/src/game.cpp @@ -370,7 +370,7 @@ void GameInterface::app_init() loadcons(); fi.initactorflags(); - duke_menufont.Callback(); // depends on the .CON files so it must be after loadcons + duke_menufont->Callback(); // depends on the .CON files so it must be after loadcons OnEvent(EVENT_INIT); diff --git a/source/games/duke/src/gamedef.cpp b/source/games/duke/src/gamedef.cpp index 95d6a79e1..5beaf443b 100644 --- a/source/games/duke/src/gamedef.cpp +++ b/source/games/duke/src/gamedef.cpp @@ -3108,7 +3108,7 @@ void ConCompiler::compilecon(const char *filenam) // Install the crosshair toggle messages in the CVAR. - cl_crosshair.SetToggleMessages(quoteMgr.GetRawQuote(QUOTE_CROSSHAIR_OFF), quoteMgr.GetRawQuote(QUOTE_CROSSHAIR_OFF-1)); + cl_crosshair->SetToggleMessages(quoteMgr.GetRawQuote(QUOTE_CROSSHAIR_OFF), quoteMgr.GetRawQuote(QUOTE_CROSSHAIR_OFF-1)); } //==========================================================================