2019-10-03 22:52:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifndef __RESFILE_H
|
|
|
|
#define __RESFILE_H
|
|
|
|
|
2020-05-25 21:59:07 +00:00
|
|
|
#include <limits.h>
|
2023-08-19 14:57:37 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
2023-08-23 18:36:19 +00:00
|
|
|
#include "fs_files.h"
|
2020-04-11 21:54:33 +00:00
|
|
|
|
2023-08-23 18:36:19 +00:00
|
|
|
namespace FileSys {
|
|
|
|
|
|
|
|
class StringPool;
|
2023-08-19 14:57:37 +00:00
|
|
|
std::string ExtractBaseName(const char* path, bool include_extension = false);
|
|
|
|
void strReplace(std::string& str, const char* from, const char* to);
|
|
|
|
|
|
|
|
// user context in which the file system gets opened. This also contains a few callbacks to avoid direct dependencies on the engine.
|
2020-04-11 21:54:33 +00:00
|
|
|
struct LumpFilterInfo
|
|
|
|
{
|
2023-08-19 14:57:37 +00:00
|
|
|
std::vector<std::string> gameTypeFilter; // this can contain multiple entries
|
|
|
|
std::string dotFilter;
|
2020-04-11 21:54:33 +00:00
|
|
|
|
|
|
|
// The following are for checking if the root directory of a zip can be removed.
|
2023-08-19 14:57:37 +00:00
|
|
|
std::vector<std::string> reservedFolders;
|
|
|
|
std::vector<std::string> requiredPrefixes;
|
|
|
|
std::vector<std::string> embeddings;
|
|
|
|
std::vector<std::string> blockednames; // File names that will never be accepted (e.g. dehacked.exe for Doom)
|
|
|
|
std::function<bool(const char*, const char*)> filenamecheck; // for scanning directories, this allows to eliminate unwanted content.
|
2020-04-11 21:54:33 +00:00
|
|
|
std::function<void()> postprocessFunc;
|
|
|
|
};
|
2019-10-03 22:52:19 +00:00
|
|
|
|
2023-08-19 14:57:37 +00:00
|
|
|
enum class FSMessageLevel
|
|
|
|
{
|
|
|
|
Error = 1,
|
|
|
|
Warning = 2,
|
|
|
|
Attention = 3,
|
|
|
|
Message = 4,
|
|
|
|
DebugWarn = 5,
|
|
|
|
DebugNotify = 6,
|
|
|
|
};
|
|
|
|
|
|
|
|
// pass the text output function as parameter to avoid a hard dependency on higher level code.
|
|
|
|
using FileSystemMessageFunc = int(*)(FSMessageLevel msglevel, const char* format, ...);
|
|
|
|
|
|
|
|
|
2019-10-03 22:52:19 +00:00
|
|
|
class FResourceFile;
|
|
|
|
|
2020-04-11 21:54:33 +00:00
|
|
|
// [RH] Namespaces from BOOM.
|
|
|
|
// These are needed here in the low level part so that WAD files can be properly set up.
|
2020-04-11 21:52:02 +00:00
|
|
|
typedef enum {
|
|
|
|
ns_hidden = -1,
|
|
|
|
|
|
|
|
ns_global = 0,
|
|
|
|
ns_sprites,
|
|
|
|
ns_flats,
|
|
|
|
ns_colormaps,
|
|
|
|
ns_acslibrary,
|
|
|
|
ns_newtextures,
|
2020-04-11 21:54:33 +00:00
|
|
|
ns_bloodraw, // no longer used - kept for ZScript.
|
|
|
|
ns_bloodsfx, // no longer used - kept for ZScript.
|
|
|
|
ns_bloodmisc, // no longer used - kept for ZScript.
|
2020-04-11 21:52:02 +00:00
|
|
|
ns_strifevoices,
|
|
|
|
ns_hires,
|
|
|
|
ns_voxels,
|
|
|
|
|
|
|
|
// These namespaces are only used to mark lumps in special subdirectories
|
|
|
|
// so that their contents doesn't interfere with the global namespace.
|
|
|
|
// searching for data in these namespaces works differently for lumps coming
|
|
|
|
// from Zips or other files.
|
|
|
|
ns_specialzipdirectory,
|
|
|
|
ns_sounds,
|
|
|
|
ns_patches,
|
|
|
|
ns_graphics,
|
|
|
|
ns_music,
|
|
|
|
|
|
|
|
ns_firstskin,
|
|
|
|
} namespace_t;
|
|
|
|
|
2019-10-03 22:52:19 +00:00
|
|
|
enum ELumpFlags
|
|
|
|
{
|
2020-04-11 21:54:33 +00:00
|
|
|
LUMPF_MAYBEFLAT = 1, // might be a flat outside F_START/END
|
|
|
|
LUMPF_FULLPATH = 2, // contains a full path. This will trigger extended namespace checks when looking up short names.
|
|
|
|
LUMPF_EMBEDDED = 4, // marks an embedded resource file for later processing.
|
|
|
|
LUMPF_SHORTNAME = 8, // the stored name is a short extension-less name
|
|
|
|
LUMPF_COMPRESSED = 16, // compressed or encrypted, i.e. cannot be read with the container file's reader.
|
2020-04-11 21:52:02 +00:00
|
|
|
};
|
2019-10-03 22:52:19 +00:00
|
|
|
|
2020-04-11 21:54:33 +00:00
|
|
|
// This holds a compresed Zip entry with all needed info to decompress it.
|
2019-10-03 22:52:19 +00:00
|
|
|
struct FCompressedBuffer
|
|
|
|
{
|
2023-12-10 12:30:50 +00:00
|
|
|
size_t mSize;
|
|
|
|
size_t mCompressedSize;
|
2019-10-03 22:52:19 +00:00
|
|
|
int mMethod;
|
|
|
|
int mZipFlags;
|
|
|
|
unsigned mCRC32;
|
|
|
|
char *mBuffer;
|
2023-08-19 14:57:37 +00:00
|
|
|
const char* filename;
|
2019-10-03 22:52:19 +00:00
|
|
|
|
|
|
|
bool Decompress(char *destbuffer);
|
|
|
|
void Clean()
|
|
|
|
{
|
|
|
|
mSize = mCompressedSize = 0;
|
|
|
|
if (mBuffer != nullptr)
|
|
|
|
{
|
|
|
|
delete[] mBuffer;
|
|
|
|
mBuffer = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct FResourceLump
|
|
|
|
{
|
2023-12-10 12:30:50 +00:00
|
|
|
protected:
|
2019-10-03 22:52:19 +00:00
|
|
|
friend class FResourceFile;
|
2020-04-11 21:54:33 +00:00
|
|
|
friend class FWadFile; // this still needs direct access.
|
2023-12-10 12:30:50 +00:00
|
|
|
friend class FileData;
|
|
|
|
friend class FileSystem;
|
|
|
|
friend class FLumpFile;
|
|
|
|
friend class FLumpReader;
|
|
|
|
friend class FGrpFile;
|
|
|
|
friend class F7ZFile;
|
|
|
|
friend class FSSIFile;
|
|
|
|
friend class FWHResFile;
|
|
|
|
friend class FZipFile;
|
|
|
|
friend class FPakFile;
|
|
|
|
friend class FRFFFile;
|
|
|
|
friend class FDirectory;
|
|
|
|
friend int lumpcmp(const void* a, const void* b);
|
|
|
|
|
2019-10-03 22:52:19 +00:00
|
|
|
|
2020-04-11 21:54:33 +00:00
|
|
|
int LumpSize;
|
|
|
|
int RefCount;
|
2023-12-10 12:30:50 +00:00
|
|
|
//protected:
|
2023-08-23 18:36:19 +00:00
|
|
|
const char* FullName;
|
2023-12-10 12:30:50 +00:00
|
|
|
//public:
|
2020-04-11 21:54:33 +00:00
|
|
|
uint8_t Flags;
|
|
|
|
char * Cache;
|
|
|
|
FResourceFile * Owner;
|
2019-10-03 22:52:19 +00:00
|
|
|
|
2023-12-10 12:30:50 +00:00
|
|
|
public:
|
2020-04-11 21:54:33 +00:00
|
|
|
FResourceLump()
|
|
|
|
{
|
|
|
|
Cache = NULL;
|
|
|
|
Owner = NULL;
|
|
|
|
Flags = 0;
|
|
|
|
RefCount = 0;
|
2023-08-23 18:36:19 +00:00
|
|
|
FullName = "";
|
2023-12-10 12:30:50 +00:00
|
|
|
LumpSize = 0;
|
2020-04-11 21:54:33 +00:00
|
|
|
}
|
2019-10-03 22:52:19 +00:00
|
|
|
virtual ~FResourceLump();
|
2023-12-10 12:30:50 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
|
2019-10-28 22:46:15 +00:00
|
|
|
virtual FileReader *GetReader();
|
2019-10-03 22:52:19 +00:00
|
|
|
virtual FileReader NewReader();
|
|
|
|
virtual int GetFileOffset() { return -1; }
|
2020-04-11 21:54:33 +00:00
|
|
|
virtual int GetIndexNum() const { return -1; }
|
|
|
|
virtual int GetNamespace() const { return 0; }
|
2023-08-23 18:36:19 +00:00
|
|
|
void LumpNameSetup(const char* iname, StringPool* allocator);
|
2021-04-11 22:20:45 +00:00
|
|
|
void CheckEmbedded(LumpFilterInfo* lfi);
|
2019-10-28 22:46:15 +00:00
|
|
|
virtual FCompressedBuffer GetRawData();
|
2019-10-03 22:52:19 +00:00
|
|
|
|
2020-04-11 21:54:33 +00:00
|
|
|
void *Lock(); // validates the cache and increases the refcount.
|
|
|
|
int Unlock(); // decreases the refcount and frees the buffer
|
|
|
|
|
2019-10-30 23:50:45 +00:00
|
|
|
unsigned Size() const{ return LumpSize; }
|
|
|
|
int LockCount() const { return RefCount; }
|
2023-08-23 18:36:19 +00:00
|
|
|
const char* getName() { return FullName; }
|
|
|
|
void clearName() { FullName = ""; }
|
2019-10-03 22:52:19 +00:00
|
|
|
|
|
|
|
protected:
|
2020-04-11 21:54:33 +00:00
|
|
|
virtual int FillCache() { return -1; }
|
2019-10-03 22:52:19 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class FResourceFile
|
|
|
|
{
|
|
|
|
public:
|
2023-12-10 12:30:50 +00:00
|
|
|
protected:
|
2019-10-03 22:52:19 +00:00
|
|
|
FileReader Reader;
|
2023-08-23 18:36:19 +00:00
|
|
|
const char* FileName;
|
2019-10-03 22:52:19 +00:00
|
|
|
uint32_t NumLumps;
|
2023-08-19 14:57:37 +00:00
|
|
|
char Hash[48];
|
2023-08-23 18:36:19 +00:00
|
|
|
StringPool* stringpool;
|
2019-10-03 22:52:19 +00:00
|
|
|
|
2023-08-23 18:36:19 +00:00
|
|
|
FResourceFile(const char *filename, StringPool* sp);
|
|
|
|
FResourceFile(const char *filename, FileReader &r, StringPool* sp);
|
2019-10-03 22:52:19 +00:00
|
|
|
|
2019-10-28 22:46:15 +00:00
|
|
|
// for archives that can contain directories
|
2020-04-11 21:54:33 +00:00
|
|
|
void GenerateHash();
|
|
|
|
void PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterInfo *filter);
|
2019-10-28 22:46:15 +00:00
|
|
|
|
2019-10-03 22:52:19 +00:00
|
|
|
private:
|
|
|
|
uint32_t FirstLump;
|
|
|
|
|
2023-08-19 14:57:37 +00:00
|
|
|
int FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max);
|
2020-04-11 21:54:33 +00:00
|
|
|
int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max);
|
2023-08-19 14:57:37 +00:00
|
|
|
bool FindPrefixRange(const char* filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end);
|
2019-10-28 22:46:15 +00:00
|
|
|
void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max);
|
2023-08-23 18:36:19 +00:00
|
|
|
static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
|
2019-10-28 22:46:15 +00:00
|
|
|
|
2019-10-03 22:52:19 +00:00
|
|
|
public:
|
2023-08-23 18:36:19 +00:00
|
|
|
static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
|
|
|
|
static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
|
|
|
|
static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
|
2019-10-03 22:52:19 +00:00
|
|
|
virtual ~FResourceFile();
|
|
|
|
// If this FResourceFile represents a directory, the Reader object is not usable so don't return it.
|
2023-12-10 12:30:50 +00:00
|
|
|
FileReader *GetContainerReader() { return Reader.isOpen()? &Reader : nullptr; }
|
|
|
|
const char* GetFileName() const { return FileName; }
|
2020-04-11 21:54:33 +00:00
|
|
|
uint32_t GetFirstEntry() const { return FirstLump; }
|
2019-10-03 22:52:19 +00:00
|
|
|
void SetFirstLump(uint32_t f) { FirstLump = f; }
|
2023-08-19 14:57:37 +00:00
|
|
|
const char* GetHash() const { return Hash; }
|
2019-10-28 22:46:15 +00:00
|
|
|
|
2019-10-03 22:52:19 +00:00
|
|
|
virtual FResourceLump *GetLump(int no) = 0;
|
2023-12-10 12:30:50 +00:00
|
|
|
|
|
|
|
int EntryCount() const { return NumLumps; }
|
|
|
|
int FindEntry(const char* name);
|
|
|
|
|
|
|
|
size_t Length(int entry)
|
|
|
|
{
|
|
|
|
auto l = GetLump(entry);
|
|
|
|
return l ? l->LumpSize : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileReader GetEntryReader(int entry, bool newreader = true)
|
|
|
|
{
|
|
|
|
auto l = GetLump(entry);
|
|
|
|
return l ? l->NewReader() : FileReader();
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetEntryFlags(int entry)
|
|
|
|
{
|
|
|
|
auto l = GetLump(entry);
|
|
|
|
return l ? l->Flags : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ResourceData Read(int entry)
|
|
|
|
{
|
|
|
|
auto fr = GetEntryReader(entry, false);
|
|
|
|
return fr.Read();
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* getName(int entry)
|
|
|
|
{
|
|
|
|
auto l = GetLump(entry);
|
|
|
|
return l ? l->FullName : nullptr;
|
|
|
|
}
|
|
|
|
FCompressedBuffer GetRawData(int entry)
|
|
|
|
{
|
|
|
|
auto l = GetLump(entry);
|
|
|
|
if (!l) return {};
|
|
|
|
return l->GetRawData();
|
|
|
|
}
|
|
|
|
|
|
|
|
FileReader Destroy()
|
|
|
|
{
|
|
|
|
auto fr = std::move(Reader);
|
|
|
|
delete this;
|
|
|
|
return fr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-03 22:52:19 +00:00
|
|
|
};
|
|
|
|
|
2019-10-28 22:46:15 +00:00
|
|
|
|
2023-08-23 18:36:19 +00:00
|
|
|
}
|
2019-10-28 22:46:15 +00:00
|
|
|
|
2019-10-03 22:52:19 +00:00
|
|
|
#endif
|