Sharing game files between Linux & Windows (Dual boot)

Sharing your game library between windows and Linux is in fact possible. You have many ways of doing so. Many games are organized as small binaries coupled with large archives where the media files (models, textures, art, music, cutscenes, etc.) reside in. Rarely does the game maker put everything in the executable, it's not a very efficient choice, for you would have to recompile with every asset edit.

  1. Copying over the files you already have.

Steam is a cleverly written piece of software: it can not only download games as a whole, but also knows the hashes of the individual files. So, if you:

  • Create an NTFS share between your windows and linux environments, either using something like SAMBA (local network share) or by simply mounting the partition directly, and:
  • Create a 'games' folder inside of this, then instruct steam that there is a library there, then download a game under both OSes:
  • Steam will download the missing binaries and libraries when you run it under the other operating system. It will likely not touch the game data.
  • Steam will happily allow additional files not part of the game to be within its folder. Related to mod support and games that store save data within their folders.

Talking about save data, this is perhaps the only snafu with this. If you want to share a game between OS-es, usually, the save data is within your C:\users\$user\AppData folder on Windows, but within your /home/$user/ folder on linux.

So let's say our share is called //sgShare, and we have //sgShare/steamlib/ as a library, we would then like our games to save their data in //sgShare/saveData/

Unfortunately, there's no simple fix. Some games like to use a config file (usually an ini-formatted settings.cfg file or similar in their main folder to point to the save game folder. If it's part of the game, steam may overwrite this from time to time. Other games can use a command line parameter. Or read an environment variable. (Both of which you have control over). Or... use the unfortunate method: a hard-coded path within the executable. You would then have to do some process hacking to get it to put its data where you want.

  1. Using WINE directly.

So, technically/legally speaking, WINE is copyleft open-source software. Any modifications Valve makes to it will be shared back to the WINE community, as Valve is required to do so under the LGPL license terms they accepted when incorporating WINE code into their Steam platform. Proton code can be found in github and WINE devs periodically will port back changes. Valve also courteously directly contributes.

For the user though, things aren't ever that simple. If you want a similar configuration to Proton on Steam, you'll have to do a lot of command-line work. Valve helps its userbase by pre-configuring wine prefixes for various games, but now you'll have to do the hard work yourself. Compiling various versions of wine (32-bit? 64-bit? .NET-version? DXVK or OpenGL?), with various optional experimental extensions, modifying windows (compatibility) settings, installing C++ runtimes and other required libraries (e.g. nonfree audio/video codecs), etc etc. Fortunately, users have created their own WINE wrappers, like PlayOnLinux (actually, these existed long before Proton did). But, if the game you're looking to play isn't very popular, it's likely you'll have to figure out how to get it to run yourself. If you do, please share the settings back using WineDB or create a profile in one of the wine wrappers for it so everyone after you can do less work. The WINE site has a wealth of information available on how to run each specific game.

But, by putting in the effort, you can certainly create a wine prefix and configure it yourself. Then, you can install steam to the share and simply execute env WINEPREFIX=/root/wine/pfx/pfx27 wine //sgShare/steam/steam.exe for those games with nastier class III DRM (which won't run unless you either do some hackery or do it through steam directly), and you can use:

 env WINEPREFIX=/root/wine/pfx/pfx27 wine //sgShare/steamapps/common/$game/$game.exe` 

