Post B5NZuPyZa2f5DSUAeu by drakulix@dreampi.es
 (DIR) More posts by drakulix@dreampi.es
 (DIR) Post #B585O6K3Cl4Izzo5BY by drakulix@dreampi.es
       1 likes, 0 repeats
       
       So Valve has for a while already been pushing arm64 and FEX-related stuff all over the place including in Proton. However I didn't notice, that the Proton repo literally contains build instructions for ARM64!And I happen to have a great little target device lying around, an android handheld running postmarketOS, so I decided to spend an evening on playing around with it.> It's not possible to use the resulting builds in x86 Steam running via FEX.Your funny words cannot stop me Valve.🧵 1/7
       
 (DIR) Post #B5NZuNoZcFTUVrn9nM by drakulix@dreampi.es
       0 likes, 0 repeats
       
       First some background. If you have been paying attention, playing games on arm64 isn’t exactly news. Emulators like Box86 and Box64 (and its subcomponent Box32) have existed for quite some time and have been able to run x86/x64 wine just fine, while requiring an accompanying x86/x64 root FS. The same applies to FEX, which got a lot of love from Valve in recent years.

And this is essentially how most Android apps offering “PC Emulation” worked so far and is how I am running Steam on my arm-based Handheld. Asahi Linux also has a VM involved here because of some page size shenanigans, but then also just uses FEX. Some steam-client files and resources in the FEX source code suggest, that the upcoming steam-client for arm64 will also be able to make use of FEX this way. If simply for running linux-native x86 Games or also for some Proton-based games is unclear so far.

But turns out, there is a better way. Wine can actually be compiled for arm64, which makes sense, when you consider that native Windows-on-ARM apps exist. But turns out Wine built this way can also use emulation to run x86 and x64 windows apps. For x64 this even uses the same weird arm64ec instruction set windows-on-arm uses. How similar this works exactly I don’t know, but obviously wine doesn’t use which ever proprietary emulation layer windows uses, but instead allows specially built emulators to be plugged in, e.g. FEX or Box64.

And that is also not new, hangover is a project that has done exactly this for years. But turns out the reworked wine-wow64 (amazing naming schema, thanks in part to microsoft) support only got somewhat stable with Wine 11 this year!

The neat thing about what I will call arm64ec-wine, is that you don’t need any x86/x64 linux binaries/libraries. We are not really removing a layer in this insanity that is modern computing (DirectX->Vulkan, Win32->Linux, x86->arm64), but at least more or less going from x86/x64 windows syscalls directly to arm64 linux. We are also saving on a lot of memory (which becomes relevant in this day and age).

If you want to learn more about this, I can highly recommend this 39C3 talk from @neobrain : https://media.ccc.de/v/39c3-breaking-architecture-barriers-running-x86-games-and-apps-on-arm
🧵 2/7
       
 (DIR) Post #B5NZuOdyX8aj5HqCum by drakulix@dreampi.es
       0 likes, 0 repeats
       
       So armed with this knowledge, what exactly are we trying to accomplish here?Well, we are unfortunately stuck with running Steam through FEX until Valve either publishes an official arm64 client or at least recovery images to the unreleased SteamFrame.

But wouldn’t it be neat, if we could build a custom Arm64EC proton runtime to simply select and reap the performance benefits on arm64 hosts?

So first of all I spent hours cloning and building Proton and one `make redist` later we actually have a proton runtime with arm64 binaries? That was easy, let’s drop it into `.local/share/Steam/compatibilitytools.d` and see what happens.

🧵 3/7
       
 (DIR) Post #B5NZuP6goNYmWLH8fg by drakulix@dreampi.es
       0 likes, 0 repeats
       
       I picked Celeste as a pretty easy to run and well supported game. So I selected the new runtime, click Launch and…. we get an actually error dialog from Steam. “Compatibility tool failed”, not very helpful, but expected.

Browsing through steam log files, we find this in `compat_log.txt`:

```
[2026-04-08 20:35:22] Tool 0 "proton-localbuild" has a dependency on tool 4185400.[2026-04-08 20:35:22] Tool 4185400 "" is unknown for appID 504230.
```

A quick look on steamdb.info is enough to figure out the name of our missing steam app: “Steam Linux Runtime 4.0 - Arm64”.
🧵 4/7
       
 (DIR) Post #B5NZuPT1TLQNdbiyTw by drakulix@dreampi.es
       0 likes, 0 repeats
       
       I tried for a hot minute to just change the appid to the “normal” x86 steam runtime, which I had working correctly with FEX (including host arm64 libraries), hoping it would just call into proton at some point, which would work given it would try to run an aarch64 binary on an aarch64 host.

Before I got deep enough into that rabbit hole to figure out which arm libraries were missing to start Proton I noticed two things:
1. The `proton` script file in that runtime checks for an environment variable called `PROTON_USE_ARM64` to alter its behavior quite a bit (which seems relevant).
2. 2. Given that the proton sources for arm64 are released and the steam-runtime is also open source, I should check if we can just get the arm64 runtime by building it as well. (Since the steam depot for 4185400 is blocked for “unlicensed” accounts.)

