这是关于检测 PS2 模拟器系列的第二篇文章。若未阅读过第一篇,可点击这里查看。
这是一个相当直接的方法,可在 VU1、VU0 微模式或 VU0 宏模式下进行。为简便起见,以 VU0 宏模式为例,将 VU0 用作协处理器,这样可直接在 EE CPU 上进行操作,无需处理 VU 程序。
欢迎来到~地狱~PS2 浮点数
在 VU 开发者手册中的任何乘法指令(如 MUL、MULi 等)中,会有这样的备注:
乘法存在 1 位操作误差,所以乘以 1 的值可能与原始值不同。通过使用 VF[fs]作为被乘数,乘以 1 的结果可保证准确。
其大致意思是,与 X 1不同,乘法操作 1 X不能保证结果为 X。
具体丢失 1 位的原因我不清楚,任何为 PS2 实现软件浮点数的人都需要弄清楚并反馈。
利用此特性
首先要确定触发此问题的数字,最简单的方法是暴力破解。之前已完成此操作,前 250 个有此问题的数字列表(以 0.5 递增)可在这里的 gist中找到。本次检测的目标数字为 129.5。
int isVUMulErrorPresent()
{
float in[4] __aligned(16) = {129.5f,0.0f,0.0f,0.0f};
float out[4] __aligned(16) = {0.0f,0.0f,0.0f,0.0f};
asm __volatile__(
"QMTC2 %1, $vf1\n" // 将 VF1 设置为 129.5f
"VADDw $vf2, $vf0, $vf0w\n" // VF2 = vf0[w] = 1
"VMUL $vf1, $vf2, $vf1\n" // VF1 = 1 * 129.5f
"QMFC2 %0, $vf1\n" // 将数字加载回 EE
: "=r"(out[0])
: "r"(in[0]));
return in[0]!= out[0];
}
如所述,此方法相当直接,将 1 和一个特殊数字加载到寄存器中,进行乘法操作,检查结果。目前没有模拟器(PCSX2、Play!、DobieStation、hps2x64)模拟此行为。此方法的难度定为 1/5,下次将选择更难的方法。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。