posts

Getting Crimson Desert to Run on Arch Linux

On this page

I am a recent father. If you are one too, you already know what that means for gaming: it means nothing. There is no gaming. There is a baby, there is work, there is the crib, and there is a version of you from two years ago who had opinions about frame pacing.

But every once in a while there is a window. The baby is asleep by midnight, the house is quiet, and between 00:00 and 02:00 there are two hours that belong to nobody. Last night I decided, exceptionally, to spend them playing Crimson Desert, which had just finished downloading its 117 GB onto my Steam library.

I’ll be honest about how those two hours went. The first chunk was Steam compiling shaders, a thing I hate to death and will keep hating until the day it goes away. The rest was a crash. The game got fixed at 01:59. I had one minute of Pywel on screen, admired it, and turned the machine off. That’s life.

Crimson Desert

This is the write-up of that hour and a half, in the same spirit as the Heroes III post: what broke, how each cause was found, which tests were wrong, and the exact thing that worked on my setup (Arch, Omarchy, Hyprland, an RTX 4060 laptop with 8 GB of VRAM and 16 GB of RAM). If you only want the recipe, it’s at the end.

The setup

Crimson Desert Enhanced installed on Steam, on a second NVMe library, running through GE-Proton10-34. NVIDIA driver 610.57.04. Steam client on the public beta channel, which turns out to matter.

The first launch at 00:22 stopped at “Processing shader cache” and waited for me to answer a dialog. I answered it, walked away, and came back to a game that was, in Steam’s own words, “Running”. Then it wasn’t.

Problem one: the game crashes four minutes in

At 01:14 the game actually started. It loaded data, switched the language to Brazilian Portuguese, started the client thread, and died at 01:19 with no window and no dialog. Steam quietly went back to “Play”.

The game’s own launcher log, which lives inside the prefix, was the first useful thing:

.../compatdata/3321460/pfx/drive_c/users/steamuser/AppData/Local/Pearl Abyss/log/

It ends with “[Crash] sending dump…” and a memory summary. Next to it, in Pearl Abyss/DumpCache, there is a Sentry event with the exception:

ExceptionCode: STATUS_ACCESS_VIOLATION (c0000005)
ExceptionAddress: 0000000143B3C044

A null pointer read inside CrimsonDesert.exe itself. The game is loaded at 0x140000000, so the address is game code, not Wine and not a driver.

The saved graphics options in the same folder showed preset Ultra and DLSS Frame Generation set to generate two frames. On a laptop 4060 with 8 GB of VRAM, with the game reporting 70% of system memory in use at the moment of the crash, that looked like the obvious suspect. Frame generation under Proton goes through the driver’s DLSS-G library, and it is the first thing every forum tells you to turn off. I took the bait.

Problem two: the game refuses to launch at all

Before touching the options I had switched the compatibility tool to GE-Proton11-5, on the theory that newer is better. From that moment on, clicking Play got stuck at “Downloading content” and never created a process.

Steam’s content_log.txt had the reason in one line:

Failed installing AppID 4183110 (Invalid platform)

AppID 4183110 is Steam Linux Runtime 4.0. GE-Proton11 declares it as a dependency in its toolmanifest.vdf:

"require_tool_appid" "4183110"

GE-Proton10 depends on 1628350, which is Runtime 3.0 (sniper), and that one is installed and fine. So the game was not crashing anymore. It was never starting, because Steam could not install a runtime it insisted did not exist for my platform.

This is a known bug. It is open on the steam-for-linux tracker since May, with people reporting it on stable and beta clients, native and Flatpak, NVIDIA and AMD, as recently as two weeks ago. Nobody has a reliable fix. On my machine, Steam had actually installed Runtime 4.0 on August 23, then removed its only depot the same minute and has refused to reinstall it ever since. I tried the two workarounds people mention, removing the GE-Proton folders and restarting, and wiping the appinfo cache. Neither did anything.

The consequence is bigger than one GE version. Proton Experimental and Proton Hotfix also require Runtime 4.0. On this machine, right now, the only Proton that can launch anything is GE-Proton10-34, from March. Keep that in mind, it comes back.

Test one: disable frame generation (wrong)

Back on GE-Proton10-34, I renamed the graphics options file so the game would recreate its defaults. It recreated them as Ultra with frame generation on. That is what the game picks for a 4060, apparently. Same crash, same address, at 01:32.

So I edited the file by hand, set the preset to High and deleted the frame generation block, and added a launch option that tells DXVK-NVAPI to report an Ampere GPU, which makes NVIDIA’s Streamline believe frame generation is unsupported and never load it:

DXVK_NVAPI_GPU_ARCH=GA100 PROTON_LOG=1 %command%

The Proton log confirmed the override took effect. The game crashed anyway, at 01:41, same address, same null read at offset 0x30. Frame generation was never the cause. I confess I had been sure.

Test two: verify the files (also wrong, but cheap)

Every launcher log has this line before the crash:

[DATA_ERROR] File path not found: material/dist/postprocesswaterexit_cd.material

A missing material file right before a render crash is suspicious enough to spend five minutes on. Steam’s file verification ran from 01:43 to 01:48 and downloaded nothing. The install was intact. The line is just something the game says.

