Files

诊断脚本说明

这 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 语法检查。