底特律变人游戏封包语音提取

实用技术 AI 算法
44

Detroit: Become Human (PC) BigFile 封包系统分析

大肥鱼Flash逆向整合

1. 封包文件清单

文件 作用
BigFile_PC.idx 全局索引:373748 条记录,指向所有资源
BigFile_PC.dat 数据分片 0(约 2 GiB)
BigFile_PC.d01 ~ BigFile_PC.d29 数据分片 1~29(每个约 2 GiB)
BigFile_PC.dep 依赖清单,与 idx 同构的精简版

索引和数据的分离设计:.idx 只有 10 MB,游戏启动时先加载它,之后按需从 30 个分片里 seek 读取。

2. BigFile_PC.idx 索引格式

2.1 头部

text
偏移 0:   51 55 41 4E 54 49 43 44 52 45 41 4D 54 41 42 49 4E 44 45 58
          "QUANTICDREAMTABINDEX"(19 字节,明文魔数)
偏移 19:  4 字节,值为 0x12(未知,疑似版本号)
偏移 23:  4 字节,0x00B0385F(未知)
偏移 27:  "ZEP" × 24(填充区,疑似调试/对齐用)
偏移 101: uint32 BE 条目数(Steam 版 = 373748)
偏移 105: 条目区起点

自校验公式105 + 条目数 × 28 == 文件大小,对 Steam 版:105 + 373748×28 = 10465049,精确相等。

2.2 条目结构(28 字节,全大端)

从偏移 105 起,每条 28 字节,7 个 uint32 BE:

字段 说明
type 资源类型(见附录类型表)
恒为 1 疑似版本/标志
data_id 资源 ID
offset 相对该分片文件的偏移
size 资源大小
unk 未知(多数为 0,音频里另有含义)
bigfile 分片号:0 = .dat,129 = .d01.d29

真实数据示例(前几条):

text
@105: type=19001  f2=1  id=166   off=2048     size=1529  unk=0  file=0
@133: type=19001  f2=1  id=706   off=4096     size=73     unk=0  file=0
@161: type=19001  f2=1  id=635   off=6144     size=41     unk=0  file=0

读取方法:offset/size 相对于 bigfile 指定的分片文件,直接 seek(offset) + read(size) 即可拿到资源本体。容器层无加密、无压缩

3. BigFile_PC.dep 依赖清单

与 idx 同构但更精简:

text
"QUANTICDREAMTABINDEX" + 00 00 00 12 + uint32 BE 条目数 + 条目区(从偏移 27 起)

条目同样 28 字节,但 offset/size 恒为 0(它只声明"存在哪些 type/id",供依赖分析用)。

4. 资源本体格式

按索引切出来的资源分两大类:

4.1 QZIP 容器(模型/纹理/音频等)

text
"QZIP\0" + 8 字节类型魔数 + 类型相关头 + 数据

常见魔数:GOGCCHK_(19001)、NOCHK___(19000)、ETF_RAW_(2229)、ETF_RAWL(2230)、DC_INFO(29)、CSNDDATA(1033)、CSNDEVNT(1023)等。

QZIP 内部压缩是 Quantic Dream 自研算法,不是标准 zlib(对多个偏移尝试 zlib.decompress 均失败)。模型/纹理的最终解码目前依赖 daemon1 的工具(见第 8 节)。

4.2 COM_CONT 明文结构(文本/目录类)

LOCALIZ_(1016)、CATALOG(3)、MOTION_GRAPH(15000)等直接以 COM_CONT 开头,无 QZIP 壳,是带标签的序列化结构(详见第 6 节)。

5. 语音资源深挖(CSNDDATA)

这是本项目重点。类型 1033(CSNDDATA)共 80976 条,全部可解析,结构:

