UE4 Pak 文件格式
UE4 Pak 文件格式
https://wangjie.rocks/2019/01/10/ue4-pak/
UE4 Pak 文件格式
jashwang ? 收錄于 Unreal engine4
2019-01-10? 約 1735 字? 預計閱讀 4 分鐘?
UE4 打包過程中,會調(diào)用 UnrealPak 將 Cook 后的文件資源打包成一整個 Pak 文件,這個 Pak 中的內(nèi)容可以分為三大塊,按寫入順序分別為:文件內(nèi)容區(qū) + 文件索引信息區(qū) + Pak文件信息區(qū)
-
文件內(nèi)容區(qū): 依次存儲每個文件的 FPakEntry + 文件內(nèi)容
-
文件索引信息區(qū): 依次存儲每個文件的 文件名 + FPakEntry
-
Pak文件信息區(qū): 存儲整個 Pak 文件的信息
注意: 文件內(nèi)容區(qū) 和 文件索引信息區(qū) FPakEntry 部分除了 Offset 外是冗余存儲的,文件內(nèi)容區(qū)域的 FPakEntry 序列化時 Offset 的8字節(jié)內(nèi)容全為 0,如圖
Pak文件信息區(qū): FPakInfo
這個結構體序列化后,寫到pak文件的最后的地方,固定 45 字節(jié),格式如下,代碼見 FPakFile::Initialize
-
bEncryptedIndex: 1 字節(jié),表示pak的索引部分是否被加密
Pak 文件加密的基本過程:編譯時,TargetRules.cs 文件中會添加一個宏定義 IMPLEMENT_ENCRYPTION_KEY_REGISTRATION(),這個宏展開成 UE_REGISTER_ENCRYPTION_KEY(YourAESKeyCode),這個宏里會聲明一個全局結構體實例 GEncryptionKeyRegistration,在構造函數(shù)里調(diào)用 RegisterEncryptionKeyCallback 注冊一個回調(diào),這個回調(diào)就是返回 YourAESKeyCode,RegisterEncryptionKeyCallback 這個函數(shù)里其實就是向FCoreDelegates::GetPakEncryptionKeyDelegate 里綁定了一個 lambda,lambda里調(diào)用回調(diào)函數(shù)獲取密鑰。完整的宏展開流程 IMPLEMENT_APPLICATION -> IMPLEMENT_ENCRYPTION_KEY_REGISTRATION -> UE_REGISTER_ENCRYPTION_KEY。也就是說,默認 Pak 加密的 AES 密鑰是硬編碼在代碼里的
-
Magic: 4 字節(jié),值必須為 0x5A6F12E1,否則是非法pak
-
Version: 4 字節(jié),pak文件格式的版本號
每個版本的區(qū)別如下:
- 1:初始版本號
- 2: 移除了 FPakEntry 中的時間戳
- 3:增加文件加密功能和分塊壓縮功能,FPakEntry 中多了分塊信息數(shù)據(jù)和是否加密的標志位
- 4:增加索引加密功能,FPakInfo 中多了索引是否加密的標志位
- 5:壓縮分塊信息中的起始和結束位置是相對于 FPakEntry.Offset 的偏移,之前的版本是相對于 Pak 文件起始位置(即0)的偏移
-
IndexOffset: 8 字節(jié),Pak 文件索引信息區(qū)的起始位置
-
IndexSize: 8 字節(jié),Pak 文件索引信息區(qū)的大小
-
IndexHash: 20 字節(jié),文件索引信息的SHA1值
文件索引信息區(qū)
從上面的結構體中根據(jù)索引的起始偏移和大小定位索引內(nèi)容,并且根據(jù) bEncryptedIndex 來判斷是否要對索引內(nèi)容進行解密,格式如下,代碼見 FPakFile::LoadIndex
-
MountPoint: 默認掛載點,類型是字符串,長度不定。字符串序列化格式為:4字節(jié)(內(nèi)容為字符串長度) + 字符串內(nèi)容(字符串以0結尾)
-
NumEntries: 4 字節(jié),序列化的文件數(shù)量
-
接下來就是依次存儲每個文件的 Filename(文件路徑) 和對應的 FPakEntry,有 NumEntries 個
Filename
FPakEntry
FPakEntry 記錄的是每一個文件序列化到 Pak 中的文件頭信息,序列化格式如下
-
Offset: 8 字節(jié),文件實際內(nèi)容區(qū)域起始位置在 Pak 文件中的偏移,第一個文件就是 0
-
Size:8 字節(jié),文件壓縮后的大小
-
UncompressedSize:8 字節(jié),文件原始大小
-
CompressionMethod: 4 字節(jié),文件壓縮方式,見 ECompressionFlags
-
Timestamp: 8 字節(jié),時間戳,這個數(shù)據(jù)只在老版本的pak(Version <= 1) 中才有,Version >= 2 中的 pak 已經(jīng)廢棄不序列化了
-
Hash: 20 字節(jié),文件的SHA1哈希值
-
CompressionBlocks: 分塊信息列表,每一個分塊信息為 16 字節(jié)(兩個 uint64,分別是塊內(nèi)容起始位置偏移和結束位置偏移)。分塊信息數(shù)據(jù)只有在 Version >= 3,并且開啟了壓縮的情況下才會序列化。TArray 的序列化格式為: 4 字節(jié)(內(nèi)容為Array長度) + 每一個 Array項 的序列化。所以這部分數(shù)據(jù)大小為: 4 + 16 * 分塊數(shù)量,下面的圖中只有一個分塊
-
bEncrypted: 1 字節(jié),文件塊內(nèi)容是否加密,這部分數(shù)據(jù)只有在 Version >= 3 才有
-
CompressionBlockSize: 4 字節(jié),每一個壓縮分塊的大小,這部分數(shù)據(jù)只有在 Version >= 3 才有。序列化時,每個文件會按這個值進行分塊,然后每個分塊再進行壓縮加密,默認值是 64K,如果文件大小小于這個值,則CompressionBlockSize 就是文件實際大小。反序列化時,讀取每個分塊,進行解密,然后再分配CompressionBlockSize 大小的內(nèi)存進行解壓,所有的內(nèi)存塊合起來就是真正的文件內(nèi)容,下圖的分塊大小是 1055
文件內(nèi)容區(qū)
這個區(qū)域位于 Pak 文件的起始位置,依次存儲每一個文件的 FPakEntry 和實際文件內(nèi)容,如果開啟了壓縮,則文件內(nèi)容需要進行分塊壓縮,如果開啟了加密,則壓縮過的文件內(nèi)容還要進行加密
本文于 2019-01-10 更新
?UE4
返回?|?主頁
Bluelua 新特性: 在 lua 中重載藍圖函數(shù) UE4基礎:搭建開發(fā)環(huán)境
0 條
?
?
總結
以上是生活随笔為你收集整理的UE4 Pak 文件格式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: selenium定位不准的问题
- 下一篇: SolarWinds盛邀技术专业人士参加