@@ -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接口包装
204234extern " 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