Skip to content
Snippets Groups Projects

Document the Steam compatibility tool interface

Merged Simon McVittie requested to merge wip/smcv/document-compat-tools into master
+ 417
0
 
# 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 this:
 
 
/path/to/Outer/run waitforexitandrun -- \
 
/path/to/Inner/run waitforexitandrun -- \
 
/path/to/game.exe
 
 
(In reality it would all be one line, rather than having escaped newlines
 
as shown here.)
 
 
## Launch options
 
 
If a Steam game has user-specified launch options configured in its
 
Properties, and they contain the special token `%command%`, then
 
`%command%` is replaced by the entire command-line built up from the
 
compatibility tools. For example, if a compat tool named `Inner` requires
 
a compat tool named `Outer`, both tools have `/run %verb% --` as their
 
`commandline`, and the user has set the Launch Options in the game's
 
properties to
 
 
DEBUG=yes taskset --cpu-list 0,2 %command% -console
 
 
then the final command line will look something like this:
 
 
DEBUG=yes taskset --cpu-list 0,2 \
 
/path/to/Outer/run waitforexitandrun -- \
 
/path/to/Inner/run waitforexitandrun -- \
 
/path/to/game.exe -console
 
 
(In reality it would all be one line, rather than having escaped newlines
 
as shown here.)
 
 
If the user-specified launch options for a Steam game do not contain
 
`%command%`, then they are simply appended to the command-line. For
 
example, setting the launch options to `--debug` is equivalent to
 
`%command% --debug`.
 
 
Shortcuts for non-Steam games do not currently implement the special
 
handling for `%command%`: the configured launch options are simply
 
appended to the command-line, regardless of whether they contain
 
`%command%` or not.
 
 
Please note that not all invocations of compatibility tools take the
 
user-specified launch options into account: they are used when running
 
the actual game, but they are not used for install scripts.
 
 
## 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.
 
 
The [launch options](#launch-options) are used.
 
 
## 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.
 
 
The [launch options](#launch-options) are used.
 
 
## 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.
 
 
The [launch options](#launch-options) are **not** used here.
 
 
* 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.
 
 
The [launch options](#launch-options) are used, 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 [launch options](#launch-options) are **not** used here.
 
 
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.
 
 
The [launch options](#launch-options) are used, 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.
 
 
Launch options are appended to the command-line. The special token
 
`%command%` in Steam games' launch options is not used here.
Loading