当前位置: 首页 > news >正文

UE4 Pak 文件格式

UE4 Pak 文件格式

https://wangjie.rocks/2019/01/10/ue4-pak/

UE4 Pak 文件格式

jashwang   收录于 Unreal engine4

2019-01-10  约 1735 字  预计阅读 4 分钟 

UE4 打包过程中,会调用 UnrealPak 将 Cook 后的文件资源打包成一整个 Pak 文件,这个 Pak 中的内容可以分为三大块,按写入顺序分别为:文件内容区 + 文件索引信息区 + Pak文件信息区

  • 文件内容区: 依次存储每个文件的 FPakEntry + 文件内容

  • 文件索引信息区: 依次存储每个文件的 文件名 + FPakEntry

  • Pak文件信息区: 存储整个 Pak 文件的信息

    注意: 文件内容区文件索引信息区 FPakEntry 部分除了 Offset 外是冗余存储的,文件内容区域的 FPakEntry 序列化时 Offset 的8字节内容全为 0,如图

    PakInfo_Redundant.png

Pak文件信息区: FPakInfo

这个结构体序列化后,写到pak文件的最后的地方,固定 45 字节,格式如下,代码见 FPakFile::Initialize

PakInfo.png

  • bEncryptedIndex: 1 字节,表示pak的索引部分是否被加密

    PakInfo_EncryptedIndex.png

    Pak 文件加密的基本过程:编译时,TargetRules.cs 文件中会添加一个宏定义 IMPLEMENT_ENCRYPTION_KEY_REGISTRATION(),这个宏展开成 UE_REGISTER_ENCRYPTION_KEY(YourAESKeyCode),这个宏里会声明一个全局结构体实例 GEncryptionKeyRegistration,在构造函数里调用 RegisterEncryptionKeyCallback 注册一个回调,这个回调就是返回 YourAESKeyCodeRegisterEncryptionKeyCallback 这个函数里其实就是向FCoreDelegates::GetPakEncryptionKeyDelegate 里绑定了一个 lambda,lambda里调用回调函数获取密钥。完整的宏展开流程 IMPLEMENT_APPLICATION -> IMPLEMENT_ENCRYPTION_KEY_REGISTRATION -> UE_REGISTER_ENCRYPTION_KEY。也就是说,默认 Pak 加密的 AES 密钥是硬编码在代码里的

  • Magic: 4 字节,值必须为 0x5A6F12E1,否则是非法pak

    PakInfo_Magic.png

  • Version: 4 字节,pak文件格式的版本号

    PakInfo_Version.png

    每个版本的区别如下:

    • 1:初始版本号
    • 2: 移除了 FPakEntry 中的时间戳
    • 3:增加文件加密功能和分块压缩功能,FPakEntry 中多了分块信息数据和是否加密的标志位
    • 4:增加索引加密功能,FPakInfo 中多了索引是否加密的标志位
    • 5:压缩分块信息中的起始和结束位置是相对于 FPakEntry.Offset 的偏移,之前的版本是相对于 Pak 文件起始位置(即0)的偏移
  • IndexOffset: 8 字节,Pak 文件索引信息区的起始位置

    PakInfo_IndexOffset.png

  • IndexSize: 8 字节,Pak 文件索引信息区的大小

    PakInfo_IndexSize.png

  • IndexHash: 20 字节,文件索引信息的SHA1值

    PakInfo_IndexHash.png

文件索引信息区

从上面的结构体中根据索引的起始偏移和大小定位索引内容,并且根据 bEncryptedIndex 来判断是否要对索引内容进行解密,格式如下,代码见 FPakFile::LoadIndex

  • MountPoint: 默认挂载点,类型是字符串,长度不定。字符串序列化格式为:4字节(内容为字符串长度) + 字符串内容(字符串以0结尾)

    Index_MountPoint.png

  • NumEntries: 4 字节,序列化的文件数量

    Index_NumEntries.png

  • 接下来就是依次存储每个文件的 Filename(文件路径) 和对应的 FPakEntry,有 NumEntries 个

Filename

Index_PakEntry_Filename.png

FPakEntry