What the Proton log actually said

With PROTON_LOG=1 you get ~/steam-3321460.log, and with the game’s thread names in it, the crash finally had a shape:

warn:threadname Thread renamed to "ClientRunThread"
warn:vkd3d-proton:d3d12_command_list_process_enhanced_barrier_texture: NumPlanes == 0 promotes to 1 plane.
warn:seh:dispatch_exception backtrace: --- Exception 0xc0000005.
trace:seh:dispatch_exception code=c0000005 (EXCEPTION_ACCESS_VIOLATION) addr=0000000143B3C044

The thread that died was RenderThread, on the first frame after entering the world, right after a burst of vkd3d-proton warnings. So: game code, in the renderer, immediately after asking Direct3D 12 for something.

That is when the March date started to bother me. Crimson Desert was on build 2.02.00, compiled on September 10. GE-Proton10-34 shipped a vkd3d-proton from March 23. And there was a precedent: in April, patch 1.04 of this same game started crashing on launch under every Proton because it used D3D12 interfaces that vkd3d-proton had not implemented yet. A game that asks the D3D12 layer for a feature, gets a null back, and dereferences it at offset 0x30 is exactly what an access violation in game code on the render thread looks like.

The normal answer would be “use a newer Proton”. Which, on this machine, was impossible. See problem two.

The fix: transplant vkd3d-proton

Proton Experimental had updated itself at 01:22 to a September 10 build. It cannot launch anything here, but its files are sitting on disk, and vkd3d-proton is just two DLLs. So I took them from Experimental and put them into GE-Proton10-34, and into the game’s prefix as well, keeping the originals next to them:

G=~/.local/share/Steam/compatibilitytools.d/GE-Proton10-34/files/lib/wine/vkd3d-proton
E="/mnt/steam/SteamLibrary/steamapps/common/Proton - Experimental/files/lib/wine/vkd3d-proton"
S=/mnt/steam/SteamLibrary/steamapps/compatdata/3321460/pfx/drive_c/windows/system32

for a in x86_64-windows i386-windows; do
  for f in d3d12.dll d3d12core.dll; do
    cp -n "$G/$a/$f" "$G/$a/$f.ge-orig"
    cp "$E/$a/$f" "$G/$a/$f"
  done
done
for f in d3d12.dll d3d12core.dll; do
  cp -n "$S/$f" "$S/$f.ge-orig"
  cp "$E/x86_64-windows/$f" "$S/$f"
done

One detail that cost me a wrong attempt: there is also a d3d12.dll in files/lib/wine/x86_64-windows/, and that one is Wine’s built-in stub, forty kilobytes. The real vkd3d-proton is the five megabyte d3d12core.dll under files/lib/wine/vkd3d-proton/. Copy the wrong pair and nothing changes.

At 01:57 the files were in place. At 01:59 the game was running, with the world on screen and Kliff standing there waiting for me. I looked at it for about a minute. Then I closed it, because the window was over and there is a small person who wakes up at six regardless of what I did at two.

The recipe

If you are on Arch with a Steam client that refuses to install Steam Linux Runtime 4.0, and Crimson Desert crashes right after entering the world on GE-Proton10:

  1. Confirm the symptom. In ~/.local/share/Steam/logs/content_log.txt, look for Failed installing AppID 4183110 (Invalid platform). If it is there, every Proton 11 and Proton Experimental is dead for you until Valve fixes it. Stay on GE-Proton10-34.
  2. Add PROTON_LOG=1 %command% to the launch options and reproduce the crash once. In ~/steam-3321460.log, check that the exception happens on RenderThread at an address starting with 0x14.
  3. Make sure Proton Experimental is installed and updated, even though it cannot run. You only want its files.
  4. Copy d3d12.dll and d3d12core.dll from Experimental’s files/lib/wine/vkd3d-proton/ into the same path inside GE-Proton10-34, and into compatdata/3321460/pfx/drive_c/windows/system32/. Back up the originals.
  5. Play. Or look at it for a minute, whatever your life allows.

Two caveats. The game uses Denuvo, and a community guide reports that swapping these DLLs counts as a hardware activation, so do not also bounce between Proton versions in the same day. And frame generation on an 8 GB laptop card is still a bad idea, even if it was innocent this time. I left it off.

What I take from this

The crash address never changed across four attempts. That should have been the clue from the start: a crash that ignores every graphics setting you throw at it is not a graphics setting. When the address is inside the game’s own module, on the render thread, and the game is six months newer than your D3D12 layer, the D3D12 layer is the suspect, and the way to test it is to swap the layer, not the settings.

The other thing is smaller. The launcher log was inside the prefix the whole time, in a folder named after the publisher, telling me in Korean exactly when and where it died. Look there first. It is faster than the Proton log and it does not need a relaunch.

Anyway. The game runs, the shaders are compiled, and the next window opens whenever it opens.

Apparently this “Getting [insert game title] to Run on Arch Linux” thing is turning into a series, because every game I want to play in my two hours of the night decides to make me spend those two hours earning it. I did not plan it. I’ll keep writing them anyway.