Fans of a 2013 Japanese soccer game tracked down a bizarre floating point bug
dolphin-emu.org
dolphin-emu.org
> AArch64 nmadd equation is -(A * C) - B [...] Having an add instruction subtract is a curious decision from ARM [...] AArch64's nmsub equation is (A * C) - B, which isn't negated at all. Yet AArch64's msub is negated, for whatever reason, so we used that instead. We've learned not to question it.
Re-arrange those equations a bit, and you get:
msub: (b - ac)
nmadd: -(b + ac)
nmsub: -(b - ac)
And suddenly, it all makes sense :-) FMADD: addend + ( op1 * op2)
FMSUB: addend + (-op1 * op2)
FNMADD: -addend + (-op1 * op2)
FNMSUB: -addend + ( op1 * op2)
which is to say that in all three cases the result is the output of a fused multiply-add; the difference is just whether (a) the addend and (b) op1 are negated before feeding them in.IEEE 754-2008 only defines that you have to provide a fusedMultiplyAdd() operation, so it's up to the CPU architecture whether folding in the free negations is something they want to provide, and if so, where exactly the negation is done.
Though apparently the Dolphin folks disagree either way and interpret nmadd as (nm)add, rather than n(madd).
Never mind the hyphens, what do they think a "Negated fused Multiply" is?
“We've learned not to question it.”
Truly a veteran developer crew! Congrats on the amazing fix.
Too bad PowerPC fell by the wayside.
The fused multiply-add instructions (FMA) have been used for the first time in 1990, in the first IBM POWER CPUs.
Some years later FMA instructions have been included in many other CPUs from various vendors, the main exceptions being the Intel/AMD CPUs (where the first CPU with FMA was AMD Bulldozer in 2011, 21 years later than POWER) and the ARM CPUs, which also added FMA quite late, but before the introduction of the 64-bit variant.
The problem is that both Intel and ARM have chosen to define FMA instructions that differ between themselves and also from POWER, in the position of the negation signs.
With real numbers of unlimited precision, that would not have mattered, because the negation is commutative with the multiplication and distributive over addition.
However with floating-point numbers these mathematical properties do not hold exactly, which is what the developers of the Dolphin emulator have discovered now.
This is a general rule for any floating-point computation, that changing a formula using associativity/distributivity/commutativity is not guaranteed to produce the same results.
Sometimes the differences are too small to matter, but in this case they made a game unplayable in the emulator, so they had to emulate the exact formula used in the original game, without trying to reduce the execution time by reducing the number of emulated instructions (emulating the original formula requires 2 instructions, while they initially optimized the code to use a single instruction but that computed a formula with the negation sign moved in another place).
That's not really something that unlimited precision would avoid, but also not something that "real" arithmetic suffers from since real arithmetic doesn't have -0 and +0 as distinguishable concepts.
Normally testing the sign of a floating-point number that is the result of a multiplication or division should always be preceded by a test for zero, unless you intentionally want to take different paths for zeros with different signs.
I've emailed the mods to suggest a change.
The few times i tried to play games with keyboard or gamepad(logitech) it kinda was frustrating !
*Otherwise - good job on a great project !
I'd have to dig up the old code but I'm fairly sure some of them rely on an operating system (Nintendo IOS, unrelated to both Cisco's IOS and Apple's iOS) running on the co-processor (nicknamed "Starlet"). Dolphin doesn't emulate that part at all because IOS exposes a high-level interface that can just be emulated instead. Works amazingly well for games, but will probably trip our protections.
I think a lot of software companies would do like what you did. Where they would check for some sort of thing that should be there, or not, or too much of something. But the emulator would or would not have it. I think in many cases it would be things like checking to see if 512k of memory was available, when the real box would have 128k. That was usually for things like copiers I think?
[1] https://dolphin-emu.org/blog/2017/02/01/dolphin-progress-rep...
What makes you think we did it for any of those reasons? And how does us abusing hardware bugs make video game preservation any harder?
This was not for a commercial game, this was for an entry point to load your own software on a locked down video game console.
And back then people were selling our (free!) software and we added those protections to make sure we could show a "you have been scammed if you paid for this" screen that couldn't be removed. Unfortunately that also meant breaking our loader from running in emulators, but that didn't matter at all: Those could just directly launch actual .elf files anyway and didn't need the detour through the homebrew channel.
The code (minus those protections) for the Homebrew Channel is also available as open source these days.
For research purpose, of course.
https://archive.org/advancedsearch.php?q=*&fl%5B%5D=identifi...
I vote for keeping it as is.
But now, my first guess was actually that this was about some much debated football match and that the floating point bug was present in some software used by the referees when reviewing replays.