text
"QZIP\0CSNDDATA"                       (13 字节)
00 00 00 00                            (4 字节 0)
uint32 LE (数据区大小 - 21)
uint32 LE 20                           (占位串长度)
"18446744073709551615"                 (20 字节占位串)
float32 LE @45                         时长(秒,与解码结果一致)
uint32 LE @49                          事件名长度
ASCII 事件名 @53                       如 X1106M_HOLDON_INTRO_PC_X11MMARKUS_SINGING_ENG
uint32 LE                              内嵌 RIFF 总大小(8 + riff_size)
"RIFF" + ... "WAVE" + "fmt " + "data"  (标准 RIFF/WAVE,Wwise 封装)

关键点:

  • 内层是 Wwise "Custom Vorbis"(WAVE_FORMAT_EXTENSIBLE + 私有 GUID,48 kHz 单声道)。用 vgmstream 可直接解成 PCM WAV,不用关心 GUID。
  • 事件名 = 台词/音效名,命名规则见下;这也是"说话人"信息的来源。
  • 时长字段是可信的(35.47s 的 float 与 vgmstream 解码结果一致)。

5.1 事件名命名规则

text
X1106M_HOLDON_INTRO_PC_X11MMARKUS_SINGING_ENG
│      │   │      │   │   │      │        └─ 语言后缀(ENG/JPN/...)
│      │   │      │   │   └──────┴─ 角色 token:X11M + "MARKUS"
│      │   │      └───┴─ 平台/用途(PC/FA/VO...)
│      └───┴─ 场景名(HOLDON_INTRO)
└────────── 章节码(X11 + 主角线 M)

章节码第 4 位是主角线:K=卡拉线、C=康纳线、M=马库斯线、A/X=其他。角色 token 里 X<章节><线><角色名>,如 X07KKARAX08CHANKX05MMARKUSX09KALICE

5.2 说话人提取规则(实测)

  1. 取 token 中 X + 数字 + 线字母(K/C/M/A/X)后的部分为角色名
  2. K/C/M/X 线字母直接剥离;A 仅在后面是已知人名时剥离(否则 "ANDROID" 这类保留)
  3. 已知人名表兜底:KARA/MARKUS/CONNOR/HANK/ALICE/AMANDA/CARL/LUTHER/ROSE/JOSH/NORTH/SIMON/JERRY/RALPH/ZLATKO/KAMSKI/DANIEL/TODD/CHLOE/LEO/REED/GAVIN/FOWLER/TRACI/CARLOS/CURTIS/HARVEY/MARLA/PERKINS/CARTLAND/WARREN
  4. 解析不到标 UNKNOWN

5.3 语言分布(全量验证)

80976 = 12 种配音语言 × 每种恰好 6748 条

语言 条数 语言 条数
ENG 6748 FRE 6748
GER 6748 ITA 6748
SPA 6748 MEX 6748
POR 6748 BRA 6748
JPN 6748 POL 6748
ARA 6748 RUS 6748

中文(SCH 简体 / CHI 繁体)只有字幕,没有配音。全部配音总时长约 29.2 小时/语言。

6. LOCALIZ_ 本地化文本格式

类型 1016,1327 条,COM_CONT 明文。结构要点:

text
"COM_CONT" + uint32 + uint32        (容器头)
... "LOCALIZ_" 标记 ...
uint32 LE loca_type(5 或 6)        (5=英法双语,6=全语言)
uint32 LE lang_count
内容区:
  [ 语言块 ] × lang_count
    语言块头: 01 03 00 00 + 语言码(3 字节 ASCII,如 ENG)
    键值流:
      uint32 unk + uint32 key_len
      key(ASCII)
      uint32 text_len + text(UTF-16LE)

实测:每语言 18140 键;SCH(简体)与 CHI(繁体)同时存在。带章节码的台词键约 1 万/语言,其中 6748 个有配音(其余为字幕/选项/流程名)。文本里带 {S}{*1}<QD_BR> 等事件标记,训练前需清洗。

7. CSNDEVNT 音频事件

类型 1023/1031,QZIP\0CSNDEVNT 壳:

