tanosshi/FH6Hook
GitHub: tanosshi/FH6Hook
通过代理 DLL 拦截游戏音频库文件读取操作,重建并对外广播《Forza Horizon 6》实时电台播放曲目的遥测信息。
Stars: 1 | Forks: 0
# FH6Hook
FH6 的实时电台追踪。
本项目构建了一个运行在游戏进程内部的 `version.dll` 代理。它会监视电台音频库(bank)文件的读写活动,将读取的偏移量映射回 FSB5 采样,将这些采样与 `RadioInfo_EN.xml` 进行关联,并通过命名管道发出“正在播放”的遥测数据。
游戏本身并未公开“正在播放”的 API。该 Hook 通过解析对 FMOD `.bank` 文件的读取操作,重建了当前播放的音轨信息。
任何外部监听器都可以通用此 DLL,例如 [用于 Last.fm 集成的 Python scrobbler](https://github.com/tanosshi/FH6Scrobbler)。你还可以将此 DLL 用于游戏覆盖层、日志记录或其他创意用途。
当前的方法**不会**触发反作弊系统、反篡改机制或任何可疑活动,因为它仅观察文件读取操作,不会修改游戏代码或内存。Hook 的设计非常精准且高效,遥测数据通过命名管道异步发送。
## Hook 概要
1. 代理 DLL 会被游戏作为 `version.dll` 加载,随后它会从游戏目录中加载名为 `version_original.dll` 的原始 dll。
2. `UserImplementations.cpp` 会启动一个后台线程。
3. 该线程会为以下函数安装 Detours Hook:
- `CreateFileW`
- `ReadFile`
- `CloseHandle`
4. 该线程会将 `media\Audio\RadioInfo_EN.xml` 解析为音轨元数据表。
5. 当游戏打开电台音轨库文件时,`CreateFileW` 会检测到它们。
6. `ReadFile` 会观察受追踪的库句柄的读取偏移量。
7. `AudioDiagnostics.cpp` 会解析每个 FSB5 库,并记录每个采样的字节范围。
8. `RadioTracker.cpp` 会过滤掉启动时的预载噪音,检测电台切换,并打开一个短暂的读取窗口。
9. 当读取偏移量落入已知音轨的范围内时,DLL 会通过 `\\.\pipe\molotov` 发出 `PLAY`、`PING` 和 `STOP` 事件。
这些 Hook 的作用域经过了刻意的限制。它们仅追踪电台的 `.bank` 文件,并在 Hook 路径之外对遥测数据进行排队处理,因此游戏线程不会因为管道 I/O 而被阻塞。
## Hook 的遥测数据
DLL 会向命名管道写入基于行的文本消息:
```
PLAY|Artist - Track [Station]
PING|Artist - Track [Station]
STOP|music_inactive|last=Artist - Track [Station]
```
重要的消息类型包括 `FILE`、`READ`、`STATION`、`FMOD` 和 `TICK`。
## 项目布局
### UserFiles
`UserFiles/UserImplementations.cpp`
项目的入口点。它会创建后台线程,按需打开命名管道,提供日志辅助工具,加载 `RadioInfo_EN.xml`,初始化追踪模块,并保持周期性的诊断循环持续运行。
`UserFiles/AudioDiagnostics.h`
共享的音频追踪声明。它定义了 `TrackInfo`,用于存储由库解析器和电台追踪器所使用的解析后的 XML 元数据,并声明了公共的音频诊断函数。
`UserFiles/AudioDiagnostics.cpp`
安装并管理 Windows API Hook。它会追踪已打开的电台库句柄,将宽路径转换为 UTF-8,从 `.bank` 文件中解析 FSB5 采样表,将采样的字节范围映射到 `TrackInfo`,在激活的读取窗口期间检测音轨读取操作,并发送 `PLAY`、`PING` 和 `STOP` 遥测数据。
`UserFiles/RadioTracker.h`
电台追踪器的公共接口。它暴露了初始化、排队的库路径处理以及周期性 tick 功能。
`UserFiles/RadioTracker.cpp`
将库打开事件过滤为电台状态。它会忽略启动时的预载噪音,追踪已识别的电台库,提取电台前缀(例如 `HZ6_R3_`),对电台切换进行防抖处理,并在 `AudioDiagnostics.cpp` 中激活读取窗口。
`UserFiles/FmodEngine.h`
供 `RadioTracker.cpp` 使用的小型接口,用于判断电台就绪状态和发送心跳报告。
`UserFiles/FmodEngine.cpp`
追踪电台的就绪状态并发送轻量级的 FMOD 阶段遥测数据。先前实验性的 FMOD detour 路径已被移除;当前的音轨检测由 `AudioDiagnostics.cpp` 中的文件读取 Hook 处理。
`UserFiles/StringUtils.h`
遵循 Don't Repeat Yourself (DRY) 原则的字符串转换和格式化工具。
`UserFiles/tinyxml2.h` 和 `UserFiles/tinyxml2.cpp`
内置的 TinyXML2 解析器,用于读取 `RadioInfo_EN.xml`。
## 构建说明
构建时仅需针对 `Release|x64` 目标。
本项目需要 Microsoft Detours 的头文件和库文件位于以下路径:
```
Detours-src\include
Detours-src\lib.X64
```
如果你尚未安装,请使用 `build_detours_x64.bat` 脚本来构建 Detours。
GitHub Actions 会自动下载 Microsoft Detours 并为发布版本进行构建。本地构建仍然需要在项目文件夹中包含 `Detours-src`。
典型的构建命令:
```
msbuild version.sln /p:Configuration=Release /p:Platform=x64 /m
```
输出的 DLL 会写入到:
```
x64\Release\version.dll
```
## 运行时说明
- 命名管道为 `\\.\pipe\molotov`。
- XML 元数据路径必须是 `media\Audio\RadioInfo_EN.xml`,且相对于游戏可执行文件所在目录。
- 启动时的电台库预载会产生大量噪音,因此电台检测会等待预载进度或预载超时,然后再激活正常的读取窗口。
- 音轨检测基于观察到的文件读取操作,而非直接的 FMOD 事件回调。
__请注意,我与 Microsoft、Turn 10 Studios、Playground Games、Xbox Games Studio、CBS Corporation 或 Last.fm 没有任何隶属关系。这是一个作为业余爱好创建的非官方粉丝自制 Mod,我没有受到任何资助或受邀制作此项目。__
标签:API Hook, C++, DLL代理, 数据提取, 数据擦除, 游戏模组, 端点可见性