diff --git a/source/common/console/c_console.h b/source/common/console/c_console.h deleted file mode 100644 index 2eedd9407..000000000 --- a/source/common/console/c_console.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -** c_console.h -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#ifndef __C_CONSOLE__ -#define __C_CONSOLE__ - -#include -//#include "basictypes.h" - -// Dummies for missing features to make the code compile. - -inline void C_AddTabCommand (const char *name) {} -inline void C_RemoveTabCommand (const char *name) {} - - -#if 0 - -struct event_t; - -#define C_BLINKRATE (TICRATE/2) - -typedef enum cstate_t -{ - c_up=0, c_down=1, c_falling=2, c_rising=3 -} -constate_e; - -enum -{ - PRINTLEVELS = 5 -}; -extern int PrintColors[PRINTLEVELS + 2]; - -extern constate_e ConsoleState; - -// Initialize the console -void C_InitConsole (int width, int height, bool ingame); -void C_DeinitConsole (); -void C_InitConback(); - -// Adjust the console for a new screen mode -void C_NewModeAdjust (void); - -void C_Ticker (void); - -void AddToConsole (int printlevel, const char *string); -int PrintString (int printlevel, const char *string); -int PrintStringHigh (const char *string); -int VPrintf (int printlevel, const char *format, va_list parms) GCCFORMAT(2); - -void C_DrawConsole (); -void C_ToggleConsole (void); -void C_FullConsole (void); -void C_HideConsole (void); -void C_AdjustBottom (void); -void C_FlushDisplay (void); - -class FFont; -void C_MidPrint (FFont *font, const char *message, bool bold = false); - -bool C_Responder (event_t *ev); - -void C_AddTabCommand (const char *name); -void C_RemoveTabCommand (const char *name); -void C_ClearTabCommands(); // Removes all tab commands - -extern const char *console_bar; - -#endif - -#endif diff --git a/source/common/console/c_cvars.cpp b/source/common/console/c_cvars.cpp deleted file mode 100644 index 6f69ad025..000000000 --- a/source/common/console/c_cvars.cpp +++ /dev/null @@ -1,1584 +0,0 @@ -/* -** c_cvars.cpp -** Defines all the different console variable types -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include - -#include "c_cvars.h" -#include "configfile.h" - -#include "c_console.h" - -//#include "cmdlib.h" -//#include "c_dispatch.h" - -//#include "g_game.h" -//#include "d_player.h" -//#include "v_video.h" -//#include "d_netinf.h" - -//#include "menu/menu.h" -//#include "vm.h" - -struct FLatchedValue -{ - FBaseCVar *Variable; - UCVarValue Value; - ECVarType Type; - bool UnsafeContext; -}; - -static TArray LatchedValues; - -bool FBaseCVar::m_DoNoSet = false; -bool FBaseCVar::m_UseCallback = false; - -FBaseCVar *CVars = NULL; - -int cvar_defflags; - - -FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBaseCVar &), const char *descr) -{ - if (var_name != nullptr && (flags & CVAR_SERVERINFO)) - { - // This limitation is imposed by network protocol which uses only 6 bits - // for name's length with terminating null character - static const size_t NAME_LENGHT_MAX = 63; - - /* - if (strlen(var_name) > NAME_LENGHT_MAX) - { - I_FatalError("Name of the server console variable \"%s\" is too long.\n" - "Its length should not exceed %zu characters.\n", var_name, NAME_LENGHT_MAX); - } - */ - } - - FBaseCVar *var; - - var = FindCVar (var_name, NULL); - - m_Callback = callback; - Flags = 0; - VarName = ""; - Description = descr; - - if (var_name) - { - C_AddTabCommand (var_name); - VarName = var_name; - m_Next = CVars; - CVars = this; - } - - if (var) - { - ECVarType type; - UCVarValue value; - - value = var->GetFavoriteRep (&type); - ForceSet (value, type); - - if (var->Flags & CVAR_AUTO) - delete var; - else - var->~FBaseCVar(); - - Flags = flags; - } - else - { - Flags = flags | CVAR_ISDEFAULT; - } -} - -FBaseCVar::~FBaseCVar () -{ - if (VarName.IsNotEmpty()) - { - FBaseCVar *var, *prev; - - var = FindCVar (VarName, &prev); - - if (var == this) - { - if (prev) - prev->m_Next = m_Next; - else - CVars = m_Next; - } - C_RemoveTabCommand(VarName); - } -} - -const char *FBaseCVar::GetHumanString(int precision) const -{ - return GetGenericRep(CVAR_String).String; -} - -void FBaseCVar::ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend) -{ - DoSet (value, type); - if (m_UseCallback) - Callback (); - - if ((Flags & CVAR_ARCHIVE)) - { - SafeValue = GetGenericRep(CVAR_String).String; - } - - Flags &= ~(CVAR_ISDEFAULT); -} - -void FBaseCVar::SetGenericRep (UCVarValue value, ECVarType type) -{ - if ((Flags & CVAR_NOSET) && m_DoNoSet) - { - return; - } -#if 0 - else if ((Flags & CVAR_LATCH) && gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP) - { - FLatchedValue latch; - - latch.Variable = this; - latch.Type = type; - if (type != CVAR_String) - latch.Value = value; - else - latch.Value.String = copystring(value.String); - latch.UnsafeContext = !!(Flags & CVAR_UNSAFECONTEXT); - LatchedValues.Push (latch); - - Flags &= ~CVAR_UNSAFECONTEXT; - } - else if ((Flags & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) - { - if (netgame && !players[consoleplayer].settings_controller) - { - Printf ("Only setting controllers can change %s\n", Name); - Flags &= ~CVAR_UNSAFECONTEXT; - return; - } - D_SendServerInfoChange (this, value, type); - } -#endif - else - { - ForceSet (value, type); - } -} - -bool FBaseCVar::ToBool (UCVarValue value, ECVarType type) -{ - switch (type) - { - case CVAR_Bool: - return value.Bool; - - case CVAR_Int: - return !!value.Int; - - case CVAR_Float: - return value.Float != 0.f; - - case CVAR_String: - if (stricmp (value.String, "true") == 0) - return true; - else if (stricmp (value.String, "false") == 0) - return false; - else - return !!strtoll (value.String, NULL, 0); - - default: - return false; - } -} - -int FBaseCVar::ToInt (UCVarValue value, ECVarType type) -{ - int res; -#if __GNUC__ <= 2 - float tmp; -#endif - - switch (type) - { - case CVAR_Bool: res = (int)value.Bool; break; - case CVAR_Int: res = value.Int; break; -#if __GNUC__ <= 2 - case CVAR_Float: tmp = value.Float; res = (int)tmp; break; -#else - case CVAR_Float: res = (int)value.Float; break; -#endif - case CVAR_String: - { - if (stricmp (value.String, "true") == 0) - res = 1; - else if (stricmp (value.String, "false") == 0) - res = 0; - else - res = (int)strtoll (value.String, NULL, 0); - break; - } - default: res = 0; break; - } - return res; -} - -float FBaseCVar::ToFloat (UCVarValue value, ECVarType type) -{ - switch (type) - { - case CVAR_Bool: - return (float)value.Bool; - - case CVAR_Int: - return (float)value.Int; - - case CVAR_Float: - return value.Float; - - case CVAR_String: - return (float)strtod (value.String, NULL); - - default: - return 0.f; - } -} - -static char cstrbuf[40]; -static char truestr[] = "true"; -static char falsestr[] = "false"; - -const char *FBaseCVar::ToString (UCVarValue value, ECVarType type) -{ - switch (type) - { - case CVAR_Bool: - return value.Bool ? truestr : falsestr; - - case CVAR_String: - return value.String; - - case CVAR_Int: - snprintf (cstrbuf, sizeof(cstrbuf), "%i", value.Int); - break; - - case CVAR_Float: - IGNORE_FORMAT_PRE - snprintf (cstrbuf, sizeof(cstrbuf), "%g", value.Float); - IGNORE_FORMAT_POST - break; - - default: - strcpy (cstrbuf, ""); - break; - } - return cstrbuf; -} - -UCVarValue FBaseCVar::FromBool (bool value, ECVarType type) -{ - UCVarValue ret; - - switch (type) - { - case CVAR_Bool: - ret.Bool = value; - break; - - case CVAR_Int: - ret.Int = value; - break; - - case CVAR_Float: - ret.Float = value; - break; - - case CVAR_String: - ret.String = value ? truestr : falsestr; - break; - - default: - break; - } - - return ret; -} - -UCVarValue FBaseCVar::FromInt (int value, ECVarType type) -{ - UCVarValue ret; - - switch (type) - { - case CVAR_Bool: - ret.Bool = value != 0; - break; - - case CVAR_Int: - ret.Int = value; - break; - - case CVAR_Float: - ret.Float = (float)value; - break; - - case CVAR_String: - snprintf (cstrbuf, sizeof(cstrbuf), "%i", value); - ret.String = cstrbuf; - break; - - default: - break; - } - - return ret; -} - -UCVarValue FBaseCVar::FromFloat (float value, ECVarType type) -{ - UCVarValue ret; - - switch (type) - { - case CVAR_Bool: - ret.Bool = value != 0.f; - break; - - case CVAR_Int: - ret.Int = (int)value; - break; - - case CVAR_Float: - ret.Float = value; - break; - - case CVAR_String: - IGNORE_FORMAT_PRE - snprintf (cstrbuf, sizeof(cstrbuf), "%g", value); - IGNORE_FORMAT_POST - ret.String = cstrbuf; - break; - - default: - break; - } - - return ret; -} - -static uint8_t HexToByte (const char *hex) -{ - uint8_t v = 0; - for (int i = 0; i < 2; ++i) - { - v <<= 4; - if (hex[i] >= '0' && hex[i] <= '9') - { - v += hex[i] - '0'; - } - else if (hex[i] >= 'A' && hex[i] <= 'F') - { - v += hex[i] - 'A'; - } - else // The string is already verified to contain valid hexits - { - v += hex[i] - 'a'; - } - } - return v; -} - -UCVarValue FBaseCVar::FromString (const char *value, ECVarType type) -{ - UCVarValue ret; - - switch (type) - { - case CVAR_Bool: - if (stricmp (value, "true") == 0) - ret.Bool = true; - else if (stricmp (value, "false") == 0) - ret.Bool = false; - else - ret.Bool = strtoll (value, NULL, 0) != 0; - break; - - case CVAR_Int: - if (stricmp (value, "true") == 0) - ret.Int = 1; - else if (stricmp (value, "false") == 0) - ret.Int = 0; - else - ret.Int = (int)strtoll (value, NULL, 0); - break; - - case CVAR_Float: - ret.Float = (float)strtod (value, NULL); - break; - - case CVAR_String: - ret.String = const_cast(value); - break; - - default: - break; - } - - return ret; -} - -FBaseCVar *cvar_set (const char *var_name, const char *val) -{ - FBaseCVar *var; - - if ( (var = FindCVar (var_name, NULL)) ) - { - UCVarValue value; - value.String = const_cast(val); - var->SetGenericRep (value, CVAR_String); - } - - return var; -} - -FBaseCVar *cvar_forceset (const char *var_name, const char *val) -{ - FBaseCVar *var; - UCVarValue vval; - - if ( (var = FindCVar (var_name, NULL)) ) - { - vval.String = const_cast(val); - var->ForceSet (vval, CVAR_String); - } - - return var; -} - -void FBaseCVar::EnableNoSet () -{ - m_DoNoSet = true; -} - -void FBaseCVar::EnableCallbacks () -{ - m_UseCallback = true; - FBaseCVar *cvar = CVars; - - while (cvar) - { - if (!(cvar->Flags & CVAR_NOINITCALL)) - { - cvar->Callback (); - } - cvar = cvar->m_Next; - } -} - -void FBaseCVar::DisableCallbacks () -{ - m_UseCallback = false; -} - -// -// Boolean cvar implementation -// - -FBoolCVar::FBoolCVar (const char *name, bool def, uint32_t flags, void (*callback)(FBoolCVar &), const char* descr) -: FBaseCVar (name, flags, reinterpret_cast(callback), descr) -{ - DefaultValue = def; - if (Flags & CVAR_ISDEFAULT) - Value = def; -} - -ECVarType FBoolCVar::GetRealType () const -{ - return CVAR_Bool; -} - -UCVarValue FBoolCVar::GetGenericRep (ECVarType type) const -{ - return FromBool (Value, type); -} - -UCVarValue FBoolCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Bool; - ret.Bool = Value; - return ret; -} - -UCVarValue FBoolCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromBool (DefaultValue, type); -} - -UCVarValue FBoolCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Bool; - ret.Bool = DefaultValue; - return ret; -} - -void FBoolCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - DefaultValue = ToBool (value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -void FBoolCVar::DoSet (UCVarValue value, ECVarType type) -{ - Value = ToBool (value, type); -} - -// -// Integer cvar implementation -// - -FIntCVar::FIntCVar (const char *name, int def, uint32_t flags, void (*callback)(FIntCVar &), const char* descr) -: FBaseCVar (name, flags, reinterpret_cast(callback), descr) -{ - DefaultValue = def; - if (Flags & CVAR_ISDEFAULT) - Value = def; -} - -ECVarType FIntCVar::GetRealType () const -{ - return CVAR_Int; -} - -UCVarValue FIntCVar::GetGenericRep (ECVarType type) const -{ - return FromInt (Value, type); -} - -UCVarValue FIntCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Int; - ret.Int = Value; - return ret; -} - -UCVarValue FIntCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromInt (DefaultValue, type); -} - -UCVarValue FIntCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Int; - ret.Int = DefaultValue; - return ret; -} - -void FIntCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - DefaultValue = ToInt (value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -void FIntCVar::DoSet (UCVarValue value, ECVarType type) -{ - Value = ToInt (value, type); -} - -// -// Floating point cvar implementation -// - -FFloatCVar::FFloatCVar (const char *name, float def, uint32_t flags, void (*callback)(FFloatCVar &), const char* descr) -: FBaseCVar (name, flags, reinterpret_cast(callback), descr) -{ - DefaultValue = def; - if (Flags & CVAR_ISDEFAULT) - Value = def; -} - -ECVarType FFloatCVar::GetRealType () const -{ - return CVAR_Float; -} - -const char *FFloatCVar::GetHumanString(int precision) const -{ - if (precision < 0) - { - precision = 6; - } - snprintf(cstrbuf, sizeof(cstrbuf), "%.*g", precision, Value); - return cstrbuf; -} - -UCVarValue FFloatCVar::GetGenericRep (ECVarType type) const -{ - return FromFloat (Value, type); -} - -UCVarValue FFloatCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Float; - ret.Float = Value; - return ret; -} - -UCVarValue FFloatCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromFloat (DefaultValue, type); -} - -UCVarValue FFloatCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Float; - ret.Float = DefaultValue; - return ret; -} - -void FFloatCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - DefaultValue = ToFloat (value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -void FFloatCVar::DoSet (UCVarValue value, ECVarType type) -{ - Value = ToFloat (value, type); -} - -// -// String cvar implementation -// - -FStringCVar::FStringCVar (const char *name, const char *def, uint32_t flags, void (*callback)(FStringCVar &), const char* descr) -: FBaseCVar (name, flags, reinterpret_cast(callback), descr) -{ - mDefaultValue = def; - if (Flags & CVAR_ISDEFAULT) - mValue = def; - else - mValue = ""; -} - -FStringCVar::~FStringCVar () -{ -} - -ECVarType FStringCVar::GetRealType () const -{ - return CVAR_String; -} - -UCVarValue FStringCVar::GetGenericRep (ECVarType type) const -{ - return FromString (mValue, type); -} - -UCVarValue FStringCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_String; - ret.String = mValue; - return ret; -} - -UCVarValue FStringCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromString (mDefaultValue, type); -} - -UCVarValue FStringCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_String; - ret.String = mDefaultValue; - return ret; -} - -void FStringCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - mDefaultValue = ToString(value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -void FStringCVar::DoSet (UCVarValue value, ECVarType type) -{ - mValue = ToString (value, type); -} - -// -// Color cvar implementation -// -#if 0 -#define APART(c) (((c)>>24)&0xff) -#define RPART(c) (((c)>>16)&0xff) -#define GPART(c) (((c)>>8)&0xff) -#define BPART(c) ((c)&0xff) - -FColorCVar::FColorCVar (const char *name, int def, uint32_t flags, void (*callback)(FColorCVar &), const char* descr) -: FIntCVar (name, def, flags, reinterpret_cast(callback), descr) -{ -} - -ECVarType FColorCVar::GetRealType () const -{ - return CVAR_Color; -} - -UCVarValue FColorCVar::GetGenericRep (ECVarType type) const -{ - return FromInt2 (Value, type); -} - -UCVarValue FColorCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromInt2 (DefaultValue, type); -} - -void FColorCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - DefaultValue = ToInt2 (value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -UCVarValue FColorCVar::FromInt2 (int value, ECVarType type) -{ - if (type == CVAR_String) - { - UCVarValue ret; - snprintf (cstrbuf, sizeof(cstrbuf), "%02x %02x %02x", - RPART(value), GPART(value), BPART(value)); - ret.String = cstrbuf; - return ret; - } - return FromInt (value, type); -} - -int FColorCVar::ToInt2 (UCVarValue value, ECVarType type) -{ - int ret; - -#if 0 - if (type == CVAR_String) - { - FString string; - // Only allow named colors after the screen exists (i.e. after - // we've got some lumps loaded, so X11R6RGB can be read). Since - // the only time this might be called before that is when loading - // zdoom.ini, this shouldn't be a problem. - if (screen && !(string = V_GetColorStringByName (value.String)).IsEmpty() ) - { - ret = V_GetColorFromString (NULL, string); - } - else - { - ret = V_GetColorFromString (NULL, value.String); - } - } - else -#endif - { - ret = ToInt (value, type); - } - return ret; -} -#endif - -// -// More base cvar stuff -// - -void FBaseCVar::ResetColors () -{ - FBaseCVar *var = CVars; - - while (var) - { - if (var->GetRealType () == CVAR_Color) - { - var->DoSet (var->GetGenericRep (CVAR_Int), CVAR_Int); - } - var = var->m_Next; - } -} - -void FBaseCVar::ResetToDefault () -{ - if (!(Flags & CVAR_ISDEFAULT)) - { - UCVarValue val; - ECVarType type; - - val = GetFavoriteRepDefault (&type); - SetGenericRep (val, type); - Flags |= CVAR_ISDEFAULT; - } -} - -void FBaseCVar::MarkUnsafe() -{ -} - -// -// Flag cvar implementation -// -// This type of cvar is not a "real" cvar. Instead, it gets and sets -// the value of a FIntCVar, modifying it bit-by-bit. As such, it has -// no default, and is not written to the .cfg or transferred around -// the network. The "host" cvar is responsible for that. -// - -FFlagCVar::FFlagCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr) -: FBaseCVar (name, 0, NULL, descr), -ValueVar (realvar), -BitVal (bitval) -{ - int bit; - - Flags &= ~CVAR_ISDEFAULT; - - assert (bitval != 0); - - bit = 0; - while ((bitval >>= 1) != 0) - { - ++bit; - } - BitNum = bit; - - assert ((1u << BitNum) == BitVal); -} - -ECVarType FFlagCVar::GetRealType () const -{ - return CVAR_DummyBool; -} - -UCVarValue FFlagCVar::GetGenericRep (ECVarType type) const -{ - return FromBool ((ValueVar & BitVal) != 0, type); -} - -UCVarValue FFlagCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Bool; - ret.Bool = (ValueVar & BitVal) != 0; - return ret; -} - -UCVarValue FFlagCVar::GetGenericRepDefault (ECVarType type) const -{ - ECVarType dummy; - UCVarValue def; - def = ValueVar.GetFavoriteRepDefault (&dummy); - return FromBool ((def.Int & BitVal) != 0, type); -} - -UCVarValue FFlagCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - ECVarType dummy; - UCVarValue def; - def = ValueVar.GetFavoriteRepDefault (&dummy); - def.Bool = (def.Int & BitVal) != 0; - *type = CVAR_Bool; - return def; -} - -void FFlagCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - bool newdef = ToBool (value, type); - ECVarType dummy; - UCVarValue def; - def = ValueVar.GetFavoriteRepDefault (&dummy); - if (newdef) - def.Int |= BitVal; - else - def.Int &= ~BitVal; - ValueVar.SetGenericRepDefault (def, CVAR_Int); -} - -void FFlagCVar::DoSet (UCVarValue value, ECVarType type) -{ - bool newval = ToBool (value, type); - -#if 0 - // Server cvars that get changed by this need to use a special message, because - // changes are not processed until the next net update. This is a problem with - // exec scripts because all flags will base their changes off of the value of - // the "master" cvar at the time the script was run, overriding any changes - // another flag might have made to the same cvar earlier in the script. - if ((ValueVar.GetFlags() & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) - { - if (netgame && !players[consoleplayer].settings_controller) - { - Printf ("Only setting controllers can change %s\n", Name); - return; - } - D_SendServerFlagChange (&ValueVar, BitNum, newval); - } - else -#endif - { - int val = *ValueVar; - if (newval) - val |= BitVal; - else - val &= ~BitVal; - ValueVar = val; - } -} - -// -// Mask cvar implementation -// -// Similar to FFlagCVar but can have multiple bits -// - -FMaskCVar::FMaskCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr) -: FBaseCVar (name, 0, NULL, descr), -ValueVar (realvar), -BitVal (bitval) -{ - int bit; - - Flags &= ~CVAR_ISDEFAULT; - - assert (bitval != 0); - - bit = 0; - while ((bitval & 1) == 0) - { - ++bit; - bitval >>= 1; - } - BitNum = bit; -} - -ECVarType FMaskCVar::GetRealType () const -{ - return CVAR_DummyInt; -} - -UCVarValue FMaskCVar::GetGenericRep (ECVarType type) const -{ - return FromInt ((ValueVar & BitVal) >> BitNum, type); -} - -UCVarValue FMaskCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Int; - ret.Int = (ValueVar & BitVal) >> BitNum; - return ret; -} - -UCVarValue FMaskCVar::GetGenericRepDefault (ECVarType type) const -{ - ECVarType dummy; - UCVarValue def; - def = ValueVar.GetFavoriteRepDefault (&dummy); - return FromInt ((def.Int & BitVal) >> BitNum, type); -} - -UCVarValue FMaskCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - ECVarType dummy; - UCVarValue def; - def = ValueVar.GetFavoriteRepDefault (&dummy); - def.Int = (def.Int & BitVal) >> BitNum; - *type = CVAR_Int; - return def; -} - -void FMaskCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - int val = ToInt(value, type) << BitNum; - ECVarType dummy; - UCVarValue def; - def = ValueVar.GetFavoriteRepDefault (&dummy); - def.Int &= ~BitVal; - def.Int |= val; - ValueVar.SetGenericRepDefault (def, CVAR_Int); -} - -void FMaskCVar::DoSet (UCVarValue value, ECVarType type) -{ - int val = ToInt(value, type) << BitNum; - -#if 0 - // Server cvars that get changed by this need to use a special message, because - // changes are not processed until the next net update. This is a problem with - // exec scripts because all flags will base their changes off of the value of - // the "master" cvar at the time the script was run, overriding any changes - // another flag might have made to the same cvar earlier in the script. - if ((ValueVar.GetFlags() & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) - { - if (netgame && !players[consoleplayer].settings_controller) - { - Printf ("Only setting controllers can change %s\n", Name); - return; - } - // Ugh... - for(int i = 0; i < 32; i++) - { - if (BitVal & (1<GetName(), ((*(FBaseCVar **)b))->GetName()); -} - -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) - { - if ((cvar->Flags & filter)) - cvars.Push(cvar); - } - // Now sort them, so they're in a deterministic order and not whatever - // order the linker put them in. - if (cvars.Size() > 0) - { - qsort(&cvars[0], cvars.Size(), sizeof(FBaseCVar *), sortcvars); - } -} - -void C_WriteCVars (uint8_t **demo_p, uint32_t filter, bool compact) -{ - 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 (uint32_t filter, bool compact) -{ - FBaseCVar *cvar; - FString dump; - - if (compact) - { - TArray cvars; - dump.AppendFormat("\\\\%ux", filter); - FilterCompactCVars(cvars, filter); - while (cvars.Pop (cvar)) - { - UCVarValue val = cvar->GetGenericRep(CVAR_String); - dump << '\\' << val.String; - } - } - else - { - for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) - { - if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE))) - { - UCVarValue val = cvar->GetGenericRep(CVAR_String); - dump << '\\' << cvar->GetName() << '\\' << val.String; - } - } - } - return dump; -} - -void C_ReadCVars (uint8_t **demo_p) -{ - char *ptr = *((char **)demo_p); - char *breakpt; - - if (*ptr++ != '\\') - return; - - if (*ptr == '\\') - { // compact mode - TArray cvars; - FBaseCVar *cvar; - uint32_t filter; - - ptr++; - breakpt = strchr (ptr, '\\'); - *breakpt = 0; - filter = strtoul (ptr, NULL, 16); - *breakpt = '\\'; - ptr = breakpt + 1; - - FilterCompactCVars (cvars, filter); - - while (cvars.Pop (cvar)) - { - UCVarValue val; - breakpt = strchr (ptr, '\\'); - if (breakpt) - *breakpt = 0; - val.String = ptr; - cvar->ForceSet (val, CVAR_String); - if (breakpt) - { - *breakpt = '\\'; - ptr = breakpt + 1; - } - else - break; - } - } - else - { - char *value; - - while ( (breakpt = strchr (ptr, '\\')) ) - { - *breakpt = 0; - value = breakpt + 1; - if ( (breakpt = strchr (value, '\\')) ) - *breakpt = 0; - - cvar_set (ptr, value); - - *(value - 1) = '\\'; - if (breakpt) - { - *breakpt = '\\'; - ptr = breakpt + 1; - } - else - { - break; - } - } - } - *demo_p += strlen (*((char **)demo_p)) + 1; -} - -struct FCVarBackup -{ - FString Name, String; -}; -static TArray CVarBackups; - -void C_BackupCVars (void) -{ - assert(CVarBackups.Size() == 0); - CVarBackups.Clear(); - - FCVarBackup backup; - - for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->m_Next) - { - if ((cvar->Flags & (CVAR_SERVERINFO|CVAR_DEMOSAVE)) && !(cvar->Flags & CVAR_LATCH)) - { - backup.Name = cvar->GetName(); - backup.String = cvar->GetGenericRep(CVAR_String).String; - CVarBackups.Push(backup); - } - } -} - -void C_RestoreCVars (void) -{ - for (unsigned int i = 0; i < CVarBackups.Size(); ++i) - { - cvar_set(CVarBackups[i].Name, CVarBackups[i].String); - } - C_ForgetCVars(); -} - -void C_ForgetCVars (void) -{ - CVarBackups.Clear(); -} - -FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev) -{ - FBaseCVar *var; - FBaseCVar *dummy; - - 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; -} - -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; -} - - -//=========================================================================== -// -// C_CreateCVar -// -// Create a new cvar with the specified name and type. It should not already -// exist. -// -//=========================================================================== - -FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, uint32_t flags) -{ - assert(FindCVar(var_name, NULL) == NULL); - flags |= CVAR_AUTO; - switch (var_type) - { - case CVAR_Bool: return new FBoolCVar(var_name, 0, flags); - case CVAR_Int: return new FIntCVar(var_name, 0, flags); - case CVAR_Float: return new FFloatCVar(var_name, 0, flags); - case CVAR_String: return new FStringCVar(var_name, NULL, flags); - //case CVAR_Color: return new FColorCVar(var_name, 0, flags); - default: return NULL; - } -} - -void UnlatchCVars (void) -{ - for (const FLatchedValue& var : LatchedValues) - { - uint32_t oldflags = var.Variable->Flags; - var.Variable->Flags &= ~(CVAR_LATCH | CVAR_SERVERINFO); - var.Variable->SetGenericRep (var.Value, var.Type); - if (var.Type == CVAR_String) - delete[] var.Value.String; - var.Variable->Flags = oldflags; - } - - LatchedValues.Clear(); -} - -void DestroyCVarsFlagged (uint32_t flags) -{ - FBaseCVar *cvar = CVars; - FBaseCVar *next = cvar; - - while(cvar) - { - next = cvar->m_Next; - - if(cvar->Flags & flags) - delete cvar; - - cvar = next; - } -} - -void C_SetCVarsToDefaults (void) -{ - FBaseCVar *cvar = CVars; - - while (cvar) - { - // Only default save-able cvars - if (cvar->Flags & CVAR_ARCHIVE) - { - UCVarValue val; - ECVarType type; - val = cvar->GetFavoriteRepDefault (&type); - cvar->SetGenericRep (val, type); - } - cvar = cvar->m_Next; - } -} - -void C_ArchiveCVars (FConfigFile *f, uint32_t filter) -{ - FBaseCVar *cvar = CVars; - - while (cvar) - { - if ((cvar->Flags & - (CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_AUTO|CVAR_SERVERINFO|CVAR_NOSAVE)) - == filter) - { - const char *const value = (cvar->Flags & CVAR_ISDEFAULT) - ? cvar->GetGenericRep(CVAR_String).String - : cvar->SafeValue.GetChars(); - f->SetValueForKey(cvar->GetName(), value); - } - cvar = cvar->m_Next; - } -} - -#if 0 -EXTERN_CVAR(Bool, sv_cheats); - -void FBaseCVar::CmdSet (const char *newval) -{ - MarkUnsafe(); - - UCVarValue val; - - // Casting away the const is safe in this case. - val.String = const_cast(newval); - SetGenericRep (val, CVAR_String); - - if (GetFlags() & CVAR_NOSET) - Printf ("%s is write protected.\n", GetName()); - else if (GetFlags() & CVAR_LATCH) - Printf ("%s will be changed for next game.\n", GetName()); -} - -CCMD (set) -{ - if (argv.argc() != 3) - { - Printf ("usage: set \n"); - } - else - { - FBaseCVar *var; - - var = FindCVar (argv[1], NULL); - if (var == NULL) - var = new FStringCVar (argv[1], NULL, CVAR_AUTO | CVAR_UNSETTABLE | cvar_defflags); - - var->CmdSet (argv[2]); - } -} - -CCMD (unset) -{ - if (argv.argc() != 2) - { - Printf ("usage: unset \n"); - } - else - { - FBaseCVar *var = FindCVar (argv[1], NULL); - if (var != NULL) - { - if (var->GetFlags() & CVAR_UNSETTABLE) - { - delete var; - } - else - { - Printf ("Cannot unset %s\n", argv[1]); - } - } - } -} - -CCMD (get) -{ - FBaseCVar *var, *prev; - - if (argv.argc() >= 2) - { - if ( (var = FindCVar (argv[1], &prev)) ) - { - UCVarValue val; - val = var->GetGenericRep (CVAR_String); - Printf ("\"%s\" is \"%s\"\n", var->GetName(), val.String); - } - else - { - Printf ("\"%s\" is unset\n", argv[1]); - } - } - else - { - Printf ("get: need variable name\n"); - } -} - -CCMD (toggle) -{ - FBaseCVar *var, *prev; - UCVarValue val; - - if (argv.argc() > 1) - { - if ( (var = FindCVar (argv[1], &prev)) ) - { - var->MarkUnsafe(); - - val = var->GetGenericRep (CVAR_Bool); - val.Bool = !val.Bool; - var->SetGenericRep (val, CVAR_Bool); - Printf ("\"%s\" = \"%s\"\n", var->GetName(), - val.Bool ? "true" : "false"); - } - } -} - -void FBaseCVar::ListVars (const char *filter, bool plain) -{ - FBaseCVar *var = CVars; - int count = 0; - - while (var) - { - if (CheckWildcards (filter, var->GetName())) - { - uint32_t flags = var->GetFlags(); - if (plain) - { // plain formatting does not include user-defined cvars - if (!(flags & CVAR_UNSETTABLE)) - { - ++count; - Printf ("%s : %s\n", var->GetName(), var->GetHumanString()); - } - } - else - { - ++count; - Printf ("%c%c%c%c%c %s = %s\n", - flags & CVAR_ARCHIVE ? 'A' : ' ', - flags & CVAR_USERINFO ? 'U' : - flags & CVAR_SERVERINFO ? 'S' : - flags & CVAR_AUTO ? 'C' : ' ', - flags & CVAR_NOSET ? '-' : - flags & CVAR_LATCH ? 'L' : - flags & CVAR_UNSETTABLE ? '*' : ' ', - flags & CVAR_MOD ? 'M' : ' ', - flags & CVAR_IGNORE ? 'X' : ' ', - var->GetName(), - var->GetHumanString()); - } - } - var = var->m_Next; - } - Printf ("%d cvars\n", count); -} - -CCMD (cvarlist) -{ - if (argv.argc() == 1) - { - FBaseCVar::ListVars (NULL, false); - } - else - { - FBaseCVar::ListVars (argv[1], false); - } -} - -CCMD (cvarlistplain) -{ - FBaseCVar::ListVars (NULL, true); -} - -CCMD (archivecvar) -{ - - if (argv.argc() == 1) - { - Printf ("Usage: archivecvar \n"); - } - else - { - FBaseCVar *var = FindCVar (argv[1], NULL); - - if (var != NULL && (var->GetFlags() & CVAR_AUTO)) - { - var->SetArchiveBit (); - } - } -} -#endif \ No newline at end of file diff --git a/source/common/console/c_cvars.h b/source/common/console/c_cvars.h deleted file mode 100644 index e1ea9c4eb..000000000 --- a/source/common/console/c_cvars.h +++ /dev/null @@ -1,436 +0,0 @@ -/* -** c_cvars.h -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#ifndef __C_CVARS_H__ -#define __C_CVARS_H__ -#include "zstring.h" -#include "tarray.h" - -/* -========================================================== - -CVARS (console variables) - -========================================================== -*/ - -enum -{ - CVAR_ARCHIVE = 1, // set to cause it to be saved to config - //CVAR_USERINFO = 2, // added to userinfo when changed - CVAR_SERVERINFO = 4, // added to serverinfo when changed - CVAR_NOSET = 8, // don't allow change from console at all, - // but can be set from the command line - CVAR_LATCH = 16, // save changes until server restart - CVAR_UNSETTABLE = 32, // can unset this var from console - CVAR_DEMOSAVE = 64, // save the value of this cvar in a demo - CVAR_ISDEFAULT = 128, // is cvar unchanged since creation? - CVAR_AUTO = 256, // allocated; needs to be freed when destroyed - CVAR_NOINITCALL = 512, // don't call callback at game start - CVAR_GLOBALCONFIG = 1024, // cvar is saved to global config section - CVAR_VIDEOCONFIG = 2048, // cvar is saved to video config section (not implemented) - CVAR_NOSAVE = 4096, // when used with CVAR_SERVERINFO, do not save var to savegame - //CVAR_MOD = 8192, // cvar was defined by a mod - //CVAR_IGNORE = 16384,// do not send cvar across the network/inaccesible from ACS (dummy mod cvar) - //CVAR_CHEAT = 32768,// can be set only when sv_cheats is enabled - //CVAR_UNSAFECONTEXT = 65536,// cvar value came from unsafe context -}; - -union UCVarValue -{ - bool Bool; - int Int; - float Float; - const char *String; -}; - -enum ECVarType -{ - CVAR_Bool, - CVAR_Int, - 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 -}; - -class FConfigFile; - -class FxCVar; - -class FBaseCVar -{ -public: - FBaseCVar (const char *name, uint32_t flags, void (*callback)(FBaseCVar &), const char *descr); - virtual ~FBaseCVar (); - - inline void Callback () { if (m_Callback) m_Callback (*this); } - - 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); - void SetGenericRep (UCVarValue value, ECVarType type); - void ResetToDefault (); - void SetArchiveBit () { Flags |= CVAR_ARCHIVE; } - void MarkUnsafe(); - - virtual ECVarType GetRealType () const = 0; - - virtual const char *GetHumanString(int precision=-1) const; - virtual UCVarValue GetGenericRep (ECVarType type) const = 0; - virtual UCVarValue GetFavoriteRep (ECVarType *type) const = 0; - - virtual UCVarValue GetGenericRepDefault (ECVarType type) const = 0; - virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const = 0; - virtual void SetGenericRepDefault (UCVarValue value, ECVarType type) = 0; - - FBaseCVar &operator= (const FBaseCVar &var) - { UCVarValue val; ECVarType type; val = var.GetFavoriteRep (&type); SetGenericRep (val, type); return *this; } - - static void EnableNoSet (); // enable the honoring of CVAR_NOSET - static void EnableCallbacks (); - static void DisableCallbacks (); - static void ResetColors (); // recalc color cvars' indices after screen change - - static void ListVars (const char *filter, bool plain); - - const char *GetDescription() const { return Description; }; - -protected: - virtual void DoSet (UCVarValue value, ECVarType type) = 0; - - static bool ToBool (UCVarValue value, ECVarType type); - static int ToInt (UCVarValue value, ECVarType type); - static float ToFloat (UCVarValue value, ECVarType type); - static const char *ToString (UCVarValue value, ECVarType type); - static UCVarValue FromBool (bool value, ECVarType type); - static UCVarValue FromInt (int value, ECVarType type); - static UCVarValue FromFloat (float value, ECVarType type); - static UCVarValue FromString (const char *value, ECVarType type); - - FString VarName; - FString SafeValue; - FString Description; - uint32_t Flags; - -private: - FBaseCVar (const FBaseCVar &var) = delete; - FBaseCVar (const char *name, uint32_t flags); - - void (*m_Callback)(FBaseCVar &); - FBaseCVar *m_Next; - - static bool m_UseCallback; - static bool m_DoNoSet; - - friend FString C_GetMassCVarString (uint32_t filter, bool compact); - friend void C_ReadCVars (uint8_t **demo_p); - friend void C_BackupCVars (void); - friend FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev); - friend FBaseCVar *FindCVarSub (const char *var_name, int namelen); - friend void UnlatchCVars (void); - friend void DestroyCVarsFlagged (uint32_t flags); - friend void C_ArchiveCVars (FConfigFile *f, uint32_t filter); - friend void C_SetCVarsToDefaults (void); - friend void FilterCompactCVars (TArray &cvars, uint32_t filter); - 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_t 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 (uint8_t **demo_p, uint32_t filter, bool compact=false); - -// Read all cvars from *demo_p and set them appropriately. -void C_ReadCVars (uint8_t **demo_p); - -// Backup demo cvars. Called before a demo starts playing to save all -// cvars the demo might change. -void C_BackupCVars (void); - -// Finds a named cvar -FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev); -FBaseCVar *FindCVarSub (const char *var_name, int namelen); - -// Create a new cvar with the specified name and type -FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, uint32_t flags); - -// Called from G_InitNew() -void UnlatchCVars (void); - -// Destroy CVars with the matching flags; called from CCMD(restart) -void DestroyCVarsFlagged (uint32_t flags); - -// archive cvars to FILE f -void C_ArchiveCVars (FConfigFile *f, uint32_t filter); - -// initialize cvars to default values after they are created -void C_SetCVarsToDefaults (void); - -void FilterCompactCVars (TArray &cvars, uint32_t filter); - -void C_DeinitConsole(); - -class FBoolCVar : public FBaseCVar -{ - friend class FxCVar; -public: - FBoolCVar (const char *name, bool def, uint32_t flags, void (*callback)(FBoolCVar &)=NULL, const char* descr = nullptr); - - virtual ECVarType GetRealType () const; - - virtual UCVarValue GetGenericRep (ECVarType type) const; - virtual UCVarValue GetFavoriteRep (ECVarType *type) const; - virtual UCVarValue GetGenericRepDefault (ECVarType type) const; - virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const; - virtual void SetGenericRepDefault (UCVarValue value, ECVarType type); - - inline bool operator= (bool boolval) - { UCVarValue val; val.Bool = boolval; SetGenericRep (val, CVAR_Bool); return boolval; } - inline operator bool () const { return Value; } - inline bool operator *() const { return Value; } - -protected: - virtual void DoSet (UCVarValue value, ECVarType type); - - bool Value; - bool DefaultValue; -}; - -class FIntCVar : public FBaseCVar -{ - friend class FxCVar; -public: - FIntCVar (const char *name, int def, uint32_t flags, void (*callback)(FIntCVar &)=NULL, const char* descr = nullptr); - - virtual ECVarType GetRealType () const; - - virtual UCVarValue GetGenericRep (ECVarType type) const; - virtual UCVarValue GetFavoriteRep (ECVarType *type) const; - virtual UCVarValue GetGenericRepDefault (ECVarType type) const; - virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const; - virtual void SetGenericRepDefault (UCVarValue value, ECVarType type); - - int operator= (int intval) - { UCVarValue val; val.Int = intval; SetGenericRep (val, CVAR_Int); return intval; } - inline operator int () const { return Value; } - inline int operator *() const { return Value; } - -protected: - virtual void DoSet (UCVarValue value, ECVarType type); - - int Value; - int DefaultValue; - - friend class FFlagCVar; -}; - -class FFloatCVar : public FBaseCVar -{ - friend class FxCVar; -public: - FFloatCVar (const char *name, float def, uint32_t flags, void (*callback)(FFloatCVar &)=NULL, const char* descr = nullptr); - - virtual ECVarType GetRealType () const; - - virtual UCVarValue GetGenericRep (ECVarType type) const; - virtual UCVarValue GetFavoriteRep (ECVarType *type) const; - virtual UCVarValue GetGenericRepDefault (ECVarType type) const; - virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const; - virtual void SetGenericRepDefault (UCVarValue value, ECVarType type); - const char *GetHumanString(int precision) const override; - - float operator= (float floatval) - { UCVarValue val; val.Float = floatval; SetGenericRep (val, CVAR_Float); return floatval; } - inline operator float () const { return Value; } - inline float operator *() const { return Value; } - -protected: - virtual void DoSet (UCVarValue value, ECVarType type); - - float Value; - float DefaultValue; -}; - -class FStringCVar : public FBaseCVar -{ - friend class FxCVar; -public: - FStringCVar (const char *name, const char *def, uint32_t flags, void (*callback)(FStringCVar &)=NULL, const char* descr = nullptr); - ~FStringCVar (); - - virtual ECVarType GetRealType () const; - - virtual UCVarValue GetGenericRep (ECVarType type) const; - virtual UCVarValue GetFavoriteRep (ECVarType *type) const; - virtual UCVarValue GetGenericRepDefault (ECVarType type) const; - virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const; - virtual void SetGenericRepDefault (UCVarValue value, ECVarType type); - - const char *operator= (const char *stringrep) - { UCVarValue val; val.String = const_cast(stringrep); SetGenericRep (val, CVAR_String); return stringrep; } - inline operator const char * () const { return mValue; } - inline const char *operator *() const { return mValue; } - -protected: - virtual void DoSet (UCVarValue value, ECVarType type); - - FString mValue; - FString mDefaultValue; -}; - -#if 0 -class FColorCVar : public FIntCVar -{ - friend class FxCVar; -public: - FColorCVar (const char *name, int def, uint32_t flags, void (*callback)(FColorCVar &)=NULL, const char* descr = nullptr); - - virtual ECVarType GetRealType () const; - - virtual UCVarValue GetGenericRep (ECVarType type) const; - virtual UCVarValue GetGenericRepDefault (ECVarType type) const; - virtual void SetGenericRepDefault (UCVarValue value, ECVarType type); - - inline operator uint32_t () const { return Value; } - inline uint32_t operator *() const { return Value; } - -protected: - virtual void DoSet (UCVarValue value, ECVarType type); - - static UCVarValue FromInt2 (int value, ECVarType type); - static int ToInt2 (UCVarValue value, ECVarType type); -}; -#endif - -class FFlagCVar : public FBaseCVar -{ - friend class FxCVar; -public: - FFlagCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr = nullptr); - - virtual ECVarType GetRealType () const; - - virtual UCVarValue GetGenericRep (ECVarType type) const; - virtual UCVarValue GetFavoriteRep (ECVarType *type) const; - virtual UCVarValue GetGenericRepDefault (ECVarType type) const; - virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const; - virtual void SetGenericRepDefault (UCVarValue value, ECVarType type); - - bool operator= (bool boolval) - { UCVarValue val; val.Bool = boolval; SetGenericRep (val, CVAR_Bool); return boolval; } - bool operator= (FFlagCVar &flag) - { UCVarValue val; val.Bool = !!flag; SetGenericRep (val, CVAR_Bool); return val.Bool; } - inline operator int () const { return (ValueVar & BitVal); } - inline int operator *() const { return (ValueVar & BitVal); } - -protected: - virtual void DoSet (UCVarValue value, ECVarType type); - - FIntCVar &ValueVar; - uint32_t BitVal; - int BitNum; -}; - -class FMaskCVar : public FBaseCVar -{ - friend class FxCVar; -public: - FMaskCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr = nullptr); - - virtual ECVarType GetRealType () const; - - virtual UCVarValue GetGenericRep (ECVarType type) const; - virtual UCVarValue GetFavoriteRep (ECVarType *type) const; - virtual UCVarValue GetGenericRepDefault (ECVarType type) const; - virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const; - virtual void SetGenericRepDefault (UCVarValue value, ECVarType type); - - inline operator int () const { return (ValueVar & BitVal) >> BitNum; } - inline int operator *() const { return (ValueVar & BitVal) >> BitNum; } - -protected: - virtual void DoSet (UCVarValue value, ECVarType type); - - FIntCVar &ValueVar; - uint32_t BitVal; - int BitNum; -}; - -extern int cvar_defflags; - -FBaseCVar *cvar_set (const char *var_name, const char *value); -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); } - - - -// Restore demo cvars. Called after demo playback to restore all cvars -// that might possibly have been changed during the course of demo playback. -void C_RestoreCVars (void); - -void C_ForgetCVars (void); - - -#define CUSTOM_CVAR(type,name,def,flags) \ - static void cvarfunc_##name(F##type##CVar &); \ - F##type##CVar name (#name, def, flags, cvarfunc_##name); \ - static void cvarfunc_##name(F##type##CVar &self) - -#define CVAR(type,name,def,flags) \ - F##type##CVar name (#name, def, flags); - -#define EXTERN_CVAR(type,name) extern F##type##CVar 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); \ - static void cvarfunc_##name(F##type##CVar &self) - -#define CVARD(type,name,def,flags, descr) \ - F##type##CVar name (#name, def, flags, descr); - - -extern FBaseCVar *CVars; - -#endif //__C_CVARS_H__ diff --git a/source/common/utility/file_zip.cpp b/source/common/utility/file_zip.cpp new file mode 100644 index 000000000..b94289e73 --- /dev/null +++ b/source/common/utility/file_zip.cpp @@ -0,0 +1,476 @@ +/* +** file_zip.cpp +** +**--------------------------------------------------------------------------- +** Copyright 1998-2009 Randy Heit +** Copyright 2005-2009 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#include +#include +#include "osd.h" +#include "file_zip.h" +//#include "cmdlib.h" +#include "templates.h" +//#include "v_text.h" +//#include "w_wad.h" +#include "w_zip.h" + +#define BUFREADCOMMENT (0x400) + +//========================================================================== +// +// Decompression subroutine +// +//========================================================================== + +static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags) +{ + try + { + switch (Method) + { + case METHOD_STORED: + { + Reader.Read(Cache, LumpSize); + break; + } + + case METHOD_DEFLATE: + case METHOD_BZIP2: + case METHOD_LZMA: + { + FileReader frz; + if (frz.OpenDecompressor(Reader, LumpSize, Method, false, [](const char* err) { throw std::runtime_error(err); })) + { + frz.Read(Cache, LumpSize); + } + break; + } + + default: + assert(0); + return false; + } + } + catch (std::runtime_error &err) + { + OSD_Printf("%s\n", err.what()); + return false; + } + return true; +} + +bool FCompressedBuffer::Decompress(char *destbuffer) +{ + FileReader mr; + mr.OpenMemory(mBuffer, mCompressedSize); + return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags); +} + +//----------------------------------------------------------------------- +// +// Finds the central directory end record in the end of the file. +// Taken from Quake3 source but the file in question is not GPL'ed. ;) +// +//----------------------------------------------------------------------- + +static uint32_t Zip_FindCentralDir(FileReader &fin) +{ + unsigned char buf[BUFREADCOMMENT + 4]; + uint32_t FileSize; + uint32_t uBackRead; + uint32_t uMaxBack; // maximum size of global comment + uint32_t uPosFound=0; + + FileSize = (uint32_t)fin.GetLength(); + uMaxBack = std::min(0xffff, FileSize); + + uBackRead = 4; + while (uBackRead < uMaxBack) + { + uint32_t uReadSize, uReadPos; + int i; + if (uBackRead + BUFREADCOMMENT > uMaxBack) + uBackRead = uMaxBack; + else + uBackRead += BUFREADCOMMENT; + uReadPos = FileSize - uBackRead; + + uReadSize = std::min((BUFREADCOMMENT + 4), (FileSize - uReadPos)); + + if (fin.Seek(uReadPos, FileReader::SeekSet) != 0) break; + + if (fin.Read(buf, (int32_t)uReadSize) != (int32_t)uReadSize) break; + + for (i = (int)uReadSize - 3; (i--) > 0;) + { + if (buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6) + { + uPosFound = uReadPos + i; + break; + } + } + + if (uPosFound != 0) + break; + } + return uPosFound; +} + +//========================================================================== +// +// Zip file +// +//========================================================================== + +FZipFile::FZipFile(const char * filename, FileReader &file) +: FResourceFile(filename, file) +{ + Lumps = NULL; +} + +bool FZipFile::Open(bool quiet) +{ + uint32_t centraldir = Zip_FindCentralDir(Reader); + FZipEndOfCentralDirectory info; + int skipped = 0; + + Lumps = NULL; + + if (centraldir == 0) + { + if (!quiet) OSD_Printf("\n%s: ZIP file corrupt!\n", FileName.GetChars()); + return false; + } + + // Read the central directory info. + Reader.Seek(centraldir, FileReader::SeekSet); + Reader.Read(&info, sizeof(FZipEndOfCentralDirectory)); + + // No multi-disk zips! + if (info.NumEntries != info.NumEntriesOnAllDisks || + info.FirstDisk != 0 || info.DiskNumber != 0) + { + if (!quiet) OSD_Printf("\n%s: Multipart Zip files are not supported.\n", FileName.GetChars()); + return false; + } + + NumLumps = LittleShort(info.NumEntries); + Lumps = new FZipLump[NumLumps]; + + // Load the entire central directory. Too bad that this contains variable length entries... + int dirsize = LittleLong(info.DirectorySize); + void *directory = malloc(dirsize); + Reader.Seek(LittleLong(info.DirectoryOffset), FileReader::SeekSet); + Reader.Read(directory, dirsize); + + char *dirptr = (char*)directory; + FZipLump *lump_p = Lumps; + + FString name0; + bool foundspeciallump = false; + + // Check if all files have the same prefix so that this can be stripped out. + // This will only be done if there is either a MAPINFO, ZMAPINFO or GAMEINFO lump in the subdirectory, denoting a ZDoom mod. + if (NumLumps > 1) for (uint32_t i = 0; i < NumLumps; i++) + { + FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; + + int len = LittleShort(zip_fh->NameLength); + FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); + + dirptr += sizeof(FZipCentralDirectoryInfo) + + LittleShort(zip_fh->NameLength) + + LittleShort(zip_fh->ExtraLength) + + LittleShort(zip_fh->CommentLength); + + if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. + { + free(directory); + if (!quiet) OSD_Printf("\n%s: Central directory corrupted.", FileName.GetChars()); + return false; + } + + name.ToLower(); + if (i == 0) + { + // check for special names, if one of these gets found this must be treated as a normal zip. + bool isspecial = !name.Compare("flats/") || + name.IndexOf("/") < 0 || + !name.Compare("textures/") || + !name.Compare("hires/") || + !name.Compare("sprites/") || + !name.Compare("voxels/") || + !name.Compare("colormaps/") || + !name.Compare("acs/") || + !name.Compare("maps/") || + !name.Compare("voices/") || + !name.Compare("patches/") || + !name.Compare("graphics/") || + !name.Compare("sounds/") || + !name.Compare("music/"); + if (isspecial) break; + name0 = name; + } + else + { + if (name.IndexOf(name0) != 0) + { + name0 = ""; + break; + } + else if (!foundspeciallump) + { + // at least one of the more common definition lumps must be present. + if (name.IndexOf(name0 + "mapinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "zmapinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "gameinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "sndinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "sbarinfo") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "menudef") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "gldefs") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "animdefs") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "decorate.") == 0) foundspeciallump = true; // DECORATE is a common subdirectory name, so the check needs to be a bit different. + else if (name.Compare(name0 + "decorate") == 0) foundspeciallump = true; + else if (name.IndexOf(name0 + "zscript.") == 0) foundspeciallump = true; // same here. + else if (name.Compare(name0 + "zscript") == 0) foundspeciallump = true; + else if (name.Compare(name0 + "maps/") == 0) foundspeciallump = true; + } + } + } + // If it ran through the list without finding anything it should not attempt any path remapping. + if (!foundspeciallump) name0 = ""; + + dirptr = (char*)directory; + lump_p = Lumps; + for (uint32_t i = 0; i < NumLumps; i++) + { + FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; + + int len = LittleShort(zip_fh->NameLength); + FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); + if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); + dirptr += sizeof(FZipCentralDirectoryInfo) + + LittleShort(zip_fh->NameLength) + + LittleShort(zip_fh->ExtraLength) + + LittleShort(zip_fh->CommentLength); + + if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. + { + free(directory); + if (!quiet) OSD_Printf("\n%s: Central directory corrupted.", FileName.GetChars()); + return false; + } + + // skip Directories + if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize) == 0)) + { + skipped++; + continue; + } + + // Ignore unknown compression formats + zip_fh->Method = LittleShort(zip_fh->Method); + if (zip_fh->Method != METHOD_STORED && + zip_fh->Method != METHOD_DEFLATE && + zip_fh->Method != METHOD_LZMA && + zip_fh->Method != METHOD_BZIP2 && + zip_fh->Method != METHOD_IMPLODE && + zip_fh->Method != METHOD_SHRINK) + { + if (!quiet) OSD_Printf("\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.GetChars(), name.GetChars(), zip_fh->Method); + skipped++; + continue; + } + // Also ignore encrypted entries + zip_fh->Flags = LittleShort(zip_fh->Flags); + if (zip_fh->Flags & ZF_ENCRYPTED) + { + if (!quiet) OSD_Printf("\n%s: '%s' is encrypted. Encryption is not supported.\n", FileName.GetChars(), name.GetChars()); + skipped++; + continue; + } + + name.ToLower(); + + lump_p->LumpNameSetup(name); + lump_p->LumpSize = LittleLong(zip_fh->UncompressedSize); + lump_p->Owner = this; + // The start of the Reader will be determined the first time it is accessed. + lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART; + lump_p->Method = uint8_t(zip_fh->Method); + if (lump_p->Method != METHOD_STORED) lump_p->Flags |= LUMPF_COMPRESSED; + lump_p->GPFlags = zip_fh->Flags; + lump_p->CRC32 = zip_fh->CRC32; + lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); + lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); + + lump_p++; + } + // Resize the lump record array to its actual size + NumLumps -= skipped; + free(directory); + + return true; +} + +//========================================================================== +// +// Zip file +// +//========================================================================== + +FZipFile::~FZipFile() +{ + if (Lumps != NULL) delete [] Lumps; +} + +//========================================================================== +// +// +// +//========================================================================== + +FCompressedBuffer FZipLump::GetRawData() +{ + FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)CompressedSize, Method, GPFlags, CRC32, new char[CompressedSize] }; + if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); + Owner->Reader.Seek(Position, FileReader::SeekSet); + Owner->Reader.Read(cbuf.mBuffer, CompressedSize); + return cbuf; +} + +//========================================================================== +// +// SetLumpAddress +// +//========================================================================== + +void FZipLump::SetLumpAddress() +{ + // This file is inside a zip and has not been opened before. + // Position points to the start of the local file header, which we must + // read and skip so that we can get to the actual file data. + FZipLocalFileHeader localHeader; + int skiplen; + + Owner->Reader.Seek(Position, FileReader::SeekSet); + Owner->Reader.Read(&localHeader, sizeof(localHeader)); + skiplen = LittleShort(localHeader.NameLength) + LittleShort(localHeader.ExtraLength); + Position += sizeof(localHeader) + skiplen; + Flags &= ~LUMPFZIP_NEEDFILESTART; +} + +//========================================================================== +// +// Get reader (only returns non-NULL if not encrypted) +// +//========================================================================== + +FileReader *FZipLump::GetReader() +{ + // Don't return the reader if this lump is encrypted + // In that case always force caching of the lump + if (Method == METHOD_STORED) + { + if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); + Owner->Reader.Seek(Position, FileReader::SeekSet); + return &Owner->Reader; + } + else return NULL; +} + +//========================================================================== +// +// Fills the lump cache and performs decompression +// +//========================================================================== + +int FZipLump::FillCache() +{ + if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); + const char *buffer; + + if (Method == METHOD_STORED && (buffer = Owner->Reader.GetBuffer()) != NULL) + { + // This is an in-memory file so the cache can point directly to the file's data. + Cache = const_cast(buffer) + Position; + RefCount = -1; + return -1; + } + + Owner->Reader.Seek(Position, FileReader::SeekSet); + Cache = new char[LumpSize]; + UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags); + RefCount = 1; + return 1; +} + +//========================================================================== +// +// +// +//========================================================================== + +int FZipLump::GetFileOffset() +{ + if (Method != METHOD_STORED) return -1; + if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); + return Position; +} + +//========================================================================== +// +// File open +// +//========================================================================== + +FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet) +{ + char head[4]; + + if (file.GetLength() >= (long)sizeof(FZipLocalFileHeader)) + { + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileReader::SeekSet); + if (!memcmp(head, "PK\x3\x4", 4)) + { + FResourceFile *rf = new FZipFile(filename, file); + if (rf->Open(quiet)) return rf; + + file = std::move(rf->Reader); // to avoid destruction of reader + delete rf; + } + } + return NULL; +} + diff --git a/source/common/utility/file_zip.h b/source/common/utility/file_zip.h new file mode 100644 index 000000000..466292e40 --- /dev/null +++ b/source/common/utility/file_zip.h @@ -0,0 +1,53 @@ +#ifndef __FILE_ZIP_H +#define __FILE_ZIP_H + +#include "resourcefile.h" + +enum +{ + LUMPFZIP_NEEDFILESTART = 128 +}; + +//========================================================================== +// +// Zip Lump +// +//========================================================================== + +struct FZipLump : public FResourceLump +{ + uint16_t GPFlags; + uint8_t Method; + int CompressedSize; + int Position; + unsigned CRC32; + + virtual FileReader *GetReader(); + virtual int FillCache(); + +private: + void SetLumpAddress(); + virtual int GetFileOffset(); + FCompressedBuffer GetRawData(); +}; + + +//========================================================================== +// +// Zip file +// +//========================================================================== + +class FZipFile : public FResourceFile +{ + FZipLump *Lumps; + +public: + FZipFile(const char * filename, FileReader &file); + virtual ~FZipFile(); + bool Open(bool quiet); + virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } +}; + + +#endif \ No newline at end of file diff --git a/source/common/utility/resourcefile.cpp b/source/common/utility/resourcefile.cpp new file mode 100644 index 000000000..49f747a0e --- /dev/null +++ b/source/common/utility/resourcefile.cpp @@ -0,0 +1,271 @@ +/* +** resourcefile.cpp +** +** Base classes for resource file management +** +**--------------------------------------------------------------------------- +** Copyright 2009 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#include +#include "resourcefile.h" + + +//========================================================================== +// +// File reader that reads from a lump's cache +// +//========================================================================== + +class FLumpReader : public MemoryReader +{ + FResourceLump *source; + +public: + FLumpReader(FResourceLump *src) + : MemoryReader(NULL, src->LumpSize), source(src) + { + src->CacheLump(); + bufptr = src->Cache; + } + + ~FLumpReader() + { + source->ReleaseCache(); + } +}; + + +//========================================================================== +// +// Base class for resource lumps +// +//========================================================================== + +FResourceLump::~FResourceLump() +{ + if (Cache != NULL && RefCount >= 0) + { + delete [] Cache; + Cache = NULL; + } + Owner = NULL; +} + + +//========================================================================== +// +// Sets up the lump name information for anything not coming from a WAD file. +// +//========================================================================== + +void FResourceLump::LumpNameSetup(FString iname) +{ + long slash = iname.LastIndexOf('/'); + FString base = (slash >= 0) ? iname.Mid(slash + 1) : iname; + auto dot = base.LastIndexOf('.'); + if (dot >= 0) base.Truncate(dot); + FullName = iname; +} + +//========================================================================== +// +// Returns a file reader to the lump's cache +// +//========================================================================== + +FileReader FResourceLump::NewReader() +{ + return FileReader(new FLumpReader(this)); +} + +//========================================================================== +// +// Caches a lump's content and increases the reference counter +// +//========================================================================== + +void *FResourceLump::CacheLump() +{ + if (Cache != NULL) + { + if (RefCount > 0) RefCount++; + } + else if (LumpSize > 0) + { + FillCache(); + } + return Cache; +} + +//========================================================================== +// +// Decrements reference counter and frees lump if counter reaches 0 +// +//========================================================================== + +int FResourceLump::ReleaseCache() +{ + if (LumpSize > 0 && RefCount > 0) + { + if (--RefCount == 0) + { + delete [] Cache; + Cache = NULL; + } + } + return RefCount; +} + +//========================================================================== +// +// Opens a resource file +// +//========================================================================== + +typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, bool quiet); + +FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet); + + +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly) +{ + return CheckZip(filename, file, quiet); +} + + +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool quiet, bool containeronly) +{ + FileReader file; + if (!file.OpenFile(filename)) return nullptr; + return OpenResourceFile(filename, file, quiet, containeronly); +} + +//========================================================================== +// +// Resource file base class +// +//========================================================================== + +FResourceFile::FResourceFile(const char *filename) + : FileName(filename) +{ +} + +FResourceFile::FResourceFile(const char *filename, FileReader &r) + : FResourceFile(filename) +{ + Reader = std::move(r); +} + +FResourceFile::~FResourceFile() +{ +} + +int lumpcmp(const void * a, const void * b) +{ + FResourceLump * rec1 = (FResourceLump *)a; + FResourceLump * rec2 = (FResourceLump *)b; + + return rec1->FullName.CompareNoCase(rec2->FullName); +} + + +//========================================================================== +// +// Finds a lump by a given name. Used for savegames +// +//========================================================================== + +FResourceLump *FResourceFile::FindLump(const char *name) +{ + for (unsigned i = 0; i < NumLumps; i++) + { + FResourceLump *lump = GetLump(i); + if (!stricmp(name, lump->FullName)) + { + return lump; + } + } + return nullptr; +} + +//========================================================================== +// +// Caches a lump's content and increases the reference counter +// +//========================================================================== + +FileReader *FUncompressedLump::GetReader() +{ + Owner->Reader.Seek(Position, FileReader::SeekSet); + return &Owner->Reader; +} + +//========================================================================== +// +// Caches a lump's content and increases the reference counter +// +//========================================================================== + +int FUncompressedLump::FillCache() +{ + const char * buffer = Owner->Reader.GetBuffer(); + + if (buffer != NULL) + { + // This is an in-memory file so the cache can point directly to the file's data. + Cache = const_cast(buffer) + Position; + RefCount = -1; + return -1; + } + + Owner->Reader.Seek(Position, FileReader::SeekSet); + Cache = new char[LumpSize]; + Owner->Reader.Read(Cache, LumpSize); + RefCount = 1; + return 1; +} + +//========================================================================== +// +// Base class for uncompressed resource files +// +//========================================================================== + +FUncompressedFile::FUncompressedFile(const char *filename) +: FResourceFile(filename) +{} + +FUncompressedFile::FUncompressedFile(const char *filename, FileReader &r) + : FResourceFile(filename, r) +{} + + diff --git a/source/common/utility/resourcefile.h b/source/common/utility/resourcefile.h new file mode 100644 index 000000000..17cca6f83 --- /dev/null +++ b/source/common/utility/resourcefile.h @@ -0,0 +1,136 @@ + + +#ifndef __RESFILE_H +#define __RESFILE_H + +#include +#include "files.h" +#include "zstring.h" + +class FResourceFile; +class FTexture; + +enum ELumpFlags +{ + LUMPF_MAYBEFLAT=1, // might be a flat outside F_START/END + LUMPF_ZIPFILE=2, // contains a full path + LUMPF_EMBEDDED=4, // from an embedded WAD + LUMPF_BLOODCRYPT = 8, // encrypted + LUMPF_COMPRESSED = 16, // compressed + LUMPF_SEQUENTIAL = 32, // compressed but a sequential reader can be retrieved. +}; + +// This holds a compresed Zip entry with all needed info to decompress it. +struct FCompressedBuffer +{ + unsigned mSize; + unsigned mCompressedSize; + int mMethod; + int mZipFlags; + unsigned mCRC32; + char *mBuffer; + + bool Decompress(char *destbuffer); + void Clean() + { + mSize = mCompressedSize = 0; + if (mBuffer != nullptr) + { + delete[] mBuffer; + mBuffer = nullptr; + } + } +}; + +struct FResourceLump +{ + friend class FResourceFile; + + int LumpSize; + FString FullName; // only valid for files loaded from a non-wad archive + uint8_t Flags; + int8_t RefCount; + char * Cache; + FResourceFile * Owner; + FTexture * LinkedTexture; + int Namespace; + + FResourceLump() + { + Cache = NULL; + Owner = NULL; + Flags = 0; + RefCount = 0; + Namespace = 0; // ns_global + LinkedTexture = NULL; + } + + virtual ~FResourceLump(); + virtual FileReader NewReader(); + virtual int GetFileOffset() { return -1; } + virtual int GetIndexNum() const { return 0; } + void LumpNameSetup(FString iname); + + void *CacheLump(); + int ReleaseCache(); + +protected: + virtual int FillCache() { return -1; } + +}; + +class FResourceFile +{ +public: + FileReader Reader; + FString FileName; +protected: + uint32_t NumLumps; + FString Hash; + + FResourceFile(const char *filename); + FResourceFile(const char *filename, FileReader &r); + +private: + uint32_t FirstLump; + +public: + static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool quiet = false, bool containeronly = false); + static FResourceFile *OpenResourceFile(const char *filename, bool quiet = false, bool containeronly = false); + virtual ~FResourceFile(); + // If this FResourceFile represents a directory, the Reader object is not usable so don't return it. + FileReader *GetReader() { return Reader.isOpen()? &Reader : nullptr; } + uint32_t LumpCount() const { return NumLumps; } + uint32_t GetFirstLump() const { return FirstLump; } + void SetFirstLump(uint32_t f) { FirstLump = f; } + const FString &GetHash() const { return Hash; } + + + virtual bool Open(bool quiet) = 0; + virtual FResourceLump *GetLump(int no) = 0; + FResourceLump *FindLump(const char *name); +}; + +struct FUncompressedLump : public FResourceLump +{ + int Position; + + virtual FileReader *GetReader(); + virtual int FillCache(); + virtual int GetFileOffset() { return Position; } + +}; + + +// Base class for uncompressed resource files (WAD, GRP, PAK and single lumps) +class FUncompressedFile : public FResourceFile +{ +protected: + TArray Lumps; + + FUncompressedFile(const char *filename); + FUncompressedFile(const char *filename, FileReader &r); + virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } +}; + +#endif diff --git a/source/common/utility/w_zip.h b/source/common/utility/w_zip.h new file mode 100644 index 000000000..af0ac90e2 --- /dev/null +++ b/source/common/utility/w_zip.h @@ -0,0 +1,68 @@ +#ifndef __W_ZIP +#define __W_ZIP + +#pragma pack(1) +// FZipCentralInfo +struct FZipEndOfCentralDirectory +{ + uint32_t Magic; + uint16_t DiskNumber; + uint16_t FirstDisk; + uint16_t NumEntries; + uint16_t NumEntriesOnAllDisks; + uint32_t DirectorySize; + uint32_t DirectoryOffset; + uint16_t ZipCommentLength; +}; + +// FZipFileInfo +struct FZipCentralDirectoryInfo +{ + uint32_t Magic; + uint8_t VersionMadeBy[2]; + uint8_t VersionToExtract[2]; + uint16_t Flags; + uint16_t Method; + uint16_t ModTime; + uint16_t ModDate; + uint32_t CRC32; + uint32_t CompressedSize; + uint32_t UncompressedSize; + uint16_t NameLength; + uint16_t ExtraLength; + uint16_t CommentLength; + uint16_t StartingDiskNumber; + uint16_t InternalAttributes; + uint32_t ExternalAttributes; + uint32_t LocalHeaderOffset; + // file name and other variable length info follows +}; + +// FZipLocalHeader +struct FZipLocalFileHeader +{ + uint32_t Magic; + uint8_t VersionToExtract[2]; + uint16_t Flags; + uint16_t Method; + uint16_t ModTime; + uint16_t ModDate; + uint32_t CRC32; + uint32_t CompressedSize; + uint32_t UncompressedSize; + uint16_t NameLength; + uint16_t ExtraLength; + // file name and other variable length info follows +}; + + +#pragma pack() + +#define ZIP_LOCALFILE MAKE_ID('P','K',3,4) +#define ZIP_CENTRALFILE MAKE_ID('P','K',1,2) +#define ZIP_ENDOFDIR MAKE_ID('P','K',5,6) + +// File header flags. +#define ZF_ENCRYPTED 0x1 + +#endif