text
"QZIP\0CSNDEVNT"
01 00 00 00              (版本/标志)
3C 00 00 00              (结构大小)
0A 00 00 00              (ID 串长度)
"1284272540"             (事件 ID,十进制 ASCII)
16 00 00 00              (事件名长度)
"Play_AD_VO_CAR_SHOP_PH" (事件名,AD_VO=语音对白)
00 00 00 00
float32 × 2              (疑似音量/时长)
uint32 1022              (引用类型 CSNDBNK_)
uint32                   (bank 索引)

8. exe 侧逆向线索(脱壳后)

用 radare2 / IDA 分析 DetroitBecomeHuman.exe.unpacked.exe

地址 内容
0x141DED060 / 0x141DED070 魔数被拆成两段存储:"TABINDEX" + "QUANTICDREAM",加载时拼接校验
sub_140528BA0 "%s%.2d" 拼接分片文件名,再调 sub_14052A130 打开并校验魔数
sub_1401367E0 BigFile 管理器初始化(读取 "Bigfile" 配置键)
0x141DEDB10 字符串 "BigFile_Chunk_%i_PC"

结论:索引读取逻辑就是"校验魔数 → 读条目数 → 循环读 28 字节大端条目",与文件侧观察完全一致。

9. 提取工具链

9.1 本仓库工具(Rust)

dbh-bigfile-unpack:解析 idx、按类型/分片过滤提取、自动分片目录、生成 HTML 索引 + CSV 清单。核心优化:

  • 30 个分片各一个线程,组内按偏移排序顺序读(消除随机寻址)
  • 大类型目录按 4096 个/子目录分片(规避 NTFS 单目录瓶颈,8 万小文件从 165s 降到 26s)
  • 8MB 滑窗批量读(语言过滤场景下把寻道量减少 30 倍)

gui_dingzhi:中英/中日语音数据集导出(语音 + 说话人 + 三语文本 + 角色名映射),自动调 vgmstream 转 WAV 并裁剪首尾静音。

powershell
# 解包全部资源(按类型目录)
dbh-bigfile-unpack.exe -i 游戏目录 -o unpacked -t 1016 -t 1033
# 语音数据集(中英中日)
dbh-bigfile-unpack.exe --dataset -i 游戏目录 -o E:\dbhvoic --lang ENG,JPN --wav-convert

9.2 社区工具

  • daemon1 的 Detroit.exe(XeNTaX t=19586):模型/贴图/动画/声音提取,PC/PS4 通用,自带角色文件清单
  • dbh-file-parser(GitHub detroitbecometext):LOCALIZ_ 文本 → JSON
  • vgmstream:Wwise .wem → PCM WAV(支持该游戏的内层 Vorbis)

10. 附录:类型号全表(Steam 版 373748 条)

type 名称 条数 说明
3 CATALOG 2649 资源目录
29 DATA_CONTAINER 3265 数据容器
1016 LOCALIZ_ 1327 本地化文本
1033 CSNDDATA 80976 音频数据
2033 ANIMDATA 24562 动画
2212 EVENTS__ 24555 事件
2229/2230 ETF_RAW_/ETF_RAWL 127939 纹理
4091 HEADER__ 80976 音频头
19000/19001 NOCHK___/GOGCCHK_ 1374 关卡数据
4288/4333 SCRIPT/SCPTBANK 5485 脚本
14000 NAVM____ 79 导航网格
15000 MOTION_GRAPH 48 动作图

完整 41 种类型用 dbh-bigfile-unpack.exe -i 游戏目录 --list-types 查看。

11. 总结

  • 容器层零加密:QUANTICDREAMTABINDEX 明文魔数 + 大端 28 字节条目 + 纯 seek 读取
  • 资源层:QZIP 自研压缩壳(文本类除外) + Wwise 音频 + 自研序列化
  • 语音文件名本身就是元数据(章节/场景/角色/语言)
  • 游戏实际配音量 = 12 语言 × 6748 条/语言

本文版权遵循 CC BY-NC 协议 本站版权政策

(。>︿<。) 已经一滴回复都不剩了哦~