2022-10-12 23:39:26 +02:00
|
|
|
|
#ifndef PACKEDSTORE_H
|
|
|
|
|
#define PACKEDSTORE_H
|
|
|
|
|
/*******************************************************************
|
|
|
|
|
* ██████╗ ██╗ ██╗ ██╗██████╗ ██╗ ██╗ ██╗ ██╗██████╗ *
|
|
|
|
|
* ██╔══██╗███║ ██║ ██║██╔══██╗██║ ██╔╝ ██║ ██║██╔══██╗ *
|
|
|
|
|
* ██████╔╝╚██║ ██║ ██║██████╔╝█████╔╝ ██║ ██║██████╔╝ *
|
|
|
|
|
* ██╔══██╗ ██║ ╚██╗ ██╔╝██╔═══╝ ██╔═██╗ ██║ ██║██╔══██╗ *
|
|
|
|
|
* ██║ ██║ ██║ ╚████╔╝ ██║ ██║ ██╗ ███████╗██║██████╔╝ *
|
|
|
|
|
* ╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝╚═════╝ *
|
|
|
|
|
*******************************************************************/
|
2024-01-13 23:55:01 +01:00
|
|
|
|
#include "public/ipackedstore.h"
|
2022-11-23 12:18:33 +01:00
|
|
|
|
#include "public/ifilesystem.h"
|
2023-05-29 21:41:17 +02:00
|
|
|
|
#include "public/tier1/strtools.h"
|
|
|
|
|
#include "public/tier1/utlvector.h"
|
|
|
|
|
#include "public/tier1/utlstring.h"
|
2021-12-25 22:36:38 +01:00
|
|
|
|
#include "thirdparty/lzham/include/lzham.h"
|
|
|
|
|
|
2022-06-05 12:28:49 +02:00
|
|
|
|
constexpr unsigned int VPK_HEADER_MARKER = 0x55AA1234;
|
Proper VPK repacking
Initial proper implementation pending cleanup.
The new system builds a manifest file when a VPK is unpacked. The manifest files contains data such as the entry flags and texture flags. It also contains a field determining whether the file should be compressed or not.
When a user repacks a pack, the system attempts to load this manifest file and does a lookup to the object to retrieve the flags (most of these flags are unknown, but they are used by the engine and are necessary for stuff like cubemaps and texture files to work correctly. Cubemaps won't work with proper flags, and textures (decals, particle system components, etc..) will look washed out without them.
I think some also determine whether a file within the VPK should be cached or not, so simply marking everything as 0x101 will probably end up in more CPU time and higher filesystem cache usage (depot/ is only 0x1, I don't think anything there is getting cached ever without the 0x100 flag).
User could also repack a VPK while excluding anything that is not in the manifest file. So you could unpack all VPK's into a single directory (each VPK has its own manifest file tied to its level name), and rebuild all the VPK's with only the files that where originally in them.
fs_pack_vpk command usage: <locale> <context> <level_name> <manifest_only>
locale determines the pak language (default english), context determines whether is a server/client vpk, level_name determines the BSP name of the pak, manifest_only determines whether the pack system should only include files within the manifest (leaving this arg out will build all files into the vpk).
The VPK workspace path is determined with ConVar 'fs_packedstore_workspace'.
2022-06-04 01:08:23 +02:00
|
|
|
|
constexpr unsigned int VPK_MAJOR_VERSION = 2;
|
|
|
|
|
constexpr unsigned int VPK_MINOR_VERSION = 3;
|
2022-06-05 12:28:49 +02:00
|
|
|
|
constexpr unsigned int VPK_DICT_SIZE = 20;
|
|
|
|
|
constexpr int ENTRY_MAX_LEN = 1024 * 1024;
|
2022-11-17 20:37:12 +01:00
|
|
|
|
constexpr int PACKFILEPATCH_MAX = 512;
|
2022-11-23 12:18:33 +01:00
|
|
|
|
constexpr int PACKFILEINDEX_SEP = 0x0;
|
2022-11-16 00:54:51 +01:00
|
|
|
|
constexpr int PACKFILEINDEX_END = 0xffff;
|
2023-05-29 21:41:17 +02:00
|
|
|
|
constexpr const char VPK_IGNORE_FILE[] = ".vpkignore";
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
2023-05-29 21:41:17 +02:00
|
|
|
|
static const char* const DIR_TARGET[]
|
2022-10-02 12:17:03 +02:00
|
|
|
|
{
|
|
|
|
|
"server",
|
|
|
|
|
"client"
|
|
|
|
|
};
|
Proper VPK repacking
Initial proper implementation pending cleanup.
The new system builds a manifest file when a VPK is unpacked. The manifest files contains data such as the entry flags and texture flags. It also contains a field determining whether the file should be compressed or not.
When a user repacks a pack, the system attempts to load this manifest file and does a lookup to the object to retrieve the flags (most of these flags are unknown, but they are used by the engine and are necessary for stuff like cubemaps and texture files to work correctly. Cubemaps won't work with proper flags, and textures (decals, particle system components, etc..) will look washed out without them.
I think some also determine whether a file within the VPK should be cached or not, so simply marking everything as 0x101 will probably end up in more CPU time and higher filesystem cache usage (depot/ is only 0x1, I don't think anything there is getting cached ever without the 0x100 flag).
User could also repack a VPK while excluding anything that is not in the manifest file. So you could unpack all VPK's into a single directory (each VPK has its own manifest file tied to its level name), and rebuild all the VPK's with only the files that where originally in them.
fs_pack_vpk command usage: <locale> <context> <level_name> <manifest_only>
locale determines the pak language (default english), context determines whether is a server/client vpk, level_name determines the BSP name of the pak, manifest_only determines whether the pack system should only include files within the manifest (leaving this arg out will build all files into the vpk).
The VPK workspace path is determined with ConVar 'fs_packedstore_workspace'.
2022-06-04 01:08:23 +02:00
|
|
|
|
|
2023-07-06 00:49:17 +02:00
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// KeyValues structure for the VPK manifest file. This struct gets populated by
|
|
|
|
|
// the VPK's corresponding manifest file, which ultimately determines how each
|
|
|
|
|
// asset is getting packed into the VPK.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2022-11-23 12:18:33 +01:00
|
|
|
|
struct VPKKeyValues_t
|
Proper VPK repacking
Initial proper implementation pending cleanup.
The new system builds a manifest file when a VPK is unpacked. The manifest files contains data such as the entry flags and texture flags. It also contains a field determining whether the file should be compressed or not.
When a user repacks a pack, the system attempts to load this manifest file and does a lookup to the object to retrieve the flags (most of these flags are unknown, but they are used by the engine and are necessary for stuff like cubemaps and texture files to work correctly. Cubemaps won't work with proper flags, and textures (decals, particle system components, etc..) will look washed out without them.
I think some also determine whether a file within the VPK should be cached or not, so simply marking everything as 0x101 will probably end up in more CPU time and higher filesystem cache usage (depot/ is only 0x1, I don't think anything there is getting cached ever without the 0x100 flag).
User could also repack a VPK while excluding anything that is not in the manifest file. So you could unpack all VPK's into a single directory (each VPK has its own manifest file tied to its level name), and rebuild all the VPK's with only the files that where originally in them.
fs_pack_vpk command usage: <locale> <context> <level_name> <manifest_only>
locale determines the pak language (default english), context determines whether is a server/client vpk, level_name determines the BSP name of the pak, manifest_only determines whether the pack system should only include files within the manifest (leaving this arg out will build all files into the vpk).
The VPK workspace path is determined with ConVar 'fs_packedstore_workspace'.
2022-06-04 01:08:23 +02:00
|
|
|
|
{
|
2023-07-08 02:18:18 +02:00
|
|
|
|
static constexpr uint16_t TEXTURE_FLAGS_DEFAULT =
|
2023-07-06 00:49:17 +02:00
|
|
|
|
EPackedTextureFlags::TEXTURE_DEFAULT;
|
|
|
|
|
|
2023-07-08 02:18:18 +02:00
|
|
|
|
static constexpr uint32_t LOAD_FLAGS_DEFAULT =
|
2023-07-06 00:49:17 +02:00
|
|
|
|
EPackedLoadFlags::LOAD_VISIBLE | EPackedLoadFlags::LOAD_CACHE;
|
2022-11-23 12:18:33 +01:00
|
|
|
|
|
2023-05-29 21:41:17 +02:00
|
|
|
|
CUtlString m_EntryPath;
|
2022-11-23 12:18:33 +01:00
|
|
|
|
uint16_t m_iPreloadSize;
|
|
|
|
|
uint32_t m_nLoadFlags;
|
|
|
|
|
uint16_t m_nTextureFlags;
|
|
|
|
|
bool m_bUseCompression;
|
2023-04-03 20:08:36 +02:00
|
|
|
|
bool m_bDeduplicate;
|
2022-11-23 12:18:33 +01:00
|
|
|
|
|
2023-07-06 00:49:17 +02:00
|
|
|
|
VPKKeyValues_t(const CUtlString& svEntryPath = "",
|
|
|
|
|
uint16_t iPreloadSize = NULL,
|
|
|
|
|
uint32_t nLoadFlags = LOAD_FLAGS_DEFAULT,
|
|
|
|
|
uint16_t nTextureFlags = TEXTURE_FLAGS_DEFAULT,
|
|
|
|
|
bool bUseCompression = true, bool bDeduplicate = true);
|
Proper VPK repacking
Initial proper implementation pending cleanup.
The new system builds a manifest file when a VPK is unpacked. The manifest files contains data such as the entry flags and texture flags. It also contains a field determining whether the file should be compressed or not.
When a user repacks a pack, the system attempts to load this manifest file and does a lookup to the object to retrieve the flags (most of these flags are unknown, but they are used by the engine and are necessary for stuff like cubemaps and texture files to work correctly. Cubemaps won't work with proper flags, and textures (decals, particle system components, etc..) will look washed out without them.
I think some also determine whether a file within the VPK should be cached or not, so simply marking everything as 0x101 will probably end up in more CPU time and higher filesystem cache usage (depot/ is only 0x1, I don't think anything there is getting cached ever without the 0x100 flag).
User could also repack a VPK while excluding anything that is not in the manifest file. So you could unpack all VPK's into a single directory (each VPK has its own manifest file tied to its level name), and rebuild all the VPK's with only the files that where originally in them.
fs_pack_vpk command usage: <locale> <context> <level_name> <manifest_only>
locale determines the pak language (default english), context determines whether is a server/client vpk, level_name determines the BSP name of the pak, manifest_only determines whether the pack system should only include files within the manifest (leaving this arg out will build all files into the vpk).
The VPK workspace path is determined with ConVar 'fs_packedstore_workspace'.
2022-06-04 01:08:23 +02:00
|
|
|
|
};
|
|
|
|
|
|
2023-07-06 00:49:17 +02:00
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// An asset packed into a VPK is carved into 'ENTRY_MAX_LEN' chunks, the chunk
|
|
|
|
|
// is then optionally compressed. A chunk is NOT compressed if the compressed
|
|
|
|
|
// size equals the uncompressed size.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2022-06-06 14:54:22 +02:00
|
|
|
|
struct VPKChunkDescriptor_t
|
2021-12-25 22:36:38 +01:00
|
|
|
|
{
|
2023-07-06 00:49:17 +02:00
|
|
|
|
uint32_t m_nLoadFlags;
|
|
|
|
|
|
|
|
|
|
// Texture flags (only used if the entry is a vtf).
|
|
|
|
|
uint16_t m_nTextureFlags;
|
|
|
|
|
|
|
|
|
|
// Offset in pack file.
|
|
|
|
|
uint64_t m_nPackFileOffset;
|
|
|
|
|
uint64_t m_nCompressedSize;
|
|
|
|
|
uint64_t m_nUncompressedSize;
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
2023-05-29 21:41:17 +02:00
|
|
|
|
VPKChunkDescriptor_t()
|
|
|
|
|
: m_nLoadFlags(0)
|
|
|
|
|
, m_nTextureFlags(0)
|
|
|
|
|
, m_nPackFileOffset(0)
|
|
|
|
|
, m_nCompressedSize(0)
|
|
|
|
|
, m_nUncompressedSize(0)
|
|
|
|
|
{
|
|
|
|
|
}
|
2022-11-23 17:09:48 +01:00
|
|
|
|
VPKChunkDescriptor_t(FileHandle_t hDirectoryFile);
|
2023-07-06 00:49:17 +02:00
|
|
|
|
VPKChunkDescriptor_t(uint32_t nLoadFlags, uint16_t nTextureFlags,
|
|
|
|
|
uint64_t nPackFileOffset, uint64_t nCompressedSize, uint64_t nUncompressedSize);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
};
|
|
|
|
|
|
2023-07-06 00:49:17 +02:00
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// An asset packed into a VPK is represented as an entry block.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2022-04-09 00:59:42 +02:00
|
|
|
|
struct VPKEntryBlock_t
|
2021-12-25 22:36:38 +01:00
|
|
|
|
{
|
2023-07-06 00:49:17 +02:00
|
|
|
|
// Crc32 for the uncompressed entry.
|
|
|
|
|
uint32_t m_nFileCRC;
|
|
|
|
|
uint16_t m_iPreloadSize;
|
|
|
|
|
|
|
|
|
|
// Index of the pack file that contains this entry.
|
|
|
|
|
uint16_t m_iPackFileIndex;
|
|
|
|
|
|
|
|
|
|
// 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).
|
|
|
|
|
CUtlVector<VPKChunkDescriptor_t> m_Fragments;
|
|
|
|
|
CUtlString m_EntryPath;
|
2022-06-06 14:54:22 +02:00
|
|
|
|
|
2023-05-29 21:41:17 +02:00
|
|
|
|
VPKEntryBlock_t(FileHandle_t pFile, const char* svEntryPath);
|
2022-11-23 17:09:48 +01:00
|
|
|
|
VPKEntryBlock_t(const uint8_t* pData, size_t nLen, int64_t nOffset, uint16_t iPreloadSize,
|
2023-05-29 21:41:17 +02:00
|
|
|
|
uint16_t iPackFileIndex, uint32_t nLoadFlags, uint16_t nTextureFlags, const char* svEntryPath);
|
|
|
|
|
|
|
|
|
|
VPKEntryBlock_t(const VPKEntryBlock_t& other)
|
|
|
|
|
: m_nFileCRC(other.m_nFileCRC)
|
|
|
|
|
, m_iPreloadSize(other.m_iPreloadSize)
|
|
|
|
|
, m_iPackFileIndex(other.m_iPackFileIndex)
|
|
|
|
|
, m_EntryPath(other.m_EntryPath)
|
|
|
|
|
{
|
|
|
|
|
// Has to be explicitly copied!
|
|
|
|
|
m_Fragments = other.m_Fragments;
|
|
|
|
|
}
|
2021-12-25 22:36:38 +01:00
|
|
|
|
};
|
|
|
|
|
|
2023-07-06 00:49:17 +02:00
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// The VPK directory file header.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
Proper VPK repacking
Initial proper implementation pending cleanup.
The new system builds a manifest file when a VPK is unpacked. The manifest files contains data such as the entry flags and texture flags. It also contains a field determining whether the file should be compressed or not.
When a user repacks a pack, the system attempts to load this manifest file and does a lookup to the object to retrieve the flags (most of these flags are unknown, but they are used by the engine and are necessary for stuff like cubemaps and texture files to work correctly. Cubemaps won't work with proper flags, and textures (decals, particle system components, etc..) will look washed out without them.
I think some also determine whether a file within the VPK should be cached or not, so simply marking everything as 0x101 will probably end up in more CPU time and higher filesystem cache usage (depot/ is only 0x1, I don't think anything there is getting cached ever without the 0x100 flag).
User could also repack a VPK while excluding anything that is not in the manifest file. So you could unpack all VPK's into a single directory (each VPK has its own manifest file tied to its level name), and rebuild all the VPK's with only the files that where originally in them.
fs_pack_vpk command usage: <locale> <context> <level_name> <manifest_only>
locale determines the pak language (default english), context determines whether is a server/client vpk, level_name determines the BSP name of the pak, manifest_only determines whether the pack system should only include files within the manifest (leaving this arg out will build all files into the vpk).
The VPK workspace path is determined with ConVar 'fs_packedstore_workspace'.
2022-06-04 01:08:23 +02:00
|
|
|
|
struct VPKDirHeader_t
|
2021-12-25 22:36:38 +01:00
|
|
|
|
{
|
2023-07-06 00:49:17 +02:00
|
|
|
|
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.
|
2022-11-23 17:09:48 +01:00
|
|
|
|
};
|
|
|
|
|
|
2023-07-06 00:49:17 +02:00
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// The VPK directory tree structure.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2022-05-30 02:56:15 +02:00
|
|
|
|
struct VPKDir_t
|
|
|
|
|
{
|
2023-07-06 00:49:17 +02:00
|
|
|
|
VPKDirHeader_t m_Header;
|
|
|
|
|
CUtlString m_DirFilePath;
|
2023-07-08 02:18:18 +02:00
|
|
|
|
CUtlVector<VPKEntryBlock_t> m_EntryBlocks;
|
2023-07-06 00:49:17 +02:00
|
|
|
|
|
|
|
|
|
// This set only contains packfile indices used
|
|
|
|
|
// by the directory tree, notated as pak000_xxx.
|
|
|
|
|
std::set<uint16_t> m_PakFileIndices;
|
2024-01-14 00:43:15 +01:00
|
|
|
|
bool m_bInitFailed;
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
2023-07-05 23:04:07 +02:00
|
|
|
|
class CTreeBuilder
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
typedef std::map<std::string, std::list<VPKEntryBlock_t>> PathContainer_t;
|
|
|
|
|
typedef std::map<std::string, PathContainer_t> TypeContainer_t;
|
|
|
|
|
|
|
|
|
|
void BuildTree(const CUtlVector<VPKEntryBlock_t>& entryBlocks);
|
2023-07-15 16:25:35 +02:00
|
|
|
|
int WriteTree(FileHandle_t hDirectoryFile) const;
|
2023-07-05 23:04:07 +02:00
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
TypeContainer_t m_FileTree;
|
|
|
|
|
};
|
|
|
|
|
|
2022-11-23 17:09:48 +01:00
|
|
|
|
VPKDir_t()
|
|
|
|
|
{
|
2023-07-05 23:04:07 +02:00
|
|
|
|
m_Header.m_nHeaderMarker = VPK_HEADER_MARKER; m_Header.m_nMajorVersion = VPK_MAJOR_VERSION;
|
2023-05-29 21:41:17 +02:00
|
|
|
|
m_Header.m_nMinorVersion = VPK_MINOR_VERSION; m_Header.m_nDirectorySize = NULL, m_Header.m_nSignatureSize = NULL;
|
2024-01-14 00:43:15 +01:00
|
|
|
|
m_bInitFailed = false;
|
2022-11-23 17:09:48 +01:00
|
|
|
|
};
|
2023-05-29 21:41:17 +02:00
|
|
|
|
VPKDir_t(const CUtlString& svDirectoryFile);
|
|
|
|
|
VPKDir_t(const CUtlString& svDirectoryFile, bool bSanitizeName);
|
2022-05-30 02:56:15 +02:00
|
|
|
|
|
2023-05-29 21:41:17 +02:00
|
|
|
|
void Init(const CUtlString& svPath);
|
2024-01-14 00:43:15 +01:00
|
|
|
|
inline bool Failed() const { return m_bInitFailed; }
|
2022-11-23 17:09:48 +01:00
|
|
|
|
|
2023-05-29 21:41:17 +02:00
|
|
|
|
CUtlString StripLocalePrefix(const CUtlString& svDirectoryFile) const;
|
2023-07-06 00:49:17 +02:00
|
|
|
|
CUtlString GetPackFileNameForIndex(uint16_t iPackFileIndex) const;
|
2022-11-23 17:09:48 +01:00
|
|
|
|
|
|
|
|
|
void WriteHeader(FileHandle_t hDirectoryFile) const;
|
|
|
|
|
void WriteTreeSize(FileHandle_t hDirectoryFile) const;
|
2022-11-23 12:27:57 +01:00
|
|
|
|
|
2023-07-04 22:08:44 +02:00
|
|
|
|
void BuildDirectoryFile(const CUtlString& svDirectoryFile, const CUtlVector<VPKEntryBlock_t>& entryBlocks);
|
Proper VPK repacking
Initial proper implementation pending cleanup.
The new system builds a manifest file when a VPK is unpacked. The manifest files contains data such as the entry flags and texture flags. It also contains a field determining whether the file should be compressed or not.
When a user repacks a pack, the system attempts to load this manifest file and does a lookup to the object to retrieve the flags (most of these flags are unknown, but they are used by the engine and are necessary for stuff like cubemaps and texture files to work correctly. Cubemaps won't work with proper flags, and textures (decals, particle system components, etc..) will look washed out without them.
I think some also determine whether a file within the VPK should be cached or not, so simply marking everything as 0x101 will probably end up in more CPU time and higher filesystem cache usage (depot/ is only 0x1, I don't think anything there is getting cached ever without the 0x100 flag).
User could also repack a VPK while excluding anything that is not in the manifest file. So you could unpack all VPK's into a single directory (each VPK has its own manifest file tied to its level name), and rebuild all the VPK's with only the files that where originally in them.
fs_pack_vpk command usage: <locale> <context> <level_name> <manifest_only>
locale determines the pak language (default english), context determines whether is a server/client vpk, level_name determines the BSP name of the pak, manifest_only determines whether the pack system should only include files within the manifest (leaving this arg out will build all files into the vpk).
The VPK workspace path is determined with ConVar 'fs_packedstore_workspace'.
2022-06-04 01:08:23 +02:00
|
|
|
|
};
|
|
|
|
|
|
2023-07-06 00:49:17 +02:00
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Contains the VPK directory name, and the pack file name. Used for building
|
|
|
|
|
// the VPK file.
|
|
|
|
|
// !TODO[ AMOS ]: Remove this when patching is implemented!
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
struct VPKPair_t
|
|
|
|
|
{
|
|
|
|
|
CUtlString m_PackName;
|
|
|
|
|
CUtlString m_DirName;
|
|
|
|
|
|
|
|
|
|
VPKPair_t(const char* svLocale, const char* svTarget, const char* svLevel, int nPatch);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// VPK utility class.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2024-01-12 11:02:54 +01:00
|
|
|
|
class CPackedStoreBuilder
|
2021-12-25 22:36:38 +01:00
|
|
|
|
{
|
|
|
|
|
public:
|
2024-01-13 14:02:46 +01:00
|
|
|
|
void InitLzEncoder(const lzham_int32 maxHelperThreads = -1, const char* compressionLevel = "default");
|
|
|
|
|
void InitLzDecoder(void);
|
Proper VPK repacking
Initial proper implementation pending cleanup.
The new system builds a manifest file when a VPK is unpacked. The manifest files contains data such as the entry flags and texture flags. It also contains a field determining whether the file should be compressed or not.
When a user repacks a pack, the system attempts to load this manifest file and does a lookup to the object to retrieve the flags (most of these flags are unknown, but they are used by the engine and are necessary for stuff like cubemaps and texture files to work correctly. Cubemaps won't work with proper flags, and textures (decals, particle system components, etc..) will look washed out without them.
I think some also determine whether a file within the VPK should be cached or not, so simply marking everything as 0x101 will probably end up in more CPU time and higher filesystem cache usage (depot/ is only 0x1, I don't think anything there is getting cached ever without the 0x100 flag).
User could also repack a VPK while excluding anything that is not in the manifest file. So you could unpack all VPK's into a single directory (each VPK has its own manifest file tied to its level name), and rebuild all the VPK's with only the files that where originally in them.
fs_pack_vpk command usage: <locale> <context> <level_name> <manifest_only>
locale determines the pak language (default english), context determines whether is a server/client vpk, level_name determines the BSP name of the pak, manifest_only determines whether the pack system should only include files within the manifest (leaving this arg out will build all files into the vpk).
The VPK workspace path is determined with ConVar 'fs_packedstore_workspace'.
2022-06-04 01:08:23 +02:00
|
|
|
|
|
2023-04-03 22:46:10 +02:00
|
|
|
|
bool Deduplicate(const uint8_t* pEntryBuffer, VPKChunkDescriptor_t& descriptor, const size_t chunkIndex);
|
|
|
|
|
|
2024-01-13 14:09:37 +01:00
|
|
|
|
void PackStore(const VPKPair_t& vpkPair, const char* workspaceName, const char* buildPath);
|
|
|
|
|
void UnpackStore(const VPKDir_t& vpkDir, const char* workspaceName = "");
|
2022-06-06 14:54:22 +02:00
|
|
|
|
|
|
|
|
|
private:
|
2024-01-13 14:02:46 +01:00
|
|
|
|
lzham_compress_params m_Encoder; // LZham compression parameters.
|
|
|
|
|
lzham_decompress_params m_Decoder; // LZham decompression parameters.
|
2023-05-29 21:41:17 +02:00
|
|
|
|
std::unordered_map<string, const VPKChunkDescriptor_t&> m_ChunkHashMap;
|
2021-12-25 22:36:38 +01:00
|
|
|
|
};
|
2024-01-14 01:39:11 +01:00
|
|
|
|
|
|
|
|
|
CUtlString PackedStore_GetDirLevelName(const CUtlString& dirFileName);
|
|
|
|
|
CUtlString PackedStore_GetDirNameParts(const CUtlString& dirFileName, const int nCaptureGroup);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-10-12 23:39:26 +02:00
|
|
|
|
|
2023-07-06 00:49:17 +02:00
|
|
|
|
#endif // PACKEDSTORE_H
|