Skip to content

Commit 7c2f56c

Browse files
committed
fix. issue#1
1 parent 81f333e commit 7c2f56c

File tree

2 files changed

+118
-61
lines changed

2 files changed

+118
-61
lines changed

src/ABProcessor.cs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,8 @@ public string CreateAssetBundle(string bundleName, List<string> files)
426426
blocksInfoBytes = ms.ToArray();
427427
}
428428

429-
// 压缩块信息
430-
byte[] compressedBlocksInfo = CompressData(blocksInfoBytes, UnityCompressionType.LZ4);
429+
// 压缩块信息,并添加自定义头部
430+
byte[] compressedBlocksInfo = CompressBlocksInfoLZ4WithHeader(blocksInfoBytes);
431431

432432
// 压缩主数据
433433
byte[] compressedData = CompressData(bundleData, _unityCompressionType);
@@ -962,15 +962,15 @@ private byte[] DecryptData(byte[] data)
962962
aes.Mode = CipherMode.CBC;
963963
aes.Padding = PaddingMode.PKCS7;
964964

965-
using (MemoryStream ms = new MemoryStream())
966-
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
967-
{
968-
cs.Write(data, 0, data.Length);
969-
cs.FlushFinalBlock();
970-
return ms.ToArray();
971-
}
965+
using (MemoryStream ms = new MemoryStream())
966+
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
967+
{
968+
cs.Write(data, 0, data.Length);
969+
cs.FlushFinalBlock();
970+
return ms.ToArray();
972971
}
973972
}
973+
}
974974

975975
/// <summary>
976976
/// 计算数据哈希值
@@ -983,6 +983,25 @@ private ulong CalculateHash(byte[] data)
983983
return BitConverter.ToUInt64(hash, 0);
984984
}
985985
}
986+
987+
/// <summary>
988+
/// 使用LZ4压缩块信息并添加头部
989+
/// </summary>
990+
private byte[] CompressBlocksInfoLZ4WithHeader(byte[] data)
991+
{
992+
byte[] compressed = CompressLZ4(data);
993+
using (var ms = new MemoryStream())
994+
using (var writer = new BinaryWriter(ms))
995+
{
996+
// 写入4字节magic标识(例如 "LZ4H")
997+
writer.Write(Encoding.ASCII.GetBytes("LZ4H"));
998+
// 写入未压缩数据长度(4字节)
999+
writer.Write((uint)data.Length);
1000+
// 写入经过LZ4压缩的数据
1001+
writer.Write(compressed);
1002+
return ms.ToArray();
1003+
}
1004+
}
9861005
}
9871006
#endregion
9881007
}

src/Native/src/ABProcessorNative.cpp

Lines changed: 90 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,36 @@ class AssetBundleProcessor
200200
std::vector<std::string> ExtractAssetBundle(const std::string& bundlePath, const std::string& extractPath);
201201
};
202202

