..

Detecting a PS2 Emulator: When 1*X does not equal X

This is the second entry of my series of detecting PS2 emulators. If you haven’t read it, you can find it here .


This is a pretty straightforward method. This one can be done on VU1, VU0 micro mode or VU0 macro mode. For simplicity, I will do it with VU0 macro mode, where VU0 is used as a coprocessor. That way it can be done directly on the EE CPU without dealing with VU programs.

Welcome to hell PS2 Floating Point

If you look at any multiplication instruction (MUL,MULi, etc) in the VU developer manuals, you will see this remark:

There is an operation error of 1 bit in multiplication, so the value multiplied by 1 may not be the same as the original value. By using VF[fs] as a multiplicand, the results of multiplication with 1 are guaranteed to be accurate.

It’s a little bit loaded but the gist of it is, with multiplication operations 1 * X is not guaranteed to result in X, unlike X * 1 which is.

The exact reason why a bit is lost is not known to me, whoever decides to implement software floating point for the PS2 will have to figure that out and report back :^)

Abusing it

First things first, we need to figure out a number that triggers this issue. The easiest way to do that is to brute force it. Thankfully I’ve already done that in the past. The list of the first 250 numbers (with 0.5 increments) that have the issue can be found in a gist here.

129.5 will be our target number for this detection.

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"          // Set VF1 to 129.5f
        "VADDw $vf2, $vf0, $vf0w\n" // VF2 = vf0[w] = 1
        "VMUL $vf1, $vf2, $vf1\n"   // VF1 = 1 * 129.5f
        "QMFC2 %0, $vf1\n"          // Load the number back to the EE
        : "=r"(out[0])
        : "r"(in[0]));
    return in[0] != out[0];
}

Like I said, it’s pretty straightforward. Load 1 and a special number into a register, multiply them, check the result.

Currently no emulators (PCSX2, Play!, DobieStation, hps2x64) emulate this behaviour.

The difficulty of this one is definitely a 1/5.
I’ll choose a difficult one next time.