More regular applications tend to be much easier to get working though. E.g. something like Delphi 2 or C++ Builder 1 work out of the box just fine. The biggest issue with older software is that they sometimes had 16bit installers who do not work with 64bit Windows. Windows comes with some updated stubs for some popular installers and it is possible to manually fiddle with some of the unsupported ones to run the 32bit engine directly, though something like odtvdm/winevdm that emulates 16bit code on 64bit would also work.
But in general you can get things working, depending on how well the application was written. In some cases (games, 16bit installers) you do need workarounds as they wont work out of the box, but even those workarounds are based on the 99.9% of the rest of the system preserving backwards compatibility.
Worked generally okay until the era of the Internet came along and after you quit the game, all manner of programs would crash when the network stack suddenly found itself teleported an hour or two into the future and couldn't cope.
A better example is productivity software, like Photoshop and Illustrator or Paint Shop Pro. I can get Paint Shop Pro 5, a raster graphics editor from 1998, to run on Windows 11 just fine, for example. Another is Microsoft Office, in which Microsoft goes out of its way to make sure documents created long ago will load and work fine in modern Office, and ancient versions of Office itself will happily run mostly fine on modern Windows too (eg: I run Office XP on my Windows 7 machines).
Old games were also quite often doing direct access to graphic cards outside of official APIs
And games are not business software. An old game that stops working is "too bad, move long", accounting software that stops working has real life consequences.
> The most impressive things to read on Raymond’s weblog are the stories of the incredible efforts the Windows team has made over the years to support backwards compatibility ...
> I first heard about this from one of the developers of the hit game SimCity, who told me that there was a critical bug in his application: it used memory right after freeing it, a major no-no that happened to work OK on DOS but would not work under Windows where memory that is freed is likely to be snatched up by another running application right away. The testers on the Windows team were going through various popular applications, testing them to make sure they worked OK, but SimCity kept crashing. They reported this to the Windows developers, who disassembled SimCity, stepped through it in a debugger, found the bug, and added special code that checked if SimCity was running, and if it did, ran the memory allocator in a special mode in which you could still use memory after freeing it.
> ... Raymond Chen writes, “I get particularly furious when people accuse Microsoft of maliciously breaking applications during OS upgrades. If any application failed to run on Windows 95, I took it as a personal failure. I spent many sleepless nights fixing bugs in third-party programs just so they could keep running on Windows 95.”
> A lot of developers and engineers don’t agree with this way of working. If the application did something bad, or relied on some undocumented behavior, they think, it should just break when the OS gets upgraded. The developers of the Macintosh OS at Apple have always been in this camp. It’s why so few applications from the early days of the Macintosh still work. For example, a lot of developers used to try to make their Macintosh applications run faster by copying pointers out of the jump table and calling them directly instead of using the interrupt feature of the processor like they were supposed to. Even though somewhere in Inside Macintosh, Apple’s official Bible of Macintosh programming, there was a tech note saying “you can’t do this,” they did it, and it worked, and their programs ran faster… until the next version of the OS came out and they didn’t run at all. If the company that made the application went out of business (and most of them did), well, tough luck, bubby.
---
This really gets into a philosophical difference of how software should work and who should be maintaining it. As a user, I love Raymond Chen's approach. As a developer, trying to maintain bug for bug compatibility with older versions of the code is something that scales poorly and continues to consume more and more resources as more and more bugs need that bug for bug compatibility across versions.