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

.. 2024-06-07 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

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, $vf1n" // Set VF1 to 129.5f
"VADDw $vf2, $vf0, $vf0wn" // VF2 = vf0[w] = 1
"VMUL $vf1, $vf2, $vf1n" // VF1 = 1 * 129.5f
"QMFC2 %0, $vf1n" // 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.