Introduction
On February 25, 2022, Valve released their long awaited portable console: the Steam Deck. Millions of consoles sold[1] and a second edition later, it is safe to say that Valve’s console is a market success. The Steam Deck runs a custom Linux distribution based on Arch called SteamOS, which includes gaming-oriented drivers and optimizations. This release managed to show for the first time that Linux is a viable mainstream gaming platform.
Gaming is an important part of the push for Linux mainstream adoption. For many people, it is the only thing still keeping them tied to Windows. Indeed, for the longest time, the gaming experience on Linux was subpar compared to Windows, requiring laborious setup and hacks, and often running badly or not at all. Why is that? And how did the situation change, to the point where a Linux console managed to find mainstream success?
In the past
Linux native compatibility
Historically, many games were available natively on Linux. Playing timeless PC classics like Doom or Counter Strike on Linux is as easy now as it was back when these games released. Even now, most engines provide Linux support, with cross-compiling available at the click of a button. And yet, for the past decade, game studios have rarely bothered with Linux compatibility. What changed?
For starters, the increased complexity of games have made cross-development a more difficult task. As games become longer and more expensive to make, choices have to be made in order to maintain profitability. Even if a game can technically be released on Linux, you’d then need to provide additional support for the platform. The market share of Linux computers being much smaller than for Windows, it makes financial sense to target the platform that the most potential customers actually use.
Adding to the complexity is the widespread use of Windows-only dependencies. The main example being DirectX, a Windows-only graphics API. As games become more and more graphically impressive, devs have moved on from the cross-platform OpenGL in order to stay competitive in terms of graphics and performance.
Luckily, the Linux community isn’t one to just sit on their hands, and will go to great lengths in order to avoid using Windows. As such, they took matters into their own hands with one goal in mind: bringing Windows software — and games — to Linux.
WINE Is Not an Emulator
WINE is a compatibility layer allowing Windows executables to be ran on the Linux kernel. Started in 1993, it provides an array of tools and hacks to run Windows programs on Linux.
As the name explains, WINE is not an emulator! Linux and Windows are both built for the same architectures, so they use the same instruction set; there is no need for hardware emulation. In that case, where do Windows and Linux differ?
For starters, they use different executable formats: Linux recognizes the ELF format, while Windows recognizes the MZ format. Similarly, they both use different formats for shared libraries: shared libraries (.so) for Linux, DLLs on Windows. On top of that, both OSes offer different APIs for things like video, audio, user input, filesystem manipulation… Speaking of filesystem, Windows and Linux have wildly different file structure: Drives vs. a single root partition, different standard paths… And of course, the biggest difference: syscalls! While both OSes generally offer similar syscalls, their implementation is completely different, and of course you can’t call a Windows syscall on Linux and vice-versa.
WINE’s goal is to provide a solution to bridge each of these factors.
Executables and dynamic libraries
As we said, Linux and Windows have different formats for executables and dynamic libraries.
On Linux, programs are ran by ld.so
. This program parses the ELF format, fetches the dynamic library dependencies, then runs the program.
Things work essentially the same way on Windows, but with different formats! Therefore, the first step to running Windows executables on
Linux is, unsurprisingly, to be able to parse the MZ and DLL files in order to execute code compiled for Windows. WINE basically acts as
a dynamic linker that can parse and run MZ executables. But of course, there is much more to do before we can run our games.
Windows APIs
Indeed, once we get past the file format, we need to actually execute our code. But is this code compatible with the Linux kernel? Well, not directly. Our code most likely contains calls to functions defined by Windows-only libraries, and these libraries then make system calls to the Windows kernel. Let’s give an example:
|
|
puts(3)
is a function defined by the Standard C Library, and therefore both
Linux and Windows provide an implementation for it (eg. glibc vs ucrt)[2]. But their implementation
may differ slightly: they may not be entirely compliant with the standard, they may include bugs depending
on the version, or they may have different implementations for undefined behaviours that programs may rely on.
Obviously, for copyright reasons WINE can’t just use the Windows DLL on Linux! Therefore, there is a need for WINE developers to reverse engineer Windows libraries, reproducing everything, from the undefined behaviours to the weird quirks.
In the case of programs that dynamically link against our C library like ucrtbase.dll
, it is enough to provide a Linux implementation of it.
But some programs are statically linked to Windows APIs, in which case this method doesn’t work out: the binary already contains
the library code, so we can’t switch it for our Linux version.
In this case, the code for our puts
function will be embedded inside the binary. puts
probably makes a call to some sort
of syscall in order to write to stdout: on Linux, it will call read
, while it will call NtReadFile
on Windows!
Luckily for us, there exists a low-level Windows API that is used to make these syscalls: ntdll.dll
.
Just like we did with ucrtbase.dll
, we can provide an implementation for ntdll.dll
whose only goal is to call
the corresponding Linux syscall instead! There’s a lot more going on to these libraries so if you want more details, I highly
suggest reading Andy Hippo’s great article [3] on the subject.
One thing the article doesn’t mention though is how Wine “fakes” a Windows filesystem. If you’ve tried messing with a game’s save files, you know that games, as most programs do, make assumptions on their environment’s file structure. For example on Windows, games typically write their save data to the user’s Documents folder. Unsurprisingly, there is no such Documents folder on Linux! WINE’s solution to this problem is called prefixes. A WINE prefix is essentially a Linux directory that emulates a typical Windows environment. Whenever a program is ran using WINE, the prefix acts as a physical Windows drive from which the program is ran, so when a program wants to read or write in a standard Windows directory, it will do so in this directory. Of course, you can still access your Linux filesystem through WINE; it will usually be mounted to the Z: drive.
But the problems don’t stop with the Windows kernel. Most games rely on third-party libraries for graphics API or video codecs. These third-party dependencies are usually only available on Windows. The main example of this is DirectX, a collection of Microsoft APIs whose use is widespread in game development. Making the dependant code work on Linux therefore requires translating these third-party APIs to a Linux-compatible equivalent. An example of that is DXVK, which is a translation layer between the Windows-only DirectX API and Vulkan, an open-source, cross-platform 3D graphics API.
While DirectX is a popular API, it’s not impossible for some games to have obscure, Windows-only dependencies. How does one make sure to cover every single possible case? Well, for a long time, WINE simply could not do this. Indeed, while most games worked more or less fine, there were many issues with performance, graphics, audio, input, and some games simply didn’t run at all. A lot of theses issues were very game-specific, making it extremely difficult to solve for an open-source project taking a generalist approach.
Yet now, a lot of these previously dysfunctional, or non-functional games, are fully functioning, running flawlessly on Linux, and sometimes even better than on Windows! What happened to make such fast progress happen in recent years?
WINE’s progress and the role of Valve
Valve’s Steam Deck, a Linux-powered gaming console
Valve plays a big part in the current state of Linux gaming. The company created Proton, a toolchain that includes WINE and other compatibility tools. As such, Valve heavily contributes to WINE. They mainly do so by funding the company that maintains WINE: Codeweavers. Their process is simple: they work on a game-per-game basis with the goal of reaching a playable state without user action, making whatever fixes they need to make on the way there. This not only allows them to focus their efforts on critical releases, but it also incidentally improves the overall ecosystem: fixing one game will certainly allow more games to run properly down the line. Whereas before a gamer would have to look up the hacks needed to make their game work, they can now just use Proton which already applies these game-specific hacks.
They are also able to work directly with game developers to make their games playable on Linux. This creates a virtuous cycle: better compatibility means more people make the jump to gaming on Linux, which leads to game studios paying more attention to Linux and going out of their way to support it.
But of course, things are still far from perfect.
Current limitations
Almost every game runs perfectly fine using Proton. But there are always exceptions. Some games run, but with some graphical, audio or performance issues that have yet to be fixed. Some of these issues can be fixed, but the fixes often require messing around with terminal commands, which is a deal breaker for mainstream audiences. Game-specific fixes are very frequent, which showcases the amount of work still left to do before Proton is able to run new releases day 1 without significant effort prior.
A much bigger problem for Proton is the cooperation of game studios. What happens if they simply do not want people to run their games on Linux? This is the case with one of the biggest game studios currently: Blizzard.
Blizzard games focus on the multiplayer experience, so the company wages all-out war against cheaters. As such, they have developed Vanguard, a Windows ring 0 anticheat software that has an eye on EVERYTHING happening on a player’s PC. Vanguard is basically a kernel driver, and you absolutely cannot run a Blizzard game without this anticheat installed and running. Of course, a Linux version is most likely never happening.
Valve has already worked towards making a lot of generic anticheat solution Proton-compatible, such as EasyAntiCheat, but we might never see Blizzard games running on Linux, through Proton or otherwise. League of Legends and Valorant are massive games, for many this the only games they actually play, so this is a pretty big setback for gaming on Linux.
Conclusion
Gaming on Linux has come a long way over the past decades, to the point where it is a viable platform almost on-par with Windows. These improvements also have an impact on the larger Linux ecosystem, as shown by the increase in Linux’s market share of desktop computers (4.44% as of July 2024)[4]. Adding to that is a growing frustration with some of Microsoft’s decisions for Windows, such as the backlash generated by their announcement of “Recall”, a feature that would regularly take “snapshots” of a session’s state, called out as a security risks by both experts and casual consumers.
If you’re reading this there’s a good chance you’ve used Linux at some point, maybe even right now. If that’s you, then I can only advise you to give gaming on Linux a try. Instead of rebooting to Windows, just install Steam with your package manager and give your favorite game a try, you might be surprised! If you’re trying to convince your friends, there are distributions that are both beginner-friendly and geared towards gaming. SteamOS is not yet recommended for use outside of the Deck, but you can give Pop_OS or Bazzite a try, both of which claim to have great performance and compatibility for Desktop Linux gaming.
However, Linux as a whole still has a long way to go before it truly becomes “mainstream” as a general Desktop platform that can compete with Microsoft’s offer. On that front, Valve is also putting in effort, with contributions to Wayland and KDE, both of which are used by the Steam Deck.
Many important non-game programs are still firmly Windows exclusive, especially professional software like the Adobe suite.
Will 2025 be the year of the Linux Desktop? Probably not, but one can dream.
Notes and references
[1] Steam Deck installed base to surpass three million during 2023 - Omdia
[2] There are many other C libraries for both Linux and Windows, like musl or msvcrt. Here’s a more in-depth comparison for Linux.
[3] How Wine works 101 - werat.dev
[4] Linux market share approaching 4.5% for first time, could hit 5% by 1Q25 (Tom’s Hardware)