203+
// 辅助函数:LZ4压缩块信息并加头部
204+
static std::vector<uint8_t> CompressBlocksInfoLZ4WithHeader(const std::vector<uint8_t>& data) {
205+
std::vector<uint8_t> compressed(LZ4_compressBound((int)data.size()));
206+
int compressedSize = LZ4_compress_default(
207+
reinterpret_cast<const char*>(data.data()),
208+
reinterpret_cast<char*>(compressed.data()),
209+
(int)data.size(),
210+
(int)compressed.size()
211+
);
212+
if (compressedSize <= 0)
213+
throw std::runtime_error("LZ4压缩块信息失败");
214+
215+
compressed.resize(compressedSize);
216+
217+
std::vector<uint8_t> result;
218+
// 写入magic "LZ4H"
219+
result.push_back('L');
220+
result.push_back('Z');
221+
result.push_back('4');
222+
result.push_back('H');
223+
// 写入未压缩大小(小端)
224+
uint32_t uncompressedSize = static_cast<uint32_t>(data.size());
225+
result.insert(result.end(),
226+
reinterpret_cast<uint8_t*>(&uncompressedSize),
227+
reinterpret_cast<uint8_t*>(&uncompressedSize) + 4);
228+
// 写入压缩数据
229+
result.insert(result.end(), compressed.begin(), compressed.end());
230+
return result;
231+
}
232+
203233
// C接口包装
204234
extern "C" {
205235

@@ -684,84 +714,77 @@ std::string AssetBundleProcessor::CreateAssetBundle(const std::string& bundleNam
684714
blockInfo.Flags |= 0x1; // 设置加密标志
685715
}
686716

687-
// 序列化文件信息
688-
std::vector<uint8_t> fileInfoData;
717+
// 序列化块信息和文件信息
718+
std::vector<uint8_t> blocksInfoBytes;
719+
// 写入未压缩大小
720+
uint32_t uncompressedSize = static_cast<uint32_t>(fileData.size());
721+
blocksInfoBytes.resize(blocksInfoBytes.size() + sizeof(uint32_t));
722+
std::memcpy(blocksInfoBytes.data() + blocksInfoBytes.size() - sizeof(uint32_t), &uncompressedSize, sizeof(uint32_t));
723+
// 写入块数量
724+
uint32_t blockCount = 1;
725+
blocksInfoBytes.resize(blocksInfoBytes.size() + sizeof(uint32_t));
726+
std::memcpy(blocksInfoBytes.data() + blocksInfoBytes.size() - sizeof(uint32_t), &blockCount, sizeof(uint32_t));
727+
// 写入块信息
728+
blockInfo.Serialize(blocksInfoBytes);
689729
// 写入文件数量
690730
uint32_t fileCount = static_cast<uint32_t>(fileInfos.size());
691-
fileInfoData.resize(fileInfoData.size() + sizeof(uint32_t));
692-
std::memcpy(fileInfoData.data() + fileInfoData.size() - sizeof(uint32_t), &fileCount, sizeof(uint32_t));
693-
731+
blocksInfoBytes.resize(blocksInfoBytes.size() + sizeof(uint32_t));
732+
std::memcpy(blocksInfoBytes.data() + blocksInfoBytes.size() - sizeof(uint32_t), &fileCount, sizeof(uint32_t));
694733
// 写入每个文件的信息
695734
for (const auto& fileInfo : fileInfos) {
696-
fileInfo.Serialize(fileInfoData);
735+
fileInfo.Serialize(blocksInfoBytes);
697736
}
698-
737+
738+
// 压缩块信息并加头部
739+
std::vector<uint8_t> compressedBlocksInfo = CompressBlocksInfoLZ4WithHeader(blocksInfoBytes);
740+
699741
// 创建头部
700742
UnityAssetBundleHeader header;
701743
header.BundleName = bundleName;
702744
header.FileCount = static_cast<int32_t>(fileInfos.size());
703745
header.IsEncrypted = _useEncryption;
704746
header.CompressionType = _unityCompressionType;
705747
header.UnityVersion = _unityVersion;
706-
707-
// 计算块信息大小
708-
header.BlocksInfoSize = sizeof(uint32_t) + sizeof(BlockInfo) + fileInfoData.size();
709-
710-
// 计算文件大小
748+
header.BlocksInfoSize = static_cast<int64_t>(compressedBlocksInfo.size());
711749
header.FileSize = header.HeaderSize + header.BlocksInfoSize + compressedData.size();
712-
713-
// 计算未压缩数据哈希
714750
header.UncompressedDataHash = CalculateHash(fileData);
715-
751+
716752
// 序列化头部
717753
std::vector<uint8_t> headerData = header.SerializeHeader();
718-
754+
719755
// 创建输出文件
720756
std::ofstream outputFile(bundlePath, std::ios::binary);
721757
if (!outputFile) {
722758
throw std::runtime_error("Unable to create output file: " + bundlePath);
723759
}
724-
760+
725761
// 写入头部
726762
outputFile.write(reinterpret_cast<const char*>(headerData.data()), headerData.size());
727-
728-
// 写入块数量(始终为1)
729-
uint32_t blockCount = 1;
730-
outputFile.write(reinterpret_cast<const char*>(&blockCount), sizeof(uint32_t));
731-
732-
// 写入块信息
733-
std::vector<uint8_t> blockInfoBuffer;
734-
blockInfo.Serialize(blockInfoBuffer);
735-
outputFile.write(reinterpret_cast<const char*>(blockInfoBuffer.data()), blockInfoBuffer.size());
736-
737-
// 写入文件信息
738-
outputFile.write(reinterpret_cast<const char*>(fileInfoData.data()), fileInfoData.size());
739-
763+
// 写入块信息(LZ4压缩+头部)
764+
outputFile.write(reinterpret_cast<const char*>(compressedBlocksInfo.data()), compressedBlocksInfo.size());
740765
// 写入压缩数据
741766
outputFile.write(reinterpret_cast<const char*>(compressedData.data()), compressedData.size());
742-
743-
// 计算CRC
744767
outputFile.close();
768+
769+
// 计算CRC
745770
std::ifstream inputFile(bundlePath, std::ios::binary);
746771
if (!inputFile) {
747772
throw std::runtime_error("Unable to read file to calculate CRC: " + bundlePath);
748773
}
749-
750774
std::vector<uint8_t> fileContent(header.FileSize);
751775
inputFile.read(reinterpret_cast<char*>(fileContent.data()), fileContent.size());
752776
header.CRC = CalculateCRC32(fileContent);
753777
inputFile.close();
754-
778+
755779
// 更新CRC
756780
std::ofstream updateFile(bundlePath, std::ios::binary | std::ios::in | std::ios::out);
757781
if (!updateFile) {
758782
throw std::runtime_error("Unable to update file CRC: " + bundlePath);
759783
}
760-
761784
headerData = header.SerializeHeader();
762785
updateFile.write(reinterpret_cast<const char*>(headerData.data()), headerData.size());
763786
updateFile.close();
764-
787+
765788
return bundlePath;
766789
}
767790

