4.1 KiB
诊断脚本说明
这 4 个脚本是 2026-09-16 那轮定位用到的全部工具,用 Python 标准库写的,不需要装任何第三方包。
对应的技术报告见 ../文章/奥日2崩溃研究报告.md 第 5 节(动态实验设计及结果)。
每个脚本做什么
1. ori_debug.py — 核心诊断器
用 Windows 调试接口启动自己的游戏子进程(不是附加到别的进程,也不装系统钩子), 在音频线程初始化附近的指令上打临时断点(INT3),记录寄存器、参数、返回值和目标线程自己的 LastError。
这是抓到"SetThreadAffinityMask 返回 0、错误码 87"那个关键证据的工具。
# 只校验 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 — 普通启动器
不带调试器、不改内存,用来验证"普通启动也通过"——这才排除了"只有调试器下才成功"的可能。
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 秒取峰值。
python ori_audio_probe.py <游戏进程 PID>
它不录音、不访问麦克风、不改音量设置。它证明的是"游戏确实往 Windows 音频管线里送了声音信号" ——比"看到菜单了"强得多。
4. probe_affinity.py — 独立对照探针
在 Python 自己的短命线程上试一组掩码(0xFFFFC 到 0xFFFFFFFC)。
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 语法检查。