And it turns out Valve actually publishes build files: https://repo.steampowered.com/steamrt4/images/latest-public-stable/At this point it feels like I should be able to get this working somehow. If not directly in Steam, then at least through something like umu-launcher.

After extracting the runtime, I ran into the first real blocker. While Steam supports custom Proton Runtimes well, Steam Runtimes not so much. The dependency of our custom proton build onto the steam runtime is expressed like this in its `toolmanifest.vdf` config file: `"require_tool_appid" "4185400”`.

There is no variant of this parameter to point it to some folder or a way to assign an appid to our new steam runtime. We probably could convince steam somehow, that we downloaded the depot of “4185400”, but re-creating that seemed like a not so fun experience.

So instead, I removed the dependency from the proton runtime, which makes Steam start Proton directly, which obviously also doesn’t work. As a next step we change the `”commandline" "/proton %verb%"` of the toolmanifest to `proton-wrap` and provide a little script file, which give us a nice point to wrap proton in our steam-runtime and add the `PROTON_USE_ARM64` env var alongside some debug options:

```
#!/bin/bashexport PROTON_LOG=1export STEAM_LINUX_RUNTIME_LOG=1export STEAM_LINUX_RUNTIME_VERBOSE=1export PROTON_USE_ARM64=1
unset PRESSURE_VESSEL_BWRAP$HOME/.local/share/Steam/compatibilitytools.d/SteamLinuxRuntime_sniper-arm64/_v2-entry-point -- $HOME/.local/share/Steam/compatibilitytools.d/local/proton $@
```🧵 5/7
       
 (DIR) Post #B5NZuPyZa2f5DSUAeu by drakulix@dreampi.es
       0 likes, 0 repeats
       
       Okay! Now we have proton wrapped with the right steam runtime, should just work, right?!

Well… not so fast. Since Steam runs via FEX, I did actually build a whole multi arch image based on x64 with the necessary aarch64 libraries for FEX. If you actually use an aarch64 linux filesystem like most people would with a FEX RootFS, then it might actually just start working.

Unfortunately the steam-runtime does this, when pressure-vessel (Valve’s container runtime) tries to figure out, if bwrap works correctly:

`pressure-vessel-wrap[75609]: D: run: ‘srt-bwrap '--bind' '/' '/' 'true'`

Which on my system found an x64 `true` binary and thus failed execvp. EVEN THOUGH running the actual arm64 runtime with it’s arm64 binaries would have worked just fine. *sigh*

So one bwrap wrapper and `PRESSURE_VESSEL_BWRAP` env var later… and we finally launch wine. Success?… Well.. see for yourselves.🧵 6/7
       
 (DIR) Post #B5NZuQTli3cCmD55Hc by drakulix@dreampi.es
       0 likes, 0 repeats
       
       This is the point unfortunately where this little experiment comes to an end.

Looking into proton’s sources for `lsteamclient` the issue becomes obvious. It tries to load `steamclient.so` from the linux steam client to expose the steam api to the proton app.

Because our proton/wine build is an aarch64 binary, we need an aarch64 steamclient library to `dlopen`. We cannot dynamically link a library of a different architecture and `lsteamclient` seems to agree. On aarch64 builds it looks for `linuxarm64/steamclient.so` in our steam root. But our x86 steam client does only have `linux32` and `linux64` and no matter of browsing weird steam urls and even guessing names of the presumably somewhere existing arm64 client yielded anything. The Steamworks SDK already contains `libsteam_api.so` files for `linuxarm64` and even `androidarm64` of all things, but that is unfortunately the wrong library. `libsteam_api` is a library shipped in a specific version by the game, which will then load `steamclient`, which is part of the steam client and updated with it.

We can obviously disable the steam client wrapper in proton, which then leaves us to Celeste complaining “Could not load Steam!”. Makes sense.

One course of action would be to take any steam_api emulator from various dubious sources and stuff that into the wine prefix. After all something makes steam games work on android with the likes of `GameNative`, right?

This works and Celeste starts up fine, but at that point we could’ve just used Hangover to run the game in the first place. I guess one could use this runtime to conveniently run “non-steam games” with proton on aarch64, but that is about it. You lose all steam integrations, which make Proton so neat in the first place. No steam input, no networking, no achievements. And since we also have no `gameoverlayrenderer.so` to inject, no overlay and thus worse the game doesn’t even show up correctly in Steam’s game mode without something like `gamescope-fg`.


Still it was fun to dig around in steam’s guts and I hope this was somewhat informative. I skipped over a bunch of debugging of dead ends, but otherwise that’s about it!

🧵 7/7

       
 (DIR) Post #B5NZuQzfnR8UNA0Z0q by drakulix@dreampi.es
       0 likes, 0 repeats
       
       Somebody found the arm client! :neocat_hyper:https://bsky.app/profile/aagaming.me/post/3mjnka7iur22l