This reminds me of another story with FPU involved. I was a game developer once. We were making a game that consistently triggered assertion failures related to FPU calculations, but only on a single PC in the whole office. The game was explicitly setting FPU precision to 32 bits at the start to make all calculations more consistent. However, on that particular PC, there was a fancy hand writing input software that injected its DLL into every process. As you've probably already guessed, that DLL did FPU mode reset to the default in the event handling loop (i.e., main thread). I had to shift FPU mode setting code from process initialization to the event handling loop to be able to deal with the damage that third party DLLs could inflict.
This reminds me of an old bug in simdjson - any usage of it breaks std::unordered_map in unrelated parts of the code due to an unintentional modification of FPU flags: https://github.com/simdjson/simdjson/issues/169
It was publicly released in 2013 and you can enable it with -vr in args IIRC. Not sure if it would work with modern VR hardware since steamvr wasn't a thing back then.
I don’t know about the beta, but there’s an excellent HL2 VR conversion mod you can play today. It feels just right and got me to play HL2 again after all these years.
>a big innovation of HL2 was the extensive use of a real physics engine. The door and the guard are both physical objects, both have momentum, they impart an impulse on each other, and although the door hinge is frictionless, the guard's boots have some amount of friction with the floor.
It's been a while since I've played HL2 but this isn't exactly how I remember it. While a lot of things were physics objects I thought the doors would just smoothly rotate towards their target position without any physics at all. You can't bump them shut with another physics object for instance.
You can't move them (apart from the opening and closing animation), but they can move other objects that are in their way. Both need to be physics objects for that to work, even though the door is just kinematic (i.e. it won't react to forces applied to it). Although if I remember correctly, they are not even fully kinematic. I think you could get them stuck halfway closed by cramming something in the door frame that would get the whole thing jammed.
Just did some quick testing - the doors definitely have physics and can get stuck on objects and can impart forces. But unimpeded yes, they smoothly open/close.
I stuck a tire in a door frame and tried to close it, the tire emitted a bunch of dust clouds as the two objects fought before the door finally ejected the tire at high speed.
> The door and the guard are both physical objects, both have momentum, they impart an impulse on each other
I wonder if the term "impulse" here has any connection to the various impulse commands available in the source engine. I remember using "impulse 101" and causing havok in the opening plaza area. Spawning zombies on the roofs, sending them after the combine, etc.
The impulse console command originates from Quake, the Half-Life 1 engine (GoldSrc[0]), was based on the Quake engine, and the Half-Life 2 engine (Source), was based on GoldSrc.
In quake, the impulse commands were used mostly to switch weapons[1].
I'm not really sure about the naming though, why choose the word "impulse".
I have encountered at least one bug at $job which was tracked down to x87 instructions. Our "production" build is deployed on embedded ARM CPUs while we have test builds compiled for x86 (32-bit) and x86_64 (different subsets of functionality). Anyway, the bug only showed up in the 32-bit x86 build. The same code worked fine in production and in the 64-bit test builds.
It turned out to be an x87 bug where a piece of code was actually computing the wrong answer!. Logically following the code would make you think that the particular failure in question would never happen - and yet it did. That was quite a rabbit-hole to go into to figure out.
Nothing to do with the actual story which was very interesting, but I just find it so absurd that in 2025 we're still splitting posts into paragraphs because of some weird historical character limit on tweets.
And some of those posts are way longer than tweets used to be, but we're still splitting them for no real reason than to make them tweets instead of blog posts?
It seems to be typical - some calculations break while switching from x87 to SSE. The same happened with TF2 too - it's ammo calculation code worked slightly differently on GNU/Linux build of the game, because it was built with SSE instructions (Windows version still used x87).
I think the only visible effect from that was the Engineer's metal, giving +40 or +41 from a small box, depending on the server platform (all classes technically do have metal, but the others can't use it).
It was always fun to play on a new server and check what OS it was running that way, too. :-)
I expect this is / was a very common problem for people porting 32-bit game code to newer compilers. I work on a fairly old codebase that forces use of x87 for a handful of code paths that don't work correctly otherwise. GCC will use default to x87 if you do an i386 compile, but will default to SSE for 64-bit builds, so you have to be careful there too.
I used to work at the studio responsible for the Driver games, and few years back we dug out the code for the original PC Driver and tried to compile it again, mostly for fun - we had to change a lot of hand written assembly code to make it build, and discovered that yeah, the game worked but none of the game replays worked - and it was for that exact same reason, better/different floating point precision issues. Really fun thing to investigate though.
It's a goal of mine to get Valve using Nix. (I hope our in-progress Windows support would make this especially compelling.)
One advantage of this is that it will become very easy to not only build the original source of the game, but also build it with the original toolchain and dependencies, the toolchains for those dependencies, etc. etc., all the way down.
Hopefully something like that at your finger trips would have made finding the root cause of this bug a good bit easier!
Maybe I'm not seeing it. How would the bug finding be easier here? Seems like the same setup. They could compile with recent tools, and they already had the compiled version with old tools (hosted on Steam).
I wonder how on earth stuff like x86->ARM translation works so well if games break even after switching from x87 registers to SSE preserving all the logic otherwise...
I think x87 fpu is the only 'weird' floating point units left. I think if you stick with 64-bit double precision floats or 32-bit single precision floats, where the registers are also 64 or 32 bits, all the modern stuff behaves the same. x87 is just weird because registers are 80-bits ... the idea was to have more accurate results from more precision, but it ends up weird because if you run out of registers and have to spill to memory, you typically lose precision.
Edit: since this post was second chanced, I can add on that some of the pre-PC consoles have weird floats too. If they had floats at all. Lots of fun for emulation developers. Even fun for contemporaneous game developers... PilotWings on the SNES comes with different revision accelerator chips and the demo only works properly on the early revision chips (but I think? the later revision chips have more accurate math). The PS2 FPU has weirdness around NaN, Infinity, very large numbers, and denormalized numbers. Etc.
It's probably because you have to have weird precision issues where the numbers are calculated ever so slightly differently, and some other effect like a guard being slightly too close and getting clipped by a door where that difference matters.
I debugged some software synthesizer code a while back (like 20 years or so now I think of it) where a build of it on one platform failed because of a precision bug. I can't remember the details, but there was a lot of "works fine on my machine" type discussion around it. Anyway it relied on a crude simulation of an RC circuit reaching very close to 0 asymptotically to trigger a state change, but on something like 64-bit Intel with a specific processor it never quite made it low enough to trip the comparison because of something to do with not flushing denormals.
From an electronic standpoint, making it simulate "it's high enough" as being about 0.7 and " it's low enough" being about 0.01 was far closer to the instrument they were trying to simulate, and making it massively imprecise like that got it going on everything.
I remember there was a huge scandal where Intel's compiler, icc (considered to be the fastest for quite a while back when) defaulted to x87 when it detected an AMD CPU instead of SSE, giving AMD cpu's a handicap (incidentally, that's the reason why x87 used to be much faster on AMD for a while).
A lot of games were shipped with icc, so my guess is they'd work just fine as they were tested with both.
Rosetta uses software emulation for x87 floating point. That's slow, but in practice that doesn't matter much. Mac software never had a reason to use x87 FP, every Intel Mac had at least SSE3 support.
>But on the SSE version, a whole bunch of tiny precisions are very slightly different, and a combination of the friction on the floor and the mass of the objects means the guard still rotates from the collision, but now he rotates very slightly less far.
I'll make one that's the opposite (your post must be at least two paragraphs and an LLM is going to judge your text to make sure it's not lorum Ipsum) if you'll help me get users.
g7r|3 months ago
This reminds me of another story with FPU involved. I was a game developer once. We were making a game that consistently triggered assertion failures related to FPU calculations, but only on a single PC in the whole office. The game was explicitly setting FPU precision to 32 bits at the start to make all calculations more consistent. However, on that particular PC, there was a fancy hand writing input software that injected its DLL into every process. As you've probably already guessed, that DLL did FPU mode reset to the default in the event handling loop (i.e., main thread). I had to shift FPU mode setting code from process initialization to the event handling loop to be able to deal with the damage that third party DLLs could inflict.
djmips|3 months ago
stevefan1999|3 months ago
powerclue|3 months ago
zX41ZdbW|3 months ago
mattgreenrocks|3 months ago
Wowfunhappy|3 months ago
I'd also love to play Portal, actually. They say it makes you sick, but to my knowledge I'm immune from VR motion sickness, so worth a try...
Shekelphile|3 months ago
aranelsurion|3 months ago
davepdotorg|3 months ago
HelloUsername|3 months ago
https://www.youtube.com/watch?v=dBIh06_bmq0
shellwizard|3 months ago
FrostKiwi|3 months ago
[1] https://mastodon.gamedev.place/@TomF/115589894339657055
lomase|3 months ago
why_at|3 months ago
It's been a while since I've played HL2 but this isn't exactly how I remember it. While a lot of things were physics objects I thought the doors would just smoothly rotate towards their target position without any physics at all. You can't bump them shut with another physics object for instance.
sigmoid10|3 months ago
accrual|3 months ago
I stuck a tire in a door frame and tried to close it, the tire emitted a bunch of dust clouds as the two objects fought before the door finally ejected the tire at high speed.
accrual|3 months ago
I wonder if the term "impulse" here has any connection to the various impulse commands available in the source engine. I remember using "impulse 101" and causing havok in the opening plaza area. Spawning zombies on the roofs, sending them after the combine, etc.
https://developer.valvesoftware.com/wiki/Impulse
WatchDog|3 months ago
In quake, the impulse commands were used mostly to switch weapons[1]. I'm not really sure about the naming though, why choose the word "impulse".
[0]: https://en.wikipedia.org/wiki/GoldSrc.
[1]: https://github.com/id-Software/Quake/blob/0023db327bc1db0006...
ThrowawayR2|3 months ago
DarmokJalad1701|3 months ago
It turned out to be an x87 bug where a piece of code was actually computing the wrong answer!. Logically following the code would make you think that the particular failure in question would never happen - and yet it did. That was quite a rabbit-hole to go into to figure out.
brokenmachine|3 months ago
And some of those posts are way longer than tweets used to be, but we're still splitting them for no real reason than to make them tweets instead of blog posts?
01HNNWZ0MV43FF|3 months ago
Panzerschrek|3 months ago
arcfour|3 months ago
It was always fun to play on a new server and check what OS it was running that way, too. :-)
MBCook|3 months ago
HaroldCindy|3 months ago
gambiting|3 months ago
Ericson2314|3 months ago
One advantage of this is that it will become very easy to not only build the original source of the game, but also build it with the original toolchain and dependencies, the toolchains for those dependencies, etc. etc., all the way down.
Hopefully something like that at your finger trips would have made finding the root cause of this bug a good bit easier!
throwaway314155|3 months ago
They’re using Arch Linux. Let’s call it a win and move on lol.
zenethian|3 months ago
bpye|3 months ago
What is the current story for using Nix to build Windows binaries?
adastra22|3 months ago
voidUpdate|3 months ago
guidopallemans|3 months ago
edit: wayback machine doesn't work, though !ais does:
https://archive.is/ng0ke
dewey|3 months ago
nasretdinov|3 months ago
toast0|3 months ago
Edit: since this post was second chanced, I can add on that some of the pre-PC consoles have weird floats too. If they had floats at all. Lots of fun for emulation developers. Even fun for contemporaneous game developers... PilotWings on the SNES comes with different revision accelerator chips and the demo only works properly on the early revision chips (but I think? the later revision chips have more accurate math). The PS2 FPU has weirdness around NaN, Infinity, very large numbers, and denormalized numbers. Etc.
ErroneousBosh|3 months ago
I debugged some software synthesizer code a while back (like 20 years or so now I think of it) where a build of it on one platform failed because of a precision bug. I can't remember the details, but there was a lot of "works fine on my machine" type discussion around it. Anyway it relied on a crude simulation of an RC circuit reaching very close to 0 asymptotically to trigger a state change, but on something like 64-bit Intel with a specific processor it never quite made it low enough to trip the comparison because of something to do with not flushing denormals.
From an electronic standpoint, making it simulate "it's high enough" as being about 0.7 and " it's low enough" being about 0.01 was far closer to the instrument they were trying to simulate, and making it massively imprecise like that got it going on everything.
torginus|3 months ago
A lot of games were shipped with icc, so my guess is they'd work just fine as they were tested with both.
pdw|3 months ago
dev0p|3 months ago
Insanity. The values were just right. Just wow.
YouAreWRONGtoo|3 months ago
[deleted]
netsharc|3 months ago
bathtub365|3 months ago
tiborsaas|3 months ago
viraptor|3 months ago
fragmede|3 months ago