This is due to an overall odd strategy by the DirectX graphics team, which is to implement many of the optimization and enhancement features by Detour-ing API calls in the OS. Essentially, the Windows OS is patching itself to implement features.
Unfortunately, this is being done without core OS assistance like the AppCompat system, so it comes with similar problems to unassisted regular user-space patching. In this case, the Detours code used by DXGI is unable to support the current PAC-enabled function prologues in the current version of Windows 11 ARM64. It isn't limited to just the OP's scenario; attempting to enable Auto Super Resolution (AutoSR) on any native ARM64 program using DirectX will also currently crash in a similar manner in EnumDisplaySettings().
The full screen optimization that is mentioned also has some history. It's well intentioned to remove an entire full-screen copy per frame and increase performance/efficiency, but had some problems. When it was originally implemented in Windows 10, it broke full screen mode for some DirectX 9 apps because it made some incorrect assumptions about the window handle supplied by the application for focus tracking. But it was frustrating to deal with, because the mechanism was nearly undocumented and had no opt-out besides a manual user compatibility checkbox. It took me a couple of days of tearing apart the core windowing guts of my program to figure out what Microsoft had done and how to work around it, and it took several months for the Windows team to fix it on their end.
The Agility SDK is unrelated to what is being discussed here. It is a delivery mechanism for the Direct3D 12 runtime instead of DXGI, it is opt-in from the application side, and is done through a more stable loader stage in the core OS instead of hot-patching.
It does, however, give insight into the situation that the DirectX team is in. The in-box version of D3D12Core in the latest version of Windows 11 is SDK version 612. This can be compared against the released Agility SDK versions:
SDK version 612 is just before the 613 Agility SDK release on 3/11/2024. This means that the version of DirectX 12 they are able to ship in the main OS is a year and a half behind the latest released version.
>In this case, the Detours code used by DXGI is unable to support the current PAC-enabled function prologues in the current version of Windows 11 ARM64
Surely microsoft could avoid patching this on arm in the first place though right? As in whatever gating they use should make sure it’s not on arm.
The features in question are platform agnostic. They could temporarily disable the detouring for native ARM64 apps since the mechanism is broken on that architecture, but it's not ideal since the Snapdragon X platform is one of the main platforms for the Auto Super Resolution feature. Upgrading sequential/blit mode swap chains to flip model theoretically should be legacy, but as OP shows, it's not really as new graphics code is still being shipped without flip model support.
Note that the detouring problem is only an issue for native ARM64 programs. x64 programs running in emulation on Windows ARM64 work fine.
It seems incredible to me that Microsoft would alter the execution of programs based on the filename of the executable. For all we know, there was another game with the same filename and this game has been caught in the crossfire. This is crazy stuff.
Doing things based on exe filename is quite standard in Windows land. There's literally a registry key called "Image File Execution Options" where you can add a subkey with the name of the exe and then add values to control things like what interpreter to launch it under by default. Similar to Linux's binfmt registration, but based on filename rather than magic bytes. Very useful for attaching debuggers to specific subprocesses that you can't launch manually, as long as the process is named sufficiently uniquely.
Renaming anything (without a manifest) setup.exe will cause Windows to ask for UAC elevation. The user cannot opt-out. There are a few other hard coded strings like "install" that cause this AFAIR. You can also use its_a_setup_mr_bond.exe for example.
Funny, you are right. But it needs to be something without correct .exe metadata. "you_are_an_install_wizard_harry.exe" also triggers different behaviour/query for UAC.
I don't know if it was filename exactly, but a similar story:
> Jon Ross, who wrote the original version of SimCity for Windows 3.x, told me that he accidentally left a bug in SimCity where he read memory that he had just freed. Yep. It worked fine on Windows 3.x, because the memory never went anywhere. Here’s the amazing part: On beta versions of Windows 95, SimCity wasn’t working in testing. Microsoft tracked down the bug and added specific code to Windows 95 that looks for SimCity. If it finds SimCity running, it runs the memory allocator in a special mode that doesn’t free memory right away. That’s the kind of obsession with backward compatibility that made people willing to upgrade to Windows 95.
There is a ton of this in the app compatibility support. It comes from the era in which it would not be expected for a vendor to patch a program they already shipped. So, you know, they enable the hacks that keep SimCity working if they notice you're running SimCity. And the SimCity CD-Rom would never see an update.
>It comes from the era in which it would not be expected for a vendor to patch a program they already shipped
This is still the case today. An operating system breaking apps is not desirable behavior. Not all apps are still in development, the work may have been contacted out, the development studio may have been bankrupted, the source code may have been lost, etc. Either you add a compatibility hack to the OS or you drop support for that app.
> Either you add a compatibility hack to the OS or you drop support for that app.
It isn't really a binary choice like this in real life. This really depends on the specifics of what the breakage is. The best way is to not break the caller's expectation to begin with.
Anyway, my point is that patching on the vendor side is way more common than it would be in the days before internet updates were common.
It's still common with modern operating systems. I think the bias may just be from historical blog posts talking about old events than newer ones. The developers adding these are under NDA so they aren't going to be sharing with the world what they are doing.
You are right that it's not a binary choice, they are others like maintaining tech debt forever or paying out of pocket to upgrade people's apps. But it's common for those to not be viable options and operating systems need to keep evolving forward.
The reality that Microsoft discovered decades ago is that "Don't break the callers expectation" doesn't work at all because the callers didn't read the manual, and had blatantly incorrect expectations!.
Windows 1.0 apps that properly follow all the documented caveats still work, often without anything more than the compatibility hacks to emulate "Windows 3" or similar.
But even back in the 90s, Microsoft found that devs would do things that the documentation explicitly said would break things, and ship it as is.
Things like copy/pasting the code the manual said, in big bold letters, DO NOT DO THIS
Most popular computer games in the 90s did things like "try to allocate all virtual memory and crash if that's possible" and "turn off interrupts globally" despite being written against virtual driver systems that were meant to cooperatively manage interrupts!
Don't think that I'm naïve about this. In the 2000s I was on the Windows team. I didn't work on app compat but sometimes when I was bored in the office I would read the app compat shims.
The most memorable example of a bad behavior that I recall was a 90s video game. It used the area beyond the stack pointer as some kind of bonus storage area. It worked by coincidence because in 9x, every kernel32 call trapped directly into the kernel and would swap your stack. Suddenly NT's Win32 support sometimes involves bigger user space wrappers to ntdll. FindFirstFile was one. NT's kernel32 needed a lot of stack space to call NtQueryDirectoryFile and copy it over to a WIN32_FIND_DATA. The game's data structures got clobbered. So there was a shim that would swap the stack pointer before doing this.
Even still ... There's something in this thread that I think is missing about all this. You don't need to litter your code base with "if (!strcmp(exename, "SIMCITY.EXE"))"... I did see examples here and there of that sort of thing in the Windows code base, but mostly, that is not how this stuff actually works.
Further, I don't think the Win3.1 era is a fair comparison at all. There was no protection between processes then and it was standard practice to bypass the operating system. By Windows 95, this was starting to be less and less the case.
They had to do these hacks for things like Wing Commander, Simcity, even Microsoft Office itself needed massive hacks (to the point that a significant portion of the profanity in the Windows 2000 source leaks is explicitly calling the Office team a bunch of idiots and losers who don't know what they are doing)
>For all we know, there was another game with the same filename and this game has been caught in the crossfire
Microsoft has been doing this for 30 years and I am unaware of even one case of "program got wrong compatibility hacks"! It would be unlikely to be reported well so that's not great evidence, but it's been a massive success.
In your list these are executables that change their own behaviour based on how they are called, whereas in the OP it's the OS changing code based on the name of an application.
In all but the last example these are the programs themselves having multiple names. There are literally multiple names on the file system that point to the same executable. So `ping`, `ping4`, and `ping6` are all the same program but it checks $0 to see which name it was invoked as in order to change it’s own behavior.
This is entirely different than when DirectX behaves differently for a program named foo.exe and another one called bar.exe.
AppArmor (and for that matter SELinux) are a different thing yet again. Here the goal is not to fix bugs or incompatibilities, but to add extra security. Similar perhaps, but not nearly as intrusive. Neither involve runtime patching, which is the most salient feature of this crash report.
Vulkan even made this kind of targeted hack into a first class citizen by letting the application specify the name and version number of itself and its engine during initialization. There's no reason for that besides enabling per-app driver shenanigans.
Vulkan layers being system-wide feels like it's specifically asking for this class of bug. If you're lucky every system-wide layer ships with PDBs... but they probably don't. I've yet to find a bug in a layer, at least, but I've wasted time ruling it out.
System-wide Vulkan layers definitely cause chaos. I remember unit tests for our renderer crashing on some machines and not on other nearly identical ones. The culprit was a Vulkan layer installed by a video capture software. It had a hard limit of 16 Vulkan instances that it could keep track of before overflowing an array and crashing. But our tests would recreate the Vulkan environment from scratch for each test, which is fairly unusual for a Vulkan application, to be fair.
In the end, we added the list of loaded Vulkan layers to the diagnostic log of our software to help customer support spot fishy ones.
I've personally run into stuff like this on Windows but I want to emphasize that the vast majority of developers won't run into these problems. It's basically the equivalent of finding a compiler bug - yes, you might, but usually the problems you hit are not caused by the compiler or OS, as a general thing.
Are OS or compiler problems more common now than they were 10 years ago? Possibly, but I wouldn't be surprised if they're less common, either.
I have run into driver bugs multiple times though, perhaps more often than OS bugs. And that's really frustrating.
If you haven't run into a compiler bug you're not trying hard enough. If you support multiple compilers or your company has their own compiler team/patches it'll definitely happen.
Also happens when some pedantic people decide to turn on -Wall -Wextra -Werror because they think it's safer; now any incorrect warning bug is a fatal compiler bug.
Comes with the general perception of OS vs Software failure responsibility:
- On Windows, this is Window's fault
- On Apple OS, this is the application's fault
- On Linux, this is the user's fault
Of course exception do apply, but as far as I know MacOS I have noticed some instance of application patching by the OS itself (although I haven't dug deeper, I can confirm that the application did have a slight change of behavior even before applying vendor patches, and I doubt it was anything done by the anti-malware protection)
I never understand these drive-by comments. It's not like developing on/for the competition is any easier or less convoluted. The author is debugging a cross-language (both managed and native), cross-architecture video game with a variety of third-party libraries.
Turns out that the Windows graphics stack is complicated (mainly because it needs to support a variety of closed-source programs that never saw maintenance after initial release), so compatibility layers meant to optimise for certain programs (an easy optimisation, frankly) accidentally caught the author's program in the master list, too.
There are people who actually try to implement better APIs. (We can quibble over effectiveness all day long. Sadly, it looks like a losing battle.) This is the only way to find them.
The title is a bit clickbait but nice article ;) This is widespread in API-level software, from OSes to GPU drivers. I'm not sure how documented this is but you can find interesting stuff by renaming your exe to Quake, or FIFA, or Minecraft or whatever.
Back in 2001, ATI got in some hot water after it was revealed that they intentionally blurred all textures (used a lower resolution mipmap) if you were running Quake 3 Arena. Changing all strings from "Quake" to "Quack" (including renaming the executable) disabled the degraded mipmaps, and improved the graphics (and reduced framerates).
Meanwhile today, graphics driver tweaks for specific games has become a regular feature and is advertised in the driver release notes (and I guess that's one reason why graphics drivers have become so massively big).
I can't remember where I heard this from but I remember a talk from some guy from the DirectX team and he said that so many games use completely illegal and unsupported/weird API options and calls.
He said that's what 99% of the game optimizations are. Putting stuff in place to fix broken API stuff.
This is true. I am a graphics driver developer and part of my job is to debug rendering issues in games and we often encounter spec violations in the game. Especially so in the era of DirectX12/Vulkan explicit APIs which shift the responsibilities to the developer. Most common culprits are missing resource barriers (image transitions in Vulkan) and uninitialized resources (color/depth resources for the most part require explicit initialization). The thing about those issues is that they are likely to work on one vendor's GPUs, the one that the game developer is using, but break more or less catastrophically on another vendor's GPU.
Also it's not easy to get them fixed in the game, because of the realities of engine update cycles and things like console certification process. Unless you report the issue several months before release, there is a slim chance you will get a fix in the game.
So game companies release broken code and it somehow becomes the world's responsibility to fix it... Sometimes I wonder if simply allowing these things to break for once would be a good thing for the industry.
Its also not surprising to anyone who spent time reading Raymond Chen's The Old New Thing blog posts back in the day, a lot of them were about these rather absurd hoops Microsoft was always jumping through to increase backward and forward compatibility with these sorts of tricks.
It may have lead to an unfortunate situation for this developer in this one very niche corner case, but overall it has been wildly beneficial for users over the years (decades even) to have most software Just Work regardless of how deprecated the underlying APIs they were built on are now.
Sounds pretty click-baity but if a company put the name of my software on an opaque list that ships with the OS that makes my software behave differently than I expect it to and didn't even TELL ME about it I'd be way WAY more pissed than this guy is.
You are a unique person. You have detailedknowlage of graphics assembly and windows api. And you have the creativity to write games. Which need the side ability of drawing.
This insane amount of knowlage is rare. And the ability to write about it is also not common.
Not only that, he also does sysadmin for the game's infrastructure and administrates the drama-prone community. And whatever else happens behind the scenes. Honestly one of the greatest developers I've seen.
> It only happens when the program is called SS14.Loader.exe
This isn't something only Microsoft does but also graphics drivers, etc. TBH sometimes i consider using using GUIDs in exe names at build time to avoid such lists :-P.
I would like to disable these compatibility lists on Windows and to actually be able to report any issues and crashes to devs. But this might be a very Linux mindset thing for me to want.
The Linux kernel contains biiiig piles of hacks for individual motherboards, systems, devices. It's like this at every level everywhere, unfortunately. I mean, it was only very recently that your 64 core CPU stopped pretending to be an 8086 during initial boot
Unlike Microsoft's hacks, these hacks do not include self-modifying code as I understand. I hope code with "detours" (a beautiful French-sounding euphemism for monkey-patching) is not accepted in Linux kernel and libraries.
Such things exist in GPU drivers, instead. Closed-source Nvidia ones probably have lots of it. Fixing the bad usage of graphics APIs in client binaries is the industry standard.
Pedantically, Linux does also self-modify for some of this stuff, but it's more constrained, jumps are rewritten to avoid branches for performance reasons: https://docs.kernel.org/staging/static-keys.html
> it was only very recently that your 64 core CPU stopped pretending to be an 8086 during initial boot
Still Does[1]:
>> After a RESET or INIT, the processor is operating in 16-bit real mode. Normally within real mode, the
code-segment base-address is formed by shifting the CS-selector value left four bits. The base address
is then added to the value in EIP to form the physical address into memory. As a result, the processor
can only address the first 1 Mbyte of memory when in real mode.
The UEFI hands off the boot CPU to the OS loader (GRUB/NTLoader etc) in long mode. But when the OS brings up any CPU that is not the initial bootstrap CPU via the interprocessor interrupt... that CPU comes up in 16bit* real mode.
* This is a lie... note how the quote references EIP and not IP? That's because it's actually booting up in Unreal mode. Hence the initial instruction run is actually at 0xFFFF_FFF0 IIRC
As I remember, for 10 or 20 years on x86 execution starts at 32-bit address like 0xffff_0000:0000, not 0xffff:0000 which was used in 8086, am I wrong? Stumbled upon this when tried to disassemble BIOS.
Man I gotta give this person props, that is a LOT of effort to get your game to run native ARM64 on Windows. How many people out there are trying to game on ARM64 Windows devices?
Space Station 14 is the same though but it might use some 3d stuff for rendering based on the comments in the blog about issues with OpenGL (or might just use OpenGL's 2D stuff) I know it has some 3d-ish things for visibility shadows but those might just be done in 2D, and from what I've tried SS14 (and SS13) is a 2D game.
OpenGL doesn't really have "2D stuff" (at least not in any version from the last 20 years). It's all a programmable 3D pipeline, which you can do 2D in by just not using the Z coordinate in the shader. However, doing 2D graphics like this tends to be simple enough code that you're less likely to trigger any driver or performance issues.
> I’d rather just spend the brain power on ditching OpenGL, rather than trying to continue working with this broken API
Is "this broken API" responsible for a library monkey patching?
Also, we are lucky that linux libraries generally don't use such hacks. That's really bad style of programming. Also legacy games probably would run just fine with a bitblt if they were running fine on older software.
I understand and aprechiate the writeup, I just don't see why the conclusion is to delay the release until the detour bug is fixed, when it's easy to work around it once it has been understood?
I suspect that the fix to the detour bug will be unevenly distributed as well, so avoiding it would help user experience regardless.
Microsoft has done a lot of bad releases since they eliminated engineering in test, but it seems a little bit above and beyond to expect them to specifically add an arm executable to a list of executables to patch with x86(64) code and then not confirm that it does what it's supposed to do.
The current situation is derpy, but understandable. The patching system was ported with the rest of the arm stuff, and the executable for arm matches the name list so it makes sense to do the patch, but nobody ported the patch data. Whoops.
What, Microsoft is still doing this?!? Back in the day Windows 95 developers went the extra mile to ensure compatibility with SimCity and a bunch of other games:
This is due to an overall odd strategy by the DirectX graphics team, which is to implement many of the optimization and enhancement features by Detour-ing API calls in the OS. Essentially, the Windows OS is patching itself to implement features.
Unfortunately, this is being done without core OS assistance like the AppCompat system, so it comes with similar problems to unassisted regular user-space patching. In this case, the Detours code used by DXGI is unable to support the current PAC-enabled function prologues in the current version of Windows 11 ARM64. It isn't limited to just the OP's scenario; attempting to enable Auto Super Resolution (AutoSR) on any native ARM64 program using DirectX will also currently crash in a similar manner in EnumDisplaySettings().
The full screen optimization that is mentioned also has some history. It's well intentioned to remove an entire full-screen copy per frame and increase performance/efficiency, but had some problems. When it was originally implemented in Windows 10, it broke full screen mode for some DirectX 9 apps because it made some incorrect assumptions about the window handle supplied by the application for focus tracking. But it was frustrating to deal with, because the mechanism was nearly undocumented and had no opt-out besides a manual user compatibility checkbox. It took me a couple of days of tearing apart the core windowing guts of my program to figure out what Microsoft had done and how to work around it, and it took several months for the Windows team to fix it on their end.
That strategy is described here, and comes from game developers wanting DirectX to be untied from OS versions as it used to be.
https://devblogs.microsoft.com/directx/gettingstarted-dx12ag...
The Agility SDK is unrelated to what is being discussed here. It is a delivery mechanism for the Direct3D 12 runtime instead of DXGI, it is opt-in from the application side, and is done through a more stable loader stage in the core OS instead of hot-patching.
It does, however, give insight into the situation that the DirectX team is in. The in-box version of D3D12Core in the latest version of Windows 11 is SDK version 612. This can be compared against the released Agility SDK versions:
https://devblogs.microsoft.com/directx/gettingstarted-dx12ag...
SDK version 612 is just before the 613 Agility SDK release on 3/11/2024. This means that the version of DirectX 12 they are able to ship in the main OS is a year and a half behind the latest released version.
I thought that it also included updated DXGI components.
No, the Agility SDK only includes updated D3D12 core and debug layer components.
https://microsoft.github.io/DirectX-Specs/d3d/D3D12Redistrib...
I see, thanks.
For my DirectX hobby coding, what is in the box even if a bit oldie is good enough, so I got my info about the Agility SDK wrong.
>In this case, the Detours code used by DXGI is unable to support the current PAC-enabled function prologues in the current version of Windows 11 ARM64
Surely microsoft could avoid patching this on arm in the first place though right? As in whatever gating they use should make sure it’s not on arm.
The features in question are platform agnostic. They could temporarily disable the detouring for native ARM64 apps since the mechanism is broken on that architecture, but it's not ideal since the Snapdragon X platform is one of the main platforms for the Auto Super Resolution feature. Upgrading sequential/blit mode swap chains to flip model theoretically should be legacy, but as OP shows, it's not really as new graphics code is still being shipped without flip model support.
Note that the detouring problem is only an issue for native ARM64 programs. x64 programs running in emulation on Windows ARM64 work fine.
It seems incredible to me that Microsoft would alter the execution of programs based on the filename of the executable. For all we know, there was another game with the same filename and this game has been caught in the crossfire. This is crazy stuff.
Doing things based on exe filename is quite standard in Windows land. There's literally a registry key called "Image File Execution Options" where you can add a subkey with the name of the exe and then add values to control things like what interpreter to launch it under by default. Similar to Linux's binfmt registration, but based on filename rather than magic bytes. Very useful for attaching debuggers to specific subprocesses that you can't launch manually, as long as the process is named sufficiently uniquely.
https://techcommunity.microsoft.com/blog/askperf/two-minute-...
Renaming anything (without a manifest) setup.exe will cause Windows to ask for UAC elevation. The user cannot opt-out. There are a few other hard coded strings like "install" that cause this AFAIR. You can also use its_a_setup_mr_bond.exe for example.
Funny, you are right. But it needs to be something without correct .exe metadata. "you_are_an_install_wizard_harry.exe" also triggers different behaviour/query for UAC.
I don't know if it was filename exactly, but a similar story:
> Jon Ross, who wrote the original version of SimCity for Windows 3.x, told me that he accidentally left a bug in SimCity where he read memory that he had just freed. Yep. It worked fine on Windows 3.x, because the memory never went anywhere. Here’s the amazing part: On beta versions of Windows 95, SimCity wasn’t working in testing. Microsoft tracked down the bug and added specific code to Windows 95 that looks for SimCity. If it finds SimCity running, it runs the memory allocator in a special mode that doesn’t free memory right away. That’s the kind of obsession with backward compatibility that made people willing to upgrade to Windows 95.
https://www.joelonsoftware.com/2000/05/24/strategy-letter-ii...
It's not limited to Microsoft. Nvidia and AMD Windows drivers also do the same. Even mesa has a few lists of program-specific flags:
https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/uti...
Quite a lot of this in proton, except it's by steam appid: https://github.com/ValveSoftware/Proton/blob/proton_10.0/pro...
That's fine because app ids are unique.
There is a ton of this in the app compatibility support. It comes from the era in which it would not be expected for a vendor to patch a program they already shipped. So, you know, they enable the hacks that keep SimCity working if they notice you're running SimCity. And the SimCity CD-Rom would never see an update.
>It comes from the era in which it would not be expected for a vendor to patch a program they already shipped
This is still the case today. An operating system breaking apps is not desirable behavior. Not all apps are still in development, the work may have been contacted out, the development studio may have been bankrupted, the source code may have been lost, etc. Either you add a compatibility hack to the OS or you drop support for that app.
> Either you add a compatibility hack to the OS or you drop support for that app.
It isn't really a binary choice like this in real life. This really depends on the specifics of what the breakage is. The best way is to not break the caller's expectation to begin with.
Anyway, my point is that patching on the vendor side is way more common than it would be in the days before internet updates were common.
It's still common with modern operating systems. I think the bias may just be from historical blog posts talking about old events than newer ones. The developers adding these are under NDA so they aren't going to be sharing with the world what they are doing.
You are right that it's not a binary choice, they are others like maintaining tech debt forever or paying out of pocket to upgrade people's apps. But it's common for those to not be viable options and operating systems need to keep evolving forward.
The reality that Microsoft discovered decades ago is that "Don't break the callers expectation" doesn't work at all because the callers didn't read the manual, and had blatantly incorrect expectations!.
Windows 1.0 apps that properly follow all the documented caveats still work, often without anything more than the compatibility hacks to emulate "Windows 3" or similar.
But even back in the 90s, Microsoft found that devs would do things that the documentation explicitly said would break things, and ship it as is.
Things like copy/pasting the code the manual said, in big bold letters, DO NOT DO THIS
Most popular computer games in the 90s did things like "try to allocate all virtual memory and crash if that's possible" and "turn off interrupts globally" despite being written against virtual driver systems that were meant to cooperatively manage interrupts!
>https://ptgmedia.pearsoncmg.com/images/9780321440303/samplec...
"How to ensure your Program does not run on Windows 95"
Don't think that I'm naïve about this. In the 2000s I was on the Windows team. I didn't work on app compat but sometimes when I was bored in the office I would read the app compat shims.
The most memorable example of a bad behavior that I recall was a 90s video game. It used the area beyond the stack pointer as some kind of bonus storage area. It worked by coincidence because in 9x, every kernel32 call trapped directly into the kernel and would swap your stack. Suddenly NT's Win32 support sometimes involves bigger user space wrappers to ntdll. FindFirstFile was one. NT's kernel32 needed a lot of stack space to call NtQueryDirectoryFile and copy it over to a WIN32_FIND_DATA. The game's data structures got clobbered. So there was a shim that would swap the stack pointer before doing this.
Even still ... There's something in this thread that I think is missing about all this. You don't need to litter your code base with "if (!strcmp(exename, "SIMCITY.EXE"))"... I did see examples here and there of that sort of thing in the Windows code base, but mostly, that is not how this stuff actually works.
Further, I don't think the Win3.1 era is a fair comparison at all. There was no protection between processes then and it was standard practice to bypass the operating system. By Windows 95, this was starting to be less and less the case.
This is common across all platforms that have a backwards compatibility story
>It seems incredible to me that Microsoft would alter the execution of programs based on the filename of the executable.
This has been one of the primary ways microsoft has managed compatibility for decades.
Windows 95 had hacks based on filenames of games to make sure popular stuff worked on Windows.
Raymond Chen has an entire book! (And a free chapter about exactly this!)
https://ptgmedia.pearsoncmg.com/images/9780321440303/samplec...
They had to do these hacks for things like Wing Commander, Simcity, even Microsoft Office itself needed massive hacks (to the point that a significant portion of the profanity in the Windows 2000 source leaks is explicitly calling the Office team a bunch of idiots and losers who don't know what they are doing)
>For all we know, there was another game with the same filename and this game has been caught in the crossfire
Microsoft has been doing this for 30 years and I am unaware of even one case of "program got wrong compatibility hacks"! It would be unlikely to be reported well so that's not great evidence, but it's been a massive success.
Changing execution behaviour based on filename is common in Linux environments too. Some examples:
1. BusyBox is a single executable that executes different commands based on which symlink was used to call it
2. Bash puts itself into compatibility mode if invoked as "sh"
3. "ping" can be invoked as "ping4" or "ping6"
4. Some of git's subcommands are symlinks back to the main executable
5. Clang switches to C++ mode if invoked as "clang++"
6. AppArmor profiles activate on file paths
Your examples are interested, but not comparable.
In your list these are executables that change their own behaviour based on how they are called, whereas in the OP it's the OS changing code based on the name of an application.
But 1-5 is the executable making decisions based on it's command name, not the OS changing behavior.
In all but the last example these are the programs themselves having multiple names. There are literally multiple names on the file system that point to the same executable. So `ping`, `ping4`, and `ping6` are all the same program but it checks $0 to see which name it was invoked as in order to change it’s own behavior.
This is entirely different than when DirectX behaves differently for a program named foo.exe and another one called bar.exe.
AppArmor (and for that matter SELinux) are a different thing yet again. Here the goal is not to fix bugs or incompatibilities, but to add extra security. Similar perhaps, but not nearly as intrusive. Neither involve runtime patching, which is the most salient feature of this crash report.
> Of course it’s the goddamn filename.
Cue in a few dozen oldschool game developers thinking, right from the first paragraph, "did he name his game game.exe"?
He should try quack.exe
When I read about stuff like this it makes me feel lucky never having had to do Windows development.
No worries, the same experience can be done with OpenGL or Vulkan, depending on the specific OS flavour and OEM drivers.
Vulkan even made this kind of targeted hack into a first class citizen by letting the application specify the name and version number of itself and its engine during initialization. There's no reason for that besides enabling per-app driver shenanigans.
Vulkan layers being system-wide feels like it's specifically asking for this class of bug. If you're lucky every system-wide layer ships with PDBs... but they probably don't. I've yet to find a bug in a layer, at least, but I've wasted time ruling it out.
System-wide Vulkan layers definitely cause chaos. I remember unit tests for our renderer crashing on some machines and not on other nearly identical ones. The culprit was a Vulkan layer installed by a video capture software. It had a hard limit of 16 Vulkan instances that it could keep track of before overflowing an array and crashing. But our tests would recreate the Vulkan environment from scratch for each test, which is fairly unusual for a Vulkan application, to be fair.
In the end, we added the list of loaded Vulkan layers to the diagnostic log of our software to help customer support spot fishy ones.
I've personally run into stuff like this on Windows but I want to emphasize that the vast majority of developers won't run into these problems. It's basically the equivalent of finding a compiler bug - yes, you might, but usually the problems you hit are not caused by the compiler or OS, as a general thing.
Are OS or compiler problems more common now than they were 10 years ago? Possibly, but I wouldn't be surprised if they're less common, either.
I have run into driver bugs multiple times though, perhaps more often than OS bugs. And that's really frustrating.
If you haven't run into a compiler bug you're not trying hard enough. If you support multiple compilers or your company has their own compiler team/patches it'll definitely happen.
Also happens when some pedantic people decide to turn on -Wall -Wextra -Werror because they think it's safer; now any incorrect warning bug is a fatal compiler bug.
Each operating system has such layers of cruft, they're sometimes just harder to debug.
Comes with the general perception of OS vs Software failure responsibility:
- On Windows, this is Window's fault - On Apple OS, this is the application's fault - On Linux, this is the user's fault
Of course exception do apply, but as far as I know MacOS I have noticed some instance of application patching by the OS itself (although I haven't dug deeper, I can confirm that the application did have a slight change of behavior even before applying vendor patches, and I doubt it was anything done by the anti-malware protection)
I never understand these drive-by comments. It's not like developing on/for the competition is any easier or less convoluted. The author is debugging a cross-language (both managed and native), cross-architecture video game with a variety of third-party libraries.
Turns out that the Windows graphics stack is complicated (mainly because it needs to support a variety of closed-source programs that never saw maintenance after initial release), so compatibility layers meant to optimise for certain programs (an easy optimisation, frankly) accidentally caught the author's program in the master list, too.
There are people who actually try to implement better APIs. (We can quibble over effectiveness all day long. Sadly, it looks like a losing battle.) This is the only way to find them.
EDIT: typo
The title is a bit clickbait but nice article ;) This is widespread in API-level software, from OSes to GPU drivers. I'm not sure how documented this is but you can find interesting stuff by renaming your exe to Quake, or FIFA, or Minecraft or whatever.
Back in 2001, ATI got in some hot water after it was revealed that they intentionally blurred all textures (used a lower resolution mipmap) if you were running Quake 3 Arena. Changing all strings from "Quake" to "Quack" (including renaming the executable) disabled the degraded mipmaps, and improved the graphics (and reduced framerates).
https://web.archive.org/web/20190728022442/https://techrepor...
Meanwhile today, graphics driver tweaks for specific games has become a regular feature and is advertised in the driver release notes (and I guess that's one reason why graphics drivers have become so massively big).
I can't remember where I heard this from but I remember a talk from some guy from the DirectX team and he said that so many games use completely illegal and unsupported/weird API options and calls.
He said that's what 99% of the game optimizations are. Putting stuff in place to fix broken API stuff.
This is true. I am a graphics driver developer and part of my job is to debug rendering issues in games and we often encounter spec violations in the game. Especially so in the era of DirectX12/Vulkan explicit APIs which shift the responsibilities to the developer. Most common culprits are missing resource barriers (image transitions in Vulkan) and uninitialized resources (color/depth resources for the most part require explicit initialization). The thing about those issues is that they are likely to work on one vendor's GPUs, the one that the game developer is using, but break more or less catastrophically on another vendor's GPU.
Also it's not easy to get them fixed in the game, because of the realities of engine update cycles and things like console certification process. Unless you report the issue several months before release, there is a slim chance you will get a fix in the game.
So game companies release broken code and it somehow becomes the world's responsibility to fix it... Sometimes I wonder if simply allowing these things to break for once would be a good thing for the industry.
Its also not surprising to anyone who spent time reading Raymond Chen's The Old New Thing blog posts back in the day, a lot of them were about these rather absurd hoops Microsoft was always jumping through to increase backward and forward compatibility with these sorts of tricks.
It may have lead to an unfortunate situation for this developer in this one very niche corner case, but overall it has been wildly beneficial for users over the years (decades even) to have most software Just Work regardless of how deprecated the underlying APIs they were built on are now.
Sounds pretty click-baity but if a company put the name of my software on an opaque list that ships with the OS that makes my software behave differently than I expect it to and didn't even TELL ME about it I'd be way WAY more pissed than this guy is.
Drivers do this to every single videogame. And it is good, otherwise those game would not run in every consumer 3d card.
I'm sure the driver devs have at least some interaction with the game devs when they do this.
TrickNvidiaDriversForPerformance_javaw.exe.minecraft.exe
Hey, that was the Intel driver! ;)
You are a unique person. You have detailedknowlage of graphics assembly and windows api. And you have the creativity to write games. Which need the side ability of drawing.
This insane amount of knowlage is rare. And the ability to write about it is also not common.
You are very talented and hard working person.
I am in awe.
Not only that, he also does sysadmin for the game's infrastructure and administrates the drama-prone community. And whatever else happens behind the scenes. Honestly one of the greatest developers I've seen.
FYI: pjb goes by she/her.
Thanks, I'd forgotten that. Can't edit the comment anymore.
> It only happens when the program is called SS14.Loader.exe
This isn't something only Microsoft does but also graphics drivers, etc. TBH sometimes i consider using using GUIDs in exe names at build time to avoid such lists :-P.
It goes both ways! https://devblogs.microsoft.com/oldnewthing/20040211-00/?p=40...
I would like to disable these compatibility lists on Windows and to actually be able to report any issues and crashes to devs. But this might be a very Linux mindset thing for me to want.
The Linux kernel contains biiiig piles of hacks for individual motherboards, systems, devices. It's like this at every level everywhere, unfortunately. I mean, it was only very recently that your 64 core CPU stopped pretending to be an 8086 during initial boot
Unlike Microsoft's hacks, these hacks do not include self-modifying code as I understand. I hope code with "detours" (a beautiful French-sounding euphemism for monkey-patching) is not accepted in Linux kernel and libraries.
Such things exist in GPU drivers, instead. Closed-source Nvidia ones probably have lots of it. Fixing the bad usage of graphics APIs in client binaries is the industry standard.
Pedantically, Linux does also self-modify for some of this stuff, but it's more constrained, jumps are rewritten to avoid branches for performance reasons: https://docs.kernel.org/staging/static-keys.html
That's an interesting trick.
> it was only very recently that your 64 core CPU stopped pretending to be an 8086 during initial boot
Still Does[1]:
>> After a RESET or INIT, the processor is operating in 16-bit real mode. Normally within real mode, the code-segment base-address is formed by shifting the CS-selector value left four bits. The base address is then added to the value in EIP to form the physical address into memory. As a result, the processor can only address the first 1 Mbyte of memory when in real mode.
The UEFI hands off the boot CPU to the OS loader (GRUB/NTLoader etc) in long mode. But when the OS brings up any CPU that is not the initial bootstrap CPU via the interprocessor interrupt... that CPU comes up in 16bit* real mode.
[1]: https://docs.amd.com/v/u/en-US/40332-PUB_4.08 (the intel one says the same thing last I checked, Intel has discussed changing this... but AFAIK has not yet)
* This is a lie... note how the quote references EIP and not IP? That's because it's actually booting up in Unreal mode. Hence the initial instruction run is actually at 0xFFFF_FFF0 IIRC
https://en.wikipedia.org/wiki/Unreal_mode
As I remember, for 10 or 20 years on x86 execution starts at 32-bit address like 0xffff_0000:0000, not 0xffff:0000 which was used in 8086, am I wrong? Stumbled upon this when tried to disassemble BIOS.
You are correct, I need to edit my post because they both boot up in unreal mode. The 32bit Segment limit is an unreal mode thing.
Man I gotta give this person props, that is a LOT of effort to get your game to run native ARM64 on Windows. How many people out there are trying to game on ARM64 Windows devices?
We get a lot of people wanting to run the game on ChromeOS school laptops, which is also ARM-based.
I don't think that would contribute to much demand to run it on Windows ARM64.
I played Silksong recently on my Surface Pro 11, it worked fine. 2D game with minimal graphics requirements so it's a different case, though.
Space Station 14 is the same though but it might use some 3d stuff for rendering based on the comments in the blog about issues with OpenGL (or might just use OpenGL's 2D stuff) I know it has some 3d-ish things for visibility shadows but those might just be done in 2D, and from what I've tried SS14 (and SS13) is a 2D game.
OpenGL doesn't really have "2D stuff" (at least not in any version from the last 20 years). It's all a programmable 3D pipeline, which you can do 2D in by just not using the Z coordinate in the shader. However, doing 2D graphics like this tends to be simple enough code that you're less likely to trigger any driver or performance issues.
> I’d rather just spend the brain power on ditching OpenGL, rather than trying to continue working with this broken API
Is "this broken API" responsible for a library monkey patching?
Also, we are lucky that linux libraries generally don't use such hacks. That's really bad style of programming. Also legacy games probably would run just fine with a bitblt if they were running fine on older software.
Knowing the author it can only mean OpenGL/EGL and similar.
They ranted/vented about OpenGL sucking and DirectX being best thing since butter on toast was invented.
> It only happens when the program is called SS14.Loader.exe.
Could you have a SS14.Loader.arm.exe for arm? Then the exe name wouldn't match and it woildn't trigger the crash?
You could. The fix is easy. The problem was the painfully long debugging in order to find the root cause of the issue.
I understand and aprechiate the writeup, I just don't see why the conclusion is to delay the release until the detour bug is fixed, when it's easy to work around it once it has been understood?
I suspect that the fix to the detour bug will be unevenly distributed as well, so avoiding it would help user experience regardless.
Until microsoft ships the .arm.exe name in the list. pretty much a ticking time bomb.
Microsoft has done a lot of bad releases since they eliminated engineering in test, but it seems a little bit above and beyond to expect them to specifically add an arm executable to a list of executables to patch with x86(64) code and then not confirm that it does what it's supposed to do.
The current situation is derpy, but understandable. The patching system was ported with the rest of the arm stuff, and the executable for arm matches the name list so it makes sense to do the patch, but nobody ported the patch data. Whoops.
Y'know it would be nice if stuff would log it somewhere when it applies patches like this.
What, Microsoft is still doing this?!? Back in the day Windows 95 developers went the extra mile to ensure compatibility with SimCity and a bunch of other games:
https://news.ycombinator.com/item?id=34138028
If you’re on a list for an app you haven’t released and you didn’t know, what kinds of spyware do you have on your machine? Oh, windows…
Read the article; the list is based on EXE filenames. They developer was trying to port an existing application from AMD64 to ARM64.
The author of the post indicated that they are releasing an update to an existing game, which we can presume has the same executable filename.