For those games which are more reasonably configured (i.e. games that can, if they want the protection, just lookup steam.dll and run the checks from there, I call this class II for this post), or those that have none of it (class I, my favourite kind as it's so easy to work with).

Which method is faster will depend on the game. For most popular games, the ProtonDB is likely to be tuned well: you'll have a hard time beating it with manual configuration, but it likely can be done (and VALVE can then adopt your config into proton if you share it, improving it). For more niche/indie titles where it's unlikely that any dev time is spent, there's little diffrence between plain Wine with DXVK and Proton.

Using WINE directly also doesn't solve the savegame problem. The solution from part 1 still applies.

  1. 32-bit trouble

Games are typically laggards when it comes to adoption of hardware standards that are not backwards-compatible. WINE has a split codebase. 32-bit stuff can sometimes work for certain Windows libraries, when 64-bit stuff does not. Iff so, it's likely the Proton method (1 above) does not work. You will have to install a separate 32-bit copy of Steam in a separate 32-bit wineprefix for those games that simply will not run under 64-bit WINE. If your windows steam installation is 64-bit-based, then this is an unfortunate coincidence.

An example game that used to exhibit this problem is 'Unholy Heights'. It ran well on a 32-bit WINE prefix with .NET and C++ runtime, but crashed on any 64-bit prefix and in the initial proton versions (haven't tested lately).


4. Class IV/V DRM.

So I've talked about a bit of a difference between this; you have games with none of it (can just copy them, class I), a little bit or class II (calling the steam dll), Class III (needs steam to even run), class IV (multiple separate platforms used, e.g. UBI's ANNO), or those that just go whole hog class V and (may) muck about with rootkits and kernel hacking (ye olde Starforce/Securom/DENUVO enable this, but some don't always do it; i.e. game dev choice). Well, if rootkitting and/or kernel hacking is involved, Linux is unlikely to be able to run these, even if you are copying the files. The exact locations of the various DLL function hooks or the exact hashes of windows code aren't things WINE will emulate. It can translate syscalls, it's not exactly internally identical to the NT-kernel.

Though the situation on Windows isn't all that much better. When newer versions of Windows change things, games that mess around in low level OS internals tend to no longer work, as exploited security holes are closed and so on.

  1. Anti Cheat

This is perhaps a bit more insidious if you care about a game, I.E. have time invested in a Windows based profile and switch to Linux. Anti Cheat may cause three things. It may either work with the wine config, it may not work at all (like the class V DRM), but it can also do a third thing: ban/shadowban you for supposedly 'cheating', because it detects something is 'not normal' on your system. WINE is leaky1; an application can detect it's running under WINE, and some games unfortunately for you seem to care2. Please be advised that when playing multiplayer games making sure the developer has a reasonable stance towards Linux users is caveat emptor.

For example, Blizzard games tend to not ban you for using WINE, but with Rockstar Games titles connecting to a server with anti-cheat on under WINE gets you banned from multiplayer.

Anti-Cheat is unfortunately opaque in nature, which doesn't aid in detecting new forms of rulebreakery, nor allows the player to easily see whether the game considers itself to be in a 'cheaty' state: meaning: you can't test it!


  1. Let's talk performance. Performance is a tricky business when playing WINE games, as there are many layers wherein you are able to tweak things endlessly:
  • The linux kernel.

Depending on the distribution, you may have an older (typically slower) kernel. Or you may have one with a bunch of security features (typically on commercial distributions; they can have AppArmor or SElinux enabled) which may cause slowdowns. There's also many configuration parameters. As is with all things linux, you can build your own if you want to dive into that.

  • Graphics drivers.

This comes down to desktop environment, X window // Wayland configuration, and, for NVidia, the NVidia binary driver blobs. Especially for multi-monitor users, setting it up so it even works can be challenging. Let alone optimizing.

The main problems are usually that Linux won't properly talk to the hardware. I.E. the components won't talk to eachother. You may have to choose between a GPU that's always loud and power hungry or quiet but slow. Or get watercooling or a wall between the PC and the user. Sometimes you can configure to fix things, sometimes it's NVidia's fault, and sometimes it's the Windowing subsystem, or Pulseaudio, or two components can't agree on whose responsibility it is, and so on. If you've got AMD or Intel components though, things may be a lot better. AMD's proper Linux driver tends to be just as good as its Windows counterpart, and it's actually fully open source, so no kernel mods are needed to run it. They don't tend to 'optimize' for games like NVidia does, so some of the graphical 'extra features' can oftentimes be a bit more of a drag.

  • The X window system // wayland.

Typically, this has to do with buffering and compositing. If you want a pretty compositing desktop, but also want high-performance games and have multiple monitors, you may want to give a game direct access to a framebuffer on one monitor, while running the desktop on another. I.e. change the command of the game to use 'startx' instead; give it it's own X session.

  • Wine itself

Can be either the git/compiled version, or a packaged version from your distribution.

The most impactful parameter is what graphics pipeline is used: You can compile with DXVK, run graphics through CSMT, run single-threaded, or try to run games directly on openGL mode, or use Gallium Nine (AMD/Intel only).

There's way more information out here to help you out too.

Here's another helpful post from Reddit. And another one

  • CPU core settings:

Lots of games typically use few threads. Sometimes games can be helped if you're playing on a CPU with CSMT by making sure they run on even-numbered cores only by setting the cpu flags.

If your CPU has a form of NUMA (i.e. playing on a 2-CPU workstation, or the newer Ryzen AMD CPUs, which also have multiple subnodes), you can sometimes gain performance in a less heavily threaded game by forcing it to one node worth of cores3.

  • Memory swapping / niceness.

One major thing to help running things under WINE is to have lots of memory. If you have spare, then you can adjust down the 'swappyness' of the OS. If you have more memory than you'll almost always need, i.e. you won't run out, you can just set the default value of vm.swappiness (kernel param) from 60 all the way down to 0 (zero). Linux will only swap to disk if it runs out of memory. I recommend having at least twice over the recommended amount of memory for running through WINE.

  • Input device tuning

Linux uses sensible defaults for input devices that work well for all your standard keyboards and mice. Have a high-precision and/or low latency gaming device? You may want to adjust your input lag by increasing the polling rate.

  • Audio

Sound processing by the linux kernel and respective subsystems adds lag through buffering.

A major improvement for most people is to modify the pulseaudio component and set the setting tsched=no. This turns off timer-based scheduling in favour of old-fashioned interrupt based, which is usually much more responsive. Note: WINE games may require one or the other value for tsched; some will not output audio with either. More details in this blog post. If you want to go even further and reduce latency to 10ms and below, try out RT linux kernels.

  • tmpfs

Some (poorly optimized) games may not be agressive enough with consuming your RAM (typically, if the game is older and you have lots of RAM). If the game is (much) smaller than your RAM, you can decide to mount its directory as a tmpfs system. By doing so, the entire directory is moved into RAM, which means any "disk reading" the game does is actually from RAM. After the initial time taken to read all the game's data, load times will be blisteringly fast. Make sure you back the game up first, and move it back to a normal filesystem after playing, as tmpfs systems are ephemereal. Tools exist to help you do this.


Notes

  1. "Leaky" in terms of "Is a leaky abstraction", i.e. an application running under wine can detect that it's not running on a computer running Windows OS, because WINE 'Leaks' some information: its implementation of DirectX isn't byte-for-byte identical to that of Windows. Because some game developers think that people modifying their graphics libraries to not draw certain objects is a form of 'cheating' they implement kludges to try and prevent it. Those kludges are often blunt instruments: if the directX bytes in the binary aren't exactly what they're supposed to be, the cheat detection system goes on tilt.

  2. Example: having a poorly optimized shooting multiplayer game render things behind walls. The player can realize this and mod their graphics library so that various types of surfaces are rendered transparent (by poly count or what have you) so they can 'see through walls'. Perhaps this is true, yet open source multiplayer shooters exist, and those do perfectly well with just server-side security. Caveat being that network lag is a bit harder to work around.

  3. I.e. on a 12-core 24-thread 2-node CPU, you would use the 6 virtual cores numbered 0,2,4,6,8 and 10 (usually, you can find out the actual numa distribution with numactl). You can easily do this in Linux using the CLI taskset or using a process monitor to set the affinity bits. Have more than 32 cores? Then you will have to use the more advanced/complex numactl. CPU core settings can be incorporated into a game's startup command from inside steam by running the game through numactl or taskset.