新增奥日2排障记录:Wwise 线程亲和性故障定位与兼容补丁(文章4篇+补丁包+诊断脚本4个,已脱敏)
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# 诊断脚本说明
|
||||
|
||||
这 4 个脚本是 2026-09-16 那轮定位用到的全部工具,用 Python 标准库写的,**不需要装任何第三方包**。
|
||||
|
||||
对应的技术报告见 `../文章/奥日2崩溃研究报告.md` 第 5 节(动态实验设计及结果)。
|
||||
|
||||
---
|
||||
|
||||
## 每个脚本做什么
|
||||
|
||||
### 1. `ori_debug.py` — 核心诊断器
|
||||
|
||||
用 Windows 调试接口**启动自己的游戏子进程**(不是附加到别的进程,也不装系统钩子),
|
||||
在音频线程初始化附近的指令上打临时断点(INT3),记录寄存器、参数、返回值和**目标线程自己的** LastError。
|
||||
|
||||
这是抓到"`SetThreadAffinityMask` 返回 0、错误码 87"那个关键证据的工具。
|
||||
|
||||
```powershell
|
||||
# 只校验 DLL 哈希,不启动游戏
|
||||
python ori_debug.py --game "D:\Games\Ori and the Will of the Wisps" --check
|
||||
|
||||
# 原始运行:只下断点观察,不做任何修改
|
||||
python ori_debug.py --game "D:\Games\..." --seconds 40 --output ori-evidence/runtime-original
|
||||
|
||||
# 对照实验 A:把掩码截断到进程可用范围(用来否掉"高位越界"假设)
|
||||
python ori_debug.py --game "D:\Games\..." --clamp-affinity
|
||||
|
||||
# 对照实验 B:在进程内把 setter 写入的掩码改成 0(临时验证,不落盘)
|
||||
python ori_debug.py --game "D:\Games\..." --automatic-affinity
|
||||
```
|
||||
|
||||
**两道安全检查:**
|
||||
|
||||
- 启动前先算 `AkSoundEngine.dll` 的 SHA-256,不符就拒绝下断点
|
||||
- 关闭时只终止**自己创建的那个**进程,不会碰任何其它游戏会话
|
||||
|
||||
### 2. `ori_launch.py` — 普通启动器
|
||||
|
||||
不带调试器、不改内存,用来验证"**普通启动也通过**"——这才排除了"只有调试器下才成功"的可能。
|
||||
|
||||
```powershell
|
||||
python ori_launch.py --game "D:\Games\Ori and the Will of the Wisps" --label normal-patched-1
|
||||
```
|
||||
|
||||
它会先确认补丁已安装(校验**补丁后**的哈希),没装就直接退出。输出目录是相对于当前目录的
|
||||
`ori-evidence/<label>/`,不会写到别处。
|
||||
|
||||
> 依赖 `ori_debug.py` 里的常量定义,两个文件要放在同一目录。
|
||||
|
||||
### 3. `ori_audio_probe.py` — 音频输出验证
|
||||
|
||||
只读指定进程的 Windows 音频会话状态和电平,采样 3 秒取峰值。
|
||||
|
||||
```powershell
|
||||
python ori_audio_probe.py <游戏进程 PID>
|
||||
```
|
||||
|
||||
它**不录音、不访问麦克风、不改音量设置**。它证明的是"游戏确实往 Windows 音频管线里送了声音信号"
|
||||
——比"看到菜单了"强得多。
|
||||
|
||||
### 4. `probe_affinity.py` — 独立对照探针
|
||||
|
||||
在 Python 自己的短命线程上试一组掩码(`0xFFFFC` 到 `0xFFFFFFFC`)。
|
||||
|
||||
```powershell
|
||||
python probe_affinity.py
|
||||
```
|
||||
|
||||
这个脚本看着不起眼,但它是**否掉两个假设的关键对照**:如果游戏线程设不上这些掩码、
|
||||
而一个普通线程却能设上,那"核心太多""CPU 坏了""掩码越界"就都解释不通了。
|
||||
|
||||
---
|
||||
|
||||
## 使用前提
|
||||
|
||||
| 项目 | 要求 |
|
||||
| --- | --- |
|
||||
| 系统 | Windows x64 |
|
||||
| Python | 3.x(只用标准库) |
|
||||
| 权限 | 无需要求管理员,但要能启动游戏 |
|
||||
| 游戏目录 | **必须自己用 `--game` 指定**,脚本不带任何默认路径 |
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 脚本里的断点地址(`0x5B2B9`、`0x5B2D8`、`0x121F0` 等)是**针对特定 DLL 构建**的 RVA。
|
||||
换一个 DLL 版本这些地址就失效了,`ori_debug.py` 的哈希校验会拦住这种情况——**不要去掉那道校验**。
|
||||
- `--automatic-affinity` 只在进程内存里改,退出即失效,**不会写盘**。磁盘补丁请用补丁包里的安装器。
|
||||
- 这些脚本是**排查工具**,不是"一键修复"。它们观察和验证,不负责修好你的游戏。
|
||||
|
||||
---
|
||||
|
||||
## 发布说明
|
||||
|
||||
从原工作区复制过来时,改了 2 处:
|
||||
|
||||
| 文件 | 改动 |
|
||||
| --- | --- |
|
||||
| `ori_debug.py:239` | 原来硬编码了原作者的本地游戏目录,改成 `required=True` |
|
||||
| `ori_launch.py:10` | 同上 |
|
||||
|
||||
原因是这两行硬编码了原作者的本地游戏路径(具体路径已在本说明中略去)。
|
||||
改成必填参数后,使用者必须自己指定目录——
|
||||
和补丁包 `build_ori_share.py` 里"公开版不采用研究机器默认路径"的做法一致。
|
||||
改完已通过 `python -m py_compile` 语法检查。
|
||||
Reference in New Issue
Block a user