@@ -784,21 +807,36 @@ std::vector<std::string> AssetBundleProcessor::ExtractAssetBundle(const std::str
784807
file.read(reinterpret_cast<char*>(headerData.data()), headerData.size());
785808
UnityAssetBundleHeader header = UnityAssetBundleHeader::DeserializeHeader(headerData);
786809

787-
// 读取压缩的块信息
788-
int blocksInfoOffset = header.HeaderSize; // 使用真实头部大小
789-
file.seekg(blocksInfoOffset, std::ios::beg);
790-
791-
std::vector<uint8_t> compressedBlocksInfo(header.BlocksInfoSize);
792-
file.read(reinterpret_cast<char*>(compressedBlocksInfo.data()), compressedBlocksInfo.size());
793-
794-
// 解压块信息 - 块信息通常使用LZ4压缩
795-
std::vector<uint8_t> blocksInfoBytes = DecompressData(compressedBlocksInfo, UnityCompressionType::LZ4);
796-
810+
// 读取magic
811+
char magic[4];
812+
file.read(magic, 4);
813+
if (memcmp(magic, "LZ4H", 4) != 0)
814+
throw std::runtime_error("块信息LZ4头部magic不匹配");
815+
816+
// 读取未压缩大小
817+
uint32_t uncompressedSize = 0;
818+
file.read(reinterpret_cast<char*>(&uncompressedSize), 4);
819+
820+
// 读取压缩数据
821+
std::vector<uint8_t> compressedData(header.BlocksInfoSize - 8);
822+
file.read(reinterpret_cast<char*>(compressedData.data()), compressedData.size());
823+
824+
// 解压
825+
std::vector<uint8_t> blocksInfoBytes(uncompressedSize);
826+
int decoded = LZ4_decompress_safe(
827+
reinterpret_cast<const char*>(compressedData.data()),
828+
reinterpret_cast<char*>(blocksInfoBytes.data()),
829+
(int)compressedData.size(),
830+
(int)uncompressedSize
831+
);
832+
if (decoded != (int)uncompressedSize)
833+
throw std::runtime_error("LZ4解压块信息失败");
834+
797835
// 从解压后的块信息中读取块和文件信息
798836
size_t offset = 0;
799837

800838
// 读取未压缩大小
801-
uint32_t uncompressedSize = *reinterpret_cast<const uint32_t*>(blocksInfoBytes.data() + offset);
839+
uint32_t uncompressedSizeFromBlocks = *reinterpret_cast<const uint32_t*>(blocksInfoBytes.data() + offset);
802840
offset += sizeof(uint32_t);
803841

804842
// 读取块数量
@@ -855,19 +893,19 @@ std::vector<std::string> AssetBundleProcessor::ExtractAssetBundle(const std::str
855893
}
856894

857895
// 读取压缩数据块
858-
int dataOffset = blocksInfoOffset + static_cast<int>(header.BlocksInfoSize);
896+
int dataOffset = header.HeaderSize + static_cast<int>(header.BlocksInfoSize);
859897
file.seekg(dataOffset, std::ios::beg);
860898

861-
std::vector<uint8_t> compressedData(blocks[0].CompressedSize);
862-
file.read(reinterpret_cast<char*>(compressedData.data()), compressedData.size());
899+
std::vector<uint8_t> compressedDataBlock(blocks[0].CompressedSize);
900+
file.read(reinterpret_cast<char*>(compressedDataBlock.data()), compressedDataBlock.size());
863901

864902
// 如果数据已加密,则解密
865903
if (header.IsEncrypted && _useEncryption) {
866-
compressedData = DecryptData(compressedData);
904+
compressedDataBlock = DecryptData(compressedDataBlock);
867905
}
868906

869907
// 解压数据
870-
std::vector<uint8_t> bundleData = DecompressData(compressedData, header.CompressionType);
908+
std::vector<uint8_t> bundleData = DecompressData(compressedDataBlock, header.CompressionType);
871909

872910
// 验证解压后大小
873911
if (bundleData.size() != blocks[0].UncompressedSize) {

0 commit comments

Comments
 (0)