#include #include #include #include #include #include #include #include namespace steam2ng{ namespace valve_types { #pragma pack(push, 1) using u32 = uint32_t; using AppId_t = u32; using AppVersionId_t = u32; using FileId_t = u32; using ManifestNode_t = u32; struct TMstBinHeader // sizeof=0x38 { // XREF: _ZN4Grid12CManifestBinC2EP8_IO_FILEl/r // _ZN4Grid12CManifestBinC1EP8_IO_FILEl/r ... u32 u32MstVersion; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long):loc_FA270/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+187/r ... AppId_t uAppId; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+18C/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+18C/r AppVersionId_t uVerId; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+192/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+192/r u32 u32NumOfNodes; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+198/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long):loc_FA418/r ... u32 u32NumOfFiles; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+19E/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+19E/r u32 u32CompressionBlkSize; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1A4/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1A4/r u32 u32BinarySize; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long):loc_FA2E8/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1AA/r ... u32 u32StringTableSize; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1B0/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1B0/r u32 u32HashBuckets; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1B6/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1B6/r u32 u32NumMfpNodes; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1BC/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1BC/r u32 u32NumUserConfigNodes; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1C2/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1C2/r u32 u32DepotInfo; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1C8/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1C8/r u32 u32FingerPrint; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1CE/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1CE/r u32 u32Checksum; // XREF: Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1D4/r // Grid::CManifestBin::CManifestBin(_IO_FILE *,long)+1D4/r }; struct TDirNodeBin // sizeof=0x1C { // XREF: Grid::CManifestBin::TDirNode.dirNodeBin/r u32 u32NameOffset; u32 u32CountOrSize; FileId_t uFileId; u32 u32Flags; ManifestNode_t u32Parent; ManifestNode_t u32NextSibling; ManifestNode_t u32FirstChild; }; #pragma pack(pop) } struct manifest{ static inline manifest from_memory(std::span chars) { auto header = *reinterpret_cast(chars.data()); if (!(header.u32MstVersion == 4 || header.u32MstVersion == 3)) { throw std::runtime_error("manifest::from_memory: version isn't 3 or 4"); } if (header.u32BinarySize != chars.size()) { throw std::runtime_error("manifest::from_memory: manifest size is wrong"); } auto temp_chksum = header.u32Checksum; auto ptr_hdr = reinterpret_cast(chars.data()); ptr_hdr->u32Checksum = 0; ptr_hdr->u32FingerPrint = 0; auto chk = zng_adler32(0, reinterpret_cast(chars.data()), chars.size()); if (temp_chksum != chk) { throw std::runtime_error("manifest::from_memory: checksum is wrong"); } valve_types::TDirNodeBin* first = reinterpret_cast(chars.data() + sizeof(valve_types::TMstBinHeader)); std::vector bins; std::map tofull; bins.resize(header.u32NumOfNodes); memcpy(bins.data(), first, sizeof(valve_types::TDirNodeBin)*header.u32NumOfNodes); const char* string_table = reinterpret_cast(chars.data() + sizeof(valve_types::TMstBinHeader) + (sizeof(valve_types::TDirNodeBin)*header.u32NumOfNodes)); for (auto entry : bins) { std::string path; auto currnet_entry = &entry; while (currnet_entry->u32Parent != 0xffffffff) { path.insert(0, string_table + currnet_entry->u32NameOffset); if (currnet_entry->u32Parent != 0) { path.insert(0, "/"); } currnet_entry = &bins[currnet_entry->u32Parent]; } tofull[entry.uFileId] = path; } return {header,bins,tofull}; } valve_types::TMstBinHeader hdr; std::vector directory_nodes; std::map id_to_full; }; enum class compression_type : uint32_t { uncompressed = 0, compressed, compressed_and_encrypted, encrypted }; }