Skip to content
Snippets Groups Projects
Commit d2730ab1 authored by Simon McVittie's avatar Simon McVittie
Browse files

Document the Steam compatibility tool interface


This is based on testing with Steam beta 1623823138 and older versions,
and is not necessarily authoritative.

Signed-off-by: default avatarSimon McVittie <smcv@collabora.com>
parent 60943b8a
No related branches found
No related tags found
1 merge request!324Document the Steam compatibility tool interface
Pipeline #14336 passed
# Steam compatibility tool interface
## Compatibility tool declaration
Compatibility tools are declared by a file `compatibilitytool.vdf`,
which is a [VDF](https://developer.valvesoftware.com/wiki/KeyValues)
text file in this format:
```
"compatibilitytools"
{
"compat tools"
{
"my_compat_tool"
{
"install_path" "."
"display_name" "My Compatibility Tool"
"from_oslist" "windows"
"to_oslist" "linux"
}
}
}
```
`compat tools` can presumably contain one or more compatibility tools,
each identified by a unique name, in this case `my_compat_tool`.
Each compatibility tool can have these fields:
`install_path`
: Installation directory containing `toolmanifest.vdf` and other
necessary files, for example
`/path/to/steamapps/common/Proton - Experimental` for Proton
`display_name`
: Name to display in the Steam user interface
`from_oslist`
: Operating system(s?) whose executables can be run by this
compatibility tool, for example `windows` for Proton
`to_oslist`
: Operating system(s?) that can run this compatibility tool,
for example `linux` for Proton
For the compatibility tools provided by Steam itself, such as
Steam Linux Runtime and Proton, the equivalent of this information is
downloaded out-of-band and stored in `~/.steam/root/appcache/appinfo.vdf`,
so the depot downloaded into the Steam library will not contain this file.
Third-party compatibility tools can be installed in various locations
such as `~/.steam/root/compatibilitytools.d`.
Each subdirectory of `compatibilitytools.d` that contains
`compatibilitytool.vdf` is assumed to be a compatibility tool. The
installation path should be `"."` in this case.
Alternatively, the manifest can be placed directly in
`compatibilitytools.d` with the `install_path` set to the relative or
absolute path to the tool's installation directory.
## Tool manifest
Each compatibility tool has a *tool manifest*, `toolmanifest.vdf`, which
is a [VDF](https://developer.valvesoftware.com/wiki/KeyValues) text
file with one top-level entry, `manifest`.
`manifest` has the following known fields:
`version`
: The version number of the file format. The current version is `2`.
The default is `1`.
`commandline`
: The command-line for the entry point.
`require_tool_appid`
: If set, this compatibility tool needs to be wrapped in another
compatibility tool, specified by its numeric Steam app ID. For
example, Proton 5.13 needs to be wrapped by "Steam Linux Runtime -
soldier", so it sets this field to `1391110`.
`unlisted`
: If `1`, this compatibility tool will not be shown to users as an option for
running games. For example, until Steam is able to distinguish between
Steam Runtime 1 'scout' and Steam Runtime 2 'soldier' as distinct
platforms, it is not useful to run ordinary Steam games under 'soldier',
due to it being incompatible with 'scout'.
`use_sessions`
: If set to `1`, older versions of Steam would use the "session mode"
described below.
`use_tool_subprocess_reaper`
: If set to `1`, Steam will send `SIGINT` to the compatibility tool
instead of proceeding directly to `SIGKILL`, to give it a chance
to do graceful cleanup.
## Command-line
In a version 1 manifest, the `commandline` is a shell expression.
The first word should start with `/` and is interpreted as being
relative to the directory containing the compat tool, so `/run`
really means something like
`~/.local/share/Steam/steamapps/common/MyCompatTool/run`.
The game's command-line will be appended to the tool's command-line,
so if you are using `getopt` or a compatible command-line parser, you
might want to use a `commandline` like `/run --option --other-option --`
to get the game's command-line to appear after a `--` separator.
In a version 2 manifest, the special token `%verb%` can appear in the
`commandline`. It is replaced by either `run` or `waitforexitandrun`.
If a compatibility tool has `require_tool_appid` set, then the command-line
is built up by taking the required tool, then appending the tool that
requires it, and finally appending the actual game: so if a compat tool
named `Inner` requires a compat tool named `Outer`, and both tools have
`/run %verb% --` as their `commandline`, then the final command line will
look something like:
/path/to/Outer/run waitforexitandrun -- /path/to/Inner/run waitforexitandrun -- /path/to/game.exe
## Environment
Some environment variables are set by Steam, including:
`LD_LIBRARY_PATH`
: Used to load Steam Runtime libraries.
`LD_PRELOAD`
: Used to load the Steam Overlay.
`STEAM_COMPAT_APP_ID`
: The decimal app-ID of the game, for example 440 for Team Fortress 2.
`STEAM_COMPAT_CLIENT_INSTALL_PATH`
: The absolute path to the directory where Steam is installed. This is the
same as the target of the `~/.steam/root` symbolic link.
`STEAM_COMPAT_DATA_PATH`
: The absolute path to a directory that compatibility tools can use to
store game-specific data. For example, Proton puts its `WINEPREFIX`
in `$STEAM_COMPAT_DATA_PATH/pfx`.
`STEAM_COMPAT_INSTALL_PATH`
: The absolute path to the game's installation directory, for example
`/home/you/.local/share/Steam/steamapps/common/Estranged Act I`,
even if the current working directory is a subdirectory of this
(as is the case for Estranged: Act I (261820) for example).
`STEAM_COMPAT_LIBRARY_PATHS`
: Colon-delimited list of paths to Steam Library directories containing
the game, the compatibility tools if any, and any other resources
that the game will need, such as DirectX installers.
`STEAM_COMPAT_MOUNTS`
: Colon-delimited list of paths to additional directories that are to be
made available read/write in a pressure-vessel container.
`STEAM_COMPAT_SESSION_ID`
: In the historical session mode (see below), this is used to link together
multiple container invocations into a logical "session".
`STEAM_COMPAT_SHADER_PATH`
: The absolute path to the variable data directory used for cached
shaders, if any.
`STEAM_COMPAT_TOOL_PATHS`
: Colon-delimited list of paths to Steam compatibility tools in use.
Typically this will be a single path, but when using tools with
`require_tool_appid` set, such as Proton, it is a colon-separated
list with the "innermost" tool first and the "outermost" tool last.
`SteamAppId`
: The same as `STEAM_COMPAT_APP_ID`, but only when running the actual
game; not set when running
[install scripts](https://partner.steamgames.com/doc/sdk/installscripts)
or other setup commands. The Steamworks API assumes that every process
with this environment variable set is part of the actual game.
When Steam invokes a tool with `require_tool_appid` set, such as Proton,
the environment variables are set as described for the "outermost" tool,
which can change them if required before it invokes the "innermost" tool
(although most should not be changed).
For example, when using Proton with "Steam Linux Runtime - soldier", the
"outer" compatibility tool "Steam Linux Runtime - soldier" is run with
`LD_LIBRARY_PATH` set by the Steam Runtime to point to mixed host and
scout libraries. After setting up the container, it runs the "inner"
compatibility tool (Proton) with an entirely new `LD_LIBRARY_PATH`
pointing to mixed host and soldier libraries.
## Native Linux Steam games
This is the simplest situation and can be considered to be the baseline.
In recent versions of Steam, the game process is wrapped in a `reaper`
process which sets itself as a subreaper using `PR_SET_CHILD_SUBREAPER`
(see
[**prctl**(2)](https://manpages.debian.org/unstable/manpages-dev/prctl.2.en.html)
for details).
Version 1 compat tools are not invoked specially.
Version 2 compat tools are invoked with a `%verb%` in the `commandline`
(if any) replaced by `waitforexitandrun`.
The game is expected to run in the usual way. Conventionally, it does not
double-fork to put itself in the background, but if it does, any background
processes will be reparented to have the subreaper as their parent.
The current working directory is the working directory configured in the
game's Steam metadata (for example `estrangedact1` for Estranged: Act 1,
261820), or the game's directory (or maybe the executable's directory?)
if unconfigured. The compatibility tool is expected to preserve this
working directory when running the actual game.
The environment variable `STEAM_COMPAT_SESSION_ID` is not set.
The environment variable `STEAM_COMPAT_APP_ID` is set to the app-ID
of the game. The environment variable `SteamAppId` has the same value.
## Windows games with no install script
Some Windows games, such as Soldat (638490), do not have an
"install script" in their metadata. Running these games behaves much the
same as a native Linux game: it is wrapped in a subreaper, version 1
compat tools are not invoked specially, and version 2 compat tools
are invoked with a `%verb%` in the `commandline` (if any) replaced by
`waitforexitandrun`.
The environment variable `STEAM_COMPAT_SESSION_ID` is not set.
Historically, it was set to a unique token that was not used in any
previous invocation.
The environment variable `STEAM_COMPAT_APP_ID` is set to the app-ID
of the game. The environment variable `SteamAppId` has the same value.
The current working directory is the working directory configured in the
game's Steam metadata, as usual.
## Windows games with an install script (since Steam beta 1623823138)
Other Windows games, such as Everquest (205710), have an
[install script](https://partner.steamgames.com/doc/sdk/installscripts),
conventionally named `installscript.vdf`, which must be run by an
interpreter.
Since Steam beta 1623823138, these games are run like this:
* Run the install script. For version 1 compat tools, the compat
tool is run as usual, except that the command appended to the
command-line is the install script interpreter, not the actual game.
For version 2 compat tools, the `%verb%` is set to `run` instead
of the usual `waitforexitandrun`.
The environment variable `STEAM_COMPAT_SESSION_ID` is not set.
The environment variable `STEAM_COMPAT_APP_ID` is set to the app-ID
of the game.
The environment variable `SteamAppId` is *not* set in this case.
The current working directory is *not* the game's directory in this case.
As currently implemented, it appears to be the Steam installation
(usually `~/.local/share/Steam` or `~/.steam/debian-installation`)
but this is probably not guaranteed.
* Run the actual game in the usual way.
The environment variable `STEAM_COMPAT_SESSION_ID` is not set.
The environment variables `STEAM_COMPAT_APP_ID` and `SteamAppId`
are both set to the app-ID of the game as usual.
The current working directory is the working directory configured in
the game's Steam metadata, as usual.
## Historical behaviour of Windows games (session mode v2)
Before Steam beta 1623823138, each Windows game had several setup commands
to run before it could be launched. They were invoked like this:
* Run the first setup command. For version 1 compat tools, the compat
tool is run as usual, except that the command appended to the
command-line is the setup command, not the actual game.
For version 2 compat tools, additionally the `%verb%` is set to `run`
instead of `waitforexitandrun`.
The environment variable `STEAM_COMPAT_SESSION_ID` is set to a
unique token (in practice a 64-bit number encoded in hex).
The environment variable `STEAM_COMPAT_APP_ID` is set to the app-ID
of the game.
The environment variable `SteamAppId` is *not* set in this case.
The current working directory is *not* the game's directory in this case.
As currently implemented, it appears to be the Steam installation
(usually `~/.local/share/Steam` or `~/.steam/debian-installation`)
but this is probably not guaranteed.
The compat tool is expected to do any setup that it needs to do
(for example pressure-vessel must start a container), then run
the given command and exit. The compat tool may leave processes
running in the background.
* Run the second setup command, in the same way as the first, and so on.
More than one command can be run in parallel, so tools that need to
do setup (such as pressure-vessel) must use a lock to ensure the setup
is only done by whichever setup command wins the race to be the first.
All environment variables are the same as for the first setup command,
and in particular the `STEAM_COMPAT_SESSION_ID` is the same. This is
how compatibility tools can know which containers or subprocesses
to reuse.
* When all setup commands have finished, run the actual game. For
version 2 compat tools, the `%verb%` is set to `waitforexitandrun`.
The compat tool is expected to terminate any background processes
(for example pressure-vessel terminates the container and Proton
terminates the `wineserver`) and wait for them to exit, then launch
the actual game.
The environment variable `STEAM_COMPAT_SESSION_ID` is set to the
same unique token as for all the setup commands, so that the compat
tool can identify which subprocesses or containers to tear down.
The environment variables `STEAM_COMPAT_APP_ID` and `SteamAppId`
are both set to the app-ID of the game as usual.
## Non-Steam games
Version 1 compat tools are not invoked specially.
Version 2 compat tools are invoked with a `%verb%` in the `commandline`
(if any) replaced by `waitforexitandrun`.
The environment variable `STEAM_COMPAT_SESSION_ID` is not set.
Historically, it was set to a unique token that was not used in any
previous invocation.
`STEAM_COMPAT_APP_ID` is set to `0`. `SteamAppId` is not set.
`STEAM_COMPAT_DATA_PATH` is set to a unique directory per non-Steam game.
It is currently in the same format as Steam games' equivalent directories,
but with a large arbitrary integer replacing the Steam app ID.
`STEAM_COMPAT_INSTALL_PATH` is not set.
`LD_LIBRARY_PATH` is usually set to the empty string to "escape" from
the Steam Runtime library stack for non-Steam games, although games
configured in Steam via development tools can be flagged to use the
Steam Runtime library stack (this is done for games that are intended to
be released onto Steam as native Linux games).
The current working directory defaults to the directory containing the
main executable, but can be reconfigured through the shortcut's properties.
Steam Linux Runtime (pressure-vessel) containers will not work as expected
unless this is set to the game's top-level directory.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment