mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
No modifications to the existing logic have been performed. Some parameter names have been renamed to improve code readability and maintainability.
197 lines
7.8 KiB
C++
197 lines
7.8 KiB
C++
#ifndef PACKEDSTORE_H
|
|
#define PACKEDSTORE_H
|
|
/*******************************************************************
|
|
* ██████╗ ██╗ ██╗ ██╗██████╗ ██╗ ██╗ ██╗ ██╗██████╗ *
|
|
* ██╔══██╗███║ ██║ ██║██╔══██╗██║ ██╔╝ ██║ ██║██╔══██╗ *
|
|
* ██████╔╝╚██║ ██║ ██║██████╔╝█████╔╝ ██║ ██║██████╔╝ *
|
|
* ██╔══██╗ ██║ ╚██╗ ██╔╝██╔═══╝ ██╔═██╗ ██║ ██║██╔══██╗ *
|
|
* ██║ ██║ ██║ ╚████╔╝ ██║ ██║ ██╗ ███████╗██║██████╔╝ *
|
|
* ╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝╚═════╝ *
|
|
*******************************************************************/
|
|
#include "public/utility/binstream.h"
|
|
#include "thirdparty/lzham/include/lzham.h"
|
|
|
|
constexpr unsigned int VPK_HEADER_MARKER = 0x55AA1234;
|
|
constexpr unsigned int VPK_MAJOR_VERSION = 2;
|
|
constexpr unsigned int VPK_MINOR_VERSION = 3;
|
|
constexpr unsigned int VPK_DICT_SIZE = 20;
|
|
constexpr int ENTRY_MAX_LEN = 1024 * 1024;
|
|
constexpr int PACKFILEINDEX_END = 0xffff;
|
|
|
|
static const std::regex BLOCK_REGEX{ R"(pak000_([0-9]{3}))" };
|
|
static const std::regex DIR_REGEX{ R"((?:.*\/)?([^_]*_)(.*)(.bsp.pak000_dir).*)" };
|
|
|
|
static const vector<string> DIR_TARGET =
|
|
{
|
|
"server",
|
|
"client"
|
|
};
|
|
static const vector<string> DIR_LOCALE =
|
|
{
|
|
"english",
|
|
"french",
|
|
"german",
|
|
"italian",
|
|
"japanese",
|
|
"korean",
|
|
"polish",
|
|
"portuguese",
|
|
"russian",
|
|
"spanish",
|
|
"tchinese"
|
|
};
|
|
|
|
enum class EPackedLoadFlags : int
|
|
{
|
|
LOAD_NONE,
|
|
LOAD_VISIBLE = 1 << 0, // Visible to FileSystem.
|
|
LOAD_CACHE = 1 << 8, // Only set for assets not stored in the depot directory.
|
|
LOAD_TEXTURE_UNK0 = 1 << 18,
|
|
LOAD_TEXTURE_UNK1 = 1 << 19,
|
|
LOAD_TEXTURE_UNK2 = 1 << 20,
|
|
};
|
|
|
|
enum class EPackedTextureFlags : short
|
|
{
|
|
TEXTURE_NONE,
|
|
TEXTURE_DEFAULT = 1 << 3,
|
|
TEXTURE_ENVIRONMENT_MAP = 1 << 10,
|
|
};
|
|
|
|
struct FileHandleTracker_t
|
|
{
|
|
int m_nFileNumber;
|
|
int m_nCurOfs;
|
|
HANDLE m_hFileHandle;
|
|
};
|
|
|
|
struct pFileHandleTracker_t
|
|
{
|
|
FileHandleTracker_t self[1024];
|
|
};
|
|
|
|
#pragma pack(push, 1)
|
|
struct VPKFileEntry_t
|
|
{
|
|
char* m_pszDirectory;
|
|
char* m_pszFileName;
|
|
char* m_pszExtension;
|
|
uint8_t unknown[0x38];
|
|
};
|
|
|
|
struct VPKData_t
|
|
{
|
|
int m_nHandle;
|
|
char pad[1];
|
|
char m_szPath[255];
|
|
uint8_t unknown2[0x134];
|
|
int32_t m_nEntries;
|
|
uint8_t unknown3[12];
|
|
VPKFileEntry_t* m_pEntries;
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
struct VPKChunkDescriptor_t
|
|
{
|
|
uint32_t m_nLoadFlags; // Load flags.
|
|
uint16_t m_nTextureFlags; // Texture flags (only used if the entry is a vtf).
|
|
uint64_t m_nPackFileOffset; // Offset in pack file.
|
|
uint64_t m_nCompressedSize; // Compressed size of chunk.
|
|
uint64_t m_nUncompressedSize; // Uncompressed size of chunk.
|
|
bool m_bIsCompressed = false;
|
|
|
|
VPKChunkDescriptor_t(){};
|
|
VPKChunkDescriptor_t(CIOStream* pReader);
|
|
VPKChunkDescriptor_t(uint32_t nEntryFlags, uint16_t nTextureFlags, uint64_t nPackFileOffset, uint64_t nCompressedSize, uint64_t nUncompressedSize);
|
|
};
|
|
|
|
struct VPKEntryBlock_t
|
|
{
|
|
uint32_t m_nFileCRC; // Crc32 for the uncompressed entry.
|
|
uint16_t m_iPreloadSize; // Preload bytes.
|
|
uint16_t m_iPackFileIndex; // Index of the pack file that contains this entry.
|
|
vector<VPKChunkDescriptor_t> m_vFragments; // Vector of all the chunks of a given entry (chunks have a size limit of 1 MiB, anything over this limit is fragmented into smaller chunks).
|
|
string m_svEntryPath; // Path to entry within vpk.
|
|
|
|
VPKEntryBlock_t(CIOStream* pReader, string svEntryPath);
|
|
VPKEntryBlock_t(const vector<uint8_t>& vData, int64_t nOffset, uint16_t iPreloadSize, uint16_t iPackFileIndex, uint32_t nEntryFlags, uint16_t nTextureFlags, const string& svEntryPath);
|
|
};
|
|
|
|
struct VPKDirHeader_t
|
|
{
|
|
uint32_t m_nHeaderMarker; // File magic.
|
|
uint16_t m_nMajorVersion; // Vpk major version.
|
|
uint16_t m_nMinorVersion; // Vpk minor version.
|
|
uint32_t m_nDirectorySize; // Directory tree size.
|
|
uint32_t m_nSignatureSize; // Directory signature.
|
|
};
|
|
|
|
struct VPKDir_t
|
|
{
|
|
VPKDirHeader_t m_vHeader; // Dir header.
|
|
uint32_t m_nFileDataSize; // File data section size.
|
|
vector<VPKEntryBlock_t> m_vEntryBlocks; // Vector of entry blocks.
|
|
uint16_t m_nPackFileCount; // Number of pack patches (pack file count-1).
|
|
vector<string> m_vPackFile; // Vector of pack file names.
|
|
string m_svDirPath; // Path to vpk_dir file.
|
|
|
|
VPKDir_t(const string& svPath);
|
|
VPKDir_t() { m_vHeader.m_nHeaderMarker = VPK_HEADER_MARKER; m_vHeader.m_nMajorVersion = VPK_MAJOR_VERSION; m_vHeader.m_nMinorVersion = VPK_MINOR_VERSION; };
|
|
|
|
void Build(const string& svDirectoryFile, const vector<VPKEntryBlock_t>& vEntryBlocks);
|
|
};
|
|
|
|
struct VPKPair_t
|
|
{
|
|
string m_svBlockName;
|
|
string m_svDirectoryName;
|
|
};
|
|
|
|
class CPackedStore
|
|
{
|
|
public:
|
|
void InitLzCompParams(void);
|
|
void InitLzDecompParams(void);
|
|
|
|
VPKDir_t GetDirectoryFile(const string& svDirectoryFile, bool bSanitizeName) const;
|
|
string GetPackFile(const string& svPackDirFile, uint16_t iPackFileIndex) const;
|
|
lzham_compress_level GetCompressionLevel(void) const;
|
|
|
|
vector<VPKEntryBlock_t> GetEntryBlocks(CIOStream* pReader) const;
|
|
vector<string> GetEntryPaths(const string& svPathIn) const;
|
|
vector<string> GetEntryPaths(const string& svPathIn, const nlohmann::json& jManifest) const;
|
|
|
|
string GetNameParts(const string& svDirectoryName, int nCaptureGroup) const;
|
|
string GetLevelName(const string& svDirectoryName) const;
|
|
|
|
nlohmann::json GetManifest(const string& svWorkspace, const string& svManifestName) const;
|
|
vector<string> GetIgnoreList(const string& svWorkspace) const;
|
|
|
|
string FormatEntryPath(string svName, const string& svPath, const string& svExtension) const;
|
|
string StripLocalePrefix(const string& svDirectoryFile) const;
|
|
|
|
VPKPair_t BuildFileName(string svLanguage, string svTarget, const string& svLevel, int nPatch) const;
|
|
void BuildManifest(const vector<VPKEntryBlock_t>& vBlock, const string& svWorkSpace, const string& svManifestName) const;
|
|
|
|
void PackWorkspace(const VPKPair_t& vPair, const string& svWorkspace, const string& svBuildPath, bool bManifestOnly);
|
|
void UnpackWorkspace(const VPKDir_t& vDir, const string& svPathOut = "");
|
|
|
|
void ValidateAdler32PostDecomp(const string& svDirAsset);
|
|
void ValidateCRC32PostDecomp(const string& svDirAsset);
|
|
|
|
private:
|
|
size_t m_nChunkCount; // The number of patches (multi-pack file).
|
|
lzham_uint32 m_nAdler32_Internal; // Internal operation Adler32 file checksum.
|
|
lzham_uint32 m_nAdler32; // Pre/post operation Adler32 file checksum.
|
|
lzham_uint32 m_nCrc32_Internal; // Internal operation Crc32 file checksum.
|
|
lzham_uint32 m_nCrc32; // Pre/post operation Crc32 file checksum.
|
|
lzham_compress_params m_lzCompParams; // LZham decompression parameters.
|
|
lzham_compress_status_t m_lzCompStatus; // LZham compression status.
|
|
lzham_decompress_params m_lzDecompParams; // LZham decompression parameters.
|
|
lzham_decompress_status_t m_lzDecompStatus; // LZham decompression status.
|
|
std::unordered_map<string, VPKChunkDescriptor_t&> m_mChunkHashMap;
|
|
};
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
extern CPackedStore* g_pPackedStore;
|
|
|
|
#endif // PACKEDSTORE_H
|