FPakEntry 记录的是每一个文件序列化到 Pak 中的文件头信息,序列化格式如下

  • Offset: 8 字节,文件实际内容区域起始位置在 Pak 文件中的偏移,第一个文件就是 0

    Index_PakEntry_Offset.png

  • Size:8 字节,文件压缩后的大小

    Index_PakEntry_Size.png

  • UncompressedSize:8 字节,文件原始大小

    Index_PakEntry_UncompressedSize.png

  • CompressionMethod: 4 字节,文件压缩方式,见 ECompressionFlags

    Index_PakEntry_CompressionMethod.png

  • Timestamp: 8 字节,时间戳,这个数据只在老版本的pak(Version <= 1) 中才有,Version >= 2 中的 pak 已经废弃不序列化了

  • Hash: 20 字节,文件的SHA1哈希值

    Index_PakEntry_Hash.png

  • CompressionBlocks: 分块信息列表,每一个分块信息为 16 字节(两个 uint64,分别是块内容起始位置偏移和结束位置偏移)。分块信息数据只有在 Version >= 3,并且开启了压缩的情况下才会序列化。TArray 的序列化格式为: 4 字节(内容为Array长度) + 每一个 Array项 的序列化。所以这部分数据大小为: 4 + 16 * 分块数量,下面的图中只有一个分块

    Index_PakEntry_CompressionBlocks.png

  • bEncrypted: 1 字节,文件块内容是否加密,这部分数据只有在 Version >= 3 才有

    Index_PakEntry_IsEncrypted.png

  • CompressionBlockSize: 4 字节,每一个压缩分块的大小,这部分数据只有在 Version >= 3 才有。序列化时,每个文件会按这个值进行分块,然后每个分块再进行压缩加密,默认值是 64K,如果文件大小小于这个值,则CompressionBlockSize 就是文件实际大小。反序列化时,读取每个分块,进行解密,然后再分配CompressionBlockSize 大小的内存进行解压,所有的内存块合起来就是真正的文件内容,下图的分块大小是 1055

    Index_PakEntry_CompressionBlockSize.png

文件内容区

这个区域位于 Pak 文件的起始位置,依次存储每一个文件的 FPakEntry 和实际文件内容,如果开启了压缩,则文件内容需要进行分块压缩,如果开启了加密,则压缩过的文件内容还要进行加密

FileChunk.png

本文于 2019-01-10 更新

 UE4

返回 | 主页

Bluelua 新特性: 在 lua 中重载蓝图函数 UE4基础:搭建开发环境

0 条

 

 

相关文章:

  • 更新UnrealPakViewer工具
  • UE4中Taglib使用及插件制作
  • UE4编辑器扩展踩坑血泪史
  • require函数
  • UE4 给static mesh 动态添加Socket
  • UE4 角色用Child Actor组建添加装备 这样方便随时添加,更换套装等行为
  • Unity Assets目录下的特殊文件夹名称
  • Unity-ShaderVariantCollection
  • Unity渲染教程(九):复杂材质 https://www.jianshu.com/p/5e3af869870f
  • HttpWebRequest(System.Net)模拟HTTP发送POST
  • C#中用HttpWebRequest中发送GET/HTTP/HTTPS请求 (转载)
  • System.Net.HttpWebRequest.GetRequestStream超时问题
  • System.Net.HttpWebRequest.GetResponse() 远程服务器
  • 【转载】HttpWebRequest的GetResponse或GetRequestStream偶尔超时 + 总结各种超时死掉的可能和相应的解决办法
  • UE4 AIController
  • [译]CSS 居中(Center)方法大合集
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • JavaScript-Array类型
  • js ES6 求数组的交集,并集,还有差集
  • k个最大的数及变种小结
  • Logstash 参考指南(目录)
  • mysql 数据库四种事务隔离级别
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • MySQL用户中的%到底包不包括localhost?
  • STAR法则
  • Vue 动态创建 component
  • vuex 学习笔记 01
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 第十八天-企业应用架构模式-基本模式
  • 给新手的新浪微博 SDK 集成教程【一】
  • 近期前端发展计划
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 前端js -- this指向总结。
  • 时间复杂度与空间复杂度分析
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 数据可视化之 Sankey 桑基图的实现
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 正则表达式小结
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • #Lua:Lua调用C++生成的DLL库
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (1)Nginx简介和安装教程
  • (145)光线追踪距离场柔和阴影
  • (C语言)球球大作战
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (第27天)Oracle 数据泵转换分区表
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (论文阅读30/100)Convolutional Pose Machines
  • (三) diretfbrc详解
  • .net framework 4.0中如何 输出 form 的name属性。
  • .NET Micro Framework 4.2 beta 源码探析
  • .NET 表达式计算:Expression Evaluator