- removed the ZDoom CVAR code because it won't be needed and added its Zip file reader to maintain an engine file with needed assets.

The Build code for this is far too messy for this task, so an external solution is needed.
This commit is contained in:
Christoph Oelckers 2019-10-04 00:52:19 +02:00
parent ebbe1803bb
commit c5c92c1410
8 changed files with 1004 additions and 2121 deletions

View file

@ -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 <stdarg.h>
//#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

File diff suppressed because it is too large Load diff

View file

@ -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<FBaseCVar *> &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<FBaseCVar *> &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<char *>(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__

View file

@ -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 <time.h>
#include <algorithm>
#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<uint32_t>(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<uint32_t>((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<char*>(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;
}

View file

@ -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

View file

@ -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 <zlib.h>
#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<char*>(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)
{}

View file

@ -0,0 +1,136 @@
#ifndef __RESFILE_H
#define __RESFILE_H
#include <stdint.h>
#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<FUncompressedLump> Lumps;
FUncompressedFile(const char *filename);
FUncompressedFile(const char *filename, FileReader &r);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
#endif

View file

@ -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