We launch Steam games in Proton with support for Native Wayland
The illustrations for the article were prepared by the freepik.com neural network.
In the first part of our article, we learned how to compile Wine with Wayland support and launched the Overwatch 2 game. But for most gamers, of course, the launch of Steam games is of greater interest, and we will not bypass this issue. The advantage of our Proton build will also be that it will work directly with the system libraries and hardware, when the regular Proton and GE Proton Custom are booted in a virtual container, uploading their libraries and drivers. Thus, we will get a little better performance and get rid of another unnecessary layer.
If you are interested in the article, then welcome to cut.
We won’t completely copy how Proton works, because Proton itself is not stable, has a lot of bugs due to a lot of dirty hacks in the Wine code. These hacks are not included in the main Wine code and are often written in a very messy, chaotic and random way. Most of these hacks are redundant, not needed by most games and only added to run some specific older games on Steam.
Contents
Protonate Wine
First we need to create a directory tree for our Proton and copy Wine. On most systems, Steam stores its files in ${HOME}/.steam/root
but you may not have this directory, but you may have, for example ${HOME}/.local/share/Steam
or some other directory, so replace STEAM_DIR
to your steam directory path in the bash scripts below.
By default, the Proton startup manifest looks like this:
"manifest"
{
"version" "2"
"commandline" "/proton %verb%"
"require_tool_appid" "1628350"
"use_sessions" "1"
"compatmanager_layer_name" "proton"
}
The manifest file specifies which commands Steam will execute to launch Proton. The problem with this manifest is that if the manifest contains fields require_tool_appid
and use_sessions
Proton will run in a virtual container with Steam libraries. The disadvantage of such libraries is that they are compiled only with X11 and do not know anything about Wayland. So our manifest should look like below, which will force Steam to use our OS’s system libraries.
"manifest"
{
"version" "2"
"commandline" "/proton %verb%"
}
I also want to note that the main python script proton
, is not standard, and was adapted by me to build my Proton with Wayland support, plus added the option to run Wine with real-time priority. You can find the differences by comparing the files using the utility diff
. The original script can be found at the proton link.
Let’s execute the script:
#!/usr/bin/bash
# Имя нашей Proton сборки.
PROTON_NAME="ProtonWay-9.2"
# Директория в которой хранятся файлы Steam.
STEAM_DIR="${HOME:?}/.steam/root"
# Директория в которой хранятся исходные коды.
SOURCE_DIR="${HOME:?}/code"
# Директория в которой установлен наш собранный Wine.
WINE_DIR="${HOME:?}/wine"
# Если возникает ошибка, то прекращаем выполнение дальнейших команд.
set -euo pipefail
# Создаем директорию для нашего Proton, если она не существует.
if [ ! -d "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}" ]; then
mkdir -p "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}"
fi
# Создаем директорию files где будут файлы нашего Wine.
if [ ! -d "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files" ]; then
mkdir -p "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files"
fi
# Копируем файлы нашего Wine.
cp -rv "${WINE_DIR:?}/bin" "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/bin"
cp -rv "${WINE_DIR:?}/lib" "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib"
cp -rv "${WINE_DIR:?}/lib64" "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib64"
cp -rv "${WINE_DIR:?}/share" "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/share"
# Генерируем файл версии unix time + уникальное имя.
echo "$(date +%s) ${PROTON_NAME:?}" > "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/version"
# Создаем манифест.
cat << EOF > "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/toolmanifest.vdf"
"manifest"
{
"version" "2"
"commandline" "/proton %verb%"
}
EOF
# Создаем файл совместимости.
cat << EOF > "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/compatibilitytool.vdf"
"compatibilitytools"
{
"compat_tools"
{
"###PROTON_NAME###"
{
"install_path" "."
"display_name" "###PROTON_NAME###"
"from_oslist" "windows"
"to_oslist" "linux"
}
}
}
EOF
sed -i "s/###PROTON_NAME###/${PROTON_NAME:?}/g" "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/compatibilitytool.vdf"
# Копируем python скрипты Proton и меняем имя сборки.
cp -vf "${SOURCE_DIR:?}/wine-wayland/proton/proton" "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/proton"
cp -vf "${SOURCE_DIR:?}/wine-wayland/proton/settings.py" "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/settings.py"
cp -vf "${SOURCE_DIR:?}/wine-wayland/proton/filelock.py" "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/filelock.py"
sed -i "s/###PROTON_NAME###/${PROTON_NAME:?}/g" "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/proton"
chmod +x "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/proton"
# Создадим директории где будем хранить наши dxvk, vkd3d-proton, nvapi.
mkdir -p "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib/wine/dxvk"
mkdir -p "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib/wine/vkd3d-proton"
mkdir -p "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib/wine/nvapi"
mkdir -p "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib64/wine/dxvk"
mkdir -p "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib64/wine/vkd3d-proton"
mkdir -p "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib64/wine/nvapi"
Installation of dxvk, vkd3d-proton, nvapi
In the first part, we downloaded and extracted the necessary files, so we will copy the files dxvk
, vkd3d-proton
, nvapi
to the appropriate directories. If you don’t have an Nvidia graphics card, you can skip copying the files nvapi.dll
, nvapi64.dll
.
# Имя нашей Proton сборки.
PROTON_NAME="ProtonWay-9.2"
# Директория в которой хранятся файлы Steam.
STEAM_DIR="${HOME:?}/.steam/root"
# Директория в которой хранятся исходные коды.
SOURCE_DIR="${HOME:?}/code"
# Скопируем dxvk.
cp -vf "${SOURCE_DIR:?}/dxvk-2.3/x64/"*.dll "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib64/wine/dxvk/"
cp -vf "${SOURCE_DIR:?}/dxvk-2.3/x32/"*.dll "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib/wine/dxvk/"
# Скопируем vkd3d-proton.
cp -vf "${SOURCE_DIR:?}/vkd3d-proton-2.11.1/x64/"*.dll "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib64/wine/vkd3d-proton/"
cp -vf "${SOURCE_DIR:?}/vkd3d-proton-2.11.1/x86/"*.dll "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib/wine/vkd3d-proton/"
# Скопируем dxvk-nvapi.
cp -vf "${SOURCE_DIR:?}/dxvk-nvapi-v0.6.4/x64/"*.dll "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib64/wine/nvapi"
cp -vf "${SOURCE_DIR:?}/dxvk-nvapi-v0.6.4/x32/"*.dll "${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}/files/lib/wine/nvapi"
Installing fonts
In order for Proton to automatically install fonts when installing games, we need to copy the fonts to a directory fonts
in files/share
of our Proton. If we don’t create this font directory, our Proton will hang on startup. This is the specifics of Proton scripts. The easiest way is to take the fonts from GE Proton Custom, but we are not looking for easy ways and therefore we will generate them ourselves. Yes, there is no error here, we will generate fonts based on open fonts: Liberation Sans
, Liberation Serif
, Liberation Mono
, Noto Sans
, changing the metadata of the source fonts. This method does not allow you to get the original Windows fonts, and only replaces them with open, renamed ones. This avoids font copyright issues and is the generation method used by Valve at Proton. In our work, we will skip the generation of specific fonts for Chinese, Japanese, Indian, Arabic languages, which is generated by Proton, but we will add additional drawings for the main Russian-English fonts, such as: bold, italic, bold-italic. Proton does not generate all of them and is often limited to only the main Regular font. At the same time, our fonts will weigh 10 times less than Proton’s, which will make them load faster.
To create fonts, we need to install the package fontforge
and python module fonttools
. In Fedora Linux, this can be done with the commands:
sudo dnf install fontforge
pip install fonttools
Let’s execute the script:
#!/usr/bin/bash
# Имя нашей Proton сборки.
PROTON_NAME="ProtonWay-9.2"
# Директория в которой хранятся файлы Steam.
STEAM_DIR="${HOME:?}/.steam/root"
# Директория в которой хранятся исходные коды.
SOURCE_DIR="${HOME:?}/code"
# Директория в которой будет происходить сборка шрифтов.
BUILD_DIR="/tmp/build-fonts"
# Директория в которой находится Proton, в которую мы установим шрифты.
INSTALL_DIR="${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}"
FONTS_DIR="${SOURCE_DIR:?}/proton/fonts"
LIBERATION_SRCDIR="${FONTS_DIR:?}/liberation-fonts/src"
NOTO_SANS_SRCDIR="${FONTS_DIR:?}/noto"
# Если возникает ошибка, то прекращаем выполнение дальнейших команд.
set -euo pipefail
# Создаем директорию в которой будет проходить сборка, если существует удаляем и создаем заново.
rm -fr "${BUILD_DIR:?}"
mkdir -p "${BUILD_DIR:?}"
# Генерируем основные шрифты: Arial, Times New Roman, Georgia, Courier New
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSans-Regular.sfd" "Arial" "Arial" "Arial" "${BUILD_DIR:?}/arial.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSans-Bold.sfd" "Arial-Bold" "Arial" "Arial Bold" "${BUILD_DIR:?}/arialbd.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSans-Italic.sfd" "Arial-Italic" "Arial" "Arial Italic" "${BUILD_DIR:?}/arialit.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSans-BoldItalic.sfd" "Arial-BoldItalic" "Arial" "Arial Bold Italic" "${BUILD_DIR:?}/arialbdit.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSerif-Regular.sfd" "TimesNewRoman" "Times New Roman" "Times New Roman" "${BUILD_DIR:?}/times.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSerif-Bold.sfd" "TimesNewRoman-Bold" "Times New Roman" "Times New Roman Bold" "${BUILD_DIR:?}/timesbd.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSerif-Italic.sfd" "TimesNewRoman-Italic" "Times New Roman" "Times New Roman Italic" "${BUILD_DIR:?}/timesit.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSerif-BoldItalic.sfd" "TimesNewRoman-BoldItalic" "Times New Roman" "Times New Roman Bold Italic" "${BUILD_DIR:?}/timesbdit.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSerif-Regular.sfd" "Georgia" "Georgia" "Georgia" "${BUILD_DIR:?}/georgia.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSerif-Bold.sfd" "Georgia-Bold" "Georgia" "Georgia Bold" "${BUILD_DIR:?}/georgiabd.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSerif-Italic.sfd" "Georgia-Italic" "Georgia" "Georgia Italic" "${BUILD_DIR:?}/georgiait.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationSerif-BoldItalic.sfd" "Georgia-BoldItalic" "Georgia" "Georgia Bold Italic" "${BUILD_DIR:?}/georgiabdit.ttf"
patch -Np1 -d "${LIBERATION_SRCDIR:?}" -i "${FONTS_DIR:?}/patches/LiberationMono-Regular.patch" -o "${BUILD_DIR:?}/LiberationMono-Regular.sfd"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${BUILD_DIR:?}/LiberationMono-Regular.sfd" "CourierNew" "Courier New" "Courier New" "${BUILD_DIR:?}/cour.ttf"
rm "${BUILD_DIR:?}/LiberationMono-Regular.sfd"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationMono-Bold.sfd" "CourierNew-Bold" "Courier New" "Courier New Bold" "${BUILD_DIR:?}/courbd.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationMono-Italic.sfd" "CourierNew-Italic" "Courier New" "Courier New Italic" "${BUILD_DIR:?}/courit.ttf"
fontforge -quiet -script "${FONTS_DIR:?}/scripts/generatefont.pe" \
"${LIBERATION_SRCDIR:?}/LiberationMono-BoldItalic.sfd" "CourierNew-BoldItalic" "Courier New" "Courier New Bold Italic" "${BUILD_DIR:?}/courbdit.ttf"
# Копируем скрипт объединения шрифтов семейства Noto Sans в один файл, и включаем игнорирование отсутствующих unicode символов в шрифтах.
cp -v "${FONTS_DIR:?}/scripts/merge.py" "${BUILD_DIR:?}/merge.py"
sed -i "s/ignore_missing_unicodes=False/ignore_missing_unicodes=True/" "${BUILD_DIR:?}/merge.py"
# Создаем шрифт Microsoft Sans Serif на основе Noto Sans.
"${BUILD_DIR:?}/merge.py" \
"${NOTO_SANS_SRCDIR:?}/NotoSans-Regular.ttf" \
"${NOTO_SANS_SRCDIR:?}/NotoSansMath-Regular.ttf" \
"${NOTO_SANS_SRCDIR:?}/NotoSansMono-Regular.ttf" \
"${NOTO_SANS_SRCDIR:?}/NotoSansSymbols-Regular.ttf" \
"${NOTO_SANS_SRCDIR:?}/NotoSansSymbols2-Regular.ttf" \
"MicrosoftSansSerif" "Microsoft Sans Serif" "Regular" \
"${FONTS_DIR:?}/ranges/micross" "${BUILD_DIR:?}/micross.ttf"
# Создаем альтернативную версию шрифта Arial на основе Noto Sans.
mkdir -p "${BUILD_DIR:?}/alt"
"${BUILD_DIR:?}/merge.py" \
"${NOTO_SANS_SRCDIR:?}/NotoSans-Regular.ttf" \
"${NOTO_SANS_SRCDIR:?}/NotoSansMath-Regular.ttf" \
"${NOTO_SANS_SRCDIR:?}/NotoSansMono-Regular.ttf" \
"${NOTO_SANS_SRCDIR:?}/NotoSansSymbols-Regular.ttf" \
"${NOTO_SANS_SRCDIR:?}/NotoSansSymbols2-Regular.ttf" \
"Arial" "Arial" "Regular" \
"${FONTS_DIR:?}/ranges/arial" "${BUILD_DIR:?}/alt/arial.ttf"
rm -vf "${BUILD_DIR:?}/merge.py"
# Создаем директорию шрифтов в нашем Proton.
if [ ! -d "${INSTALL_DIR:?}/files/share/fonts" ]; then
mkdir -p "${INSTALL_DIR:?}/files/share/fonts"
fi
# Копируем наши шрифты.
cp -rv ${BUILD_DIR:?}/* "${INSTALL_DIR:?}/files/share/fonts/"
# Очищаем директорию сборки.
rm -fr "${BUILD_DIR:?}"
If everything went well, we will see our fonts in the directory files/share/fonts
.
Building lsteamclient and steam_helper
After we have created the directory tree and copied the files, we need to compile lsteamclient
and steam_helper
, which are required to authorize games. You can do this using the script below:
#!/usr/bin/bash
# Имя нашей Proton сборки.
PROTON_NAME="ProtonWay-9.2"
# Директория в которой хранятся файлы Steam.
STEAM_DIR="${HOME:?}/.steam/root"
# Директория в которой установлен наш собранный Wine.
WINE_DIR="${HOME:?}/wine"
# Директория в которой хранятся исходные коды.
SOURCE_DIR="${HOME:?}/code"
# Директория в которой будет происходить сборка.
BUILD_DIR="/tmp/build-proton"
# Флаги компиляции 64 битной версии версии lsteamclient и steam_helper.
BUILD_CFLAGS="-march=native -mtune=native"
# Флаги компиляции 32 битной версии lsteamclient и steam_helper.
BUILD_CFLAGS_32="-mtune=native"
# Директория в которой находится Proton, в который мы установим lsteamclient и steam_helper.
INSTALL_DIR="${STEAM_DIR:?}/compatibilitytools.d/${PROTON_NAME:?}"
# Если возникает ошибка, то прекращаем выполнение дальнейших команд.
set -euo pipefail
# Сбрасываем все флаги сборки, если наши переменные окружения установлены.
unset CPPFLAGS
unset CFLAGS
unset CXXFLAGS
unset LDFLAGS
# Добавим в PATH директорию bin нашего Wine. Это необходимо для поиска инструментов сборки, который устанавливаются вместе с Wine.
export PATH="${WINE_DIR:?}/bin:${PATH}"
# Создаем директорию, в которой будет проходить сборка, если существует — удаляем и создаем заново.
rm -fr "${BUILD_DIR:?}"
mkdir -p "${BUILD_DIR:?}"
# Устанавливаем флаги для сборки 32 битных библиотек.
export CFLAGS="${BUILD_CFLAGS_32} -Wno-attributes"
export CXXFLAGS="${BUILD_CFLAGS_32} -fpermissive -Wno-attributes"
MAKEFLAGS="--nosource-fix --nolower-include --nodlls --nomsvcrt -I${SOURCE_DIR:?}/wine/include -I${SOURCE_DIR:?}/wine/include/wine"
# Создаем директорию для сборки 32 битной версии lsteamclient, копируем исходный код и переходим в нее.
rm -fr "${BUILD_DIR:?}/lsteamclient.win32"
cp -r "${SOURCE_DIR:?}/proton/lsteamclient" "${BUILD_DIR:?}/lsteamclient.win32"
cd "${BUILD_DIR:?}/lsteamclient.win32"
# Собираем lsteamclient.
winemaker --wine32 --dll ${MAKEFLAGS:?} \
-DSTEAM_API_EXPORTS \
-Dprivate=public \
-Dprotected=public \
.
sed -re 's@_LDFLAGS=@_LDFLAGS= -static-libgcc -static-libstdc++ -ldl @' -i Makefile
make -e CC="winegcc -m32" CXX="wineg++ -m32 -std=gnu++11" -j$(nproc)
# Собираем fake dll для lsteamclient.
winebuild --dll --fake-module -m32 -o lsteamclient.dll.fake -E lsteamclient.spec
mv lsteamclient.dll.fake lsteamclient.dll
# Создаем директорию для сборки 32 битной версии steam_helper, копируем исходный код и переходим в нее.
rm -fr "${BUILD_DIR:?}/steam.win32"
cp -r "${SOURCE_DIR:?}/proton/steam_helper" "${BUILD_DIR:?}/steam.win32"
cd "${BUILD_DIR:?}/steam.win32"
# Собираем steam_helper.
winemaker --wine32 --guiexe ${MAKEFLAGS:?} \
-I${SOURCE_DIR:?}/proton/openvr/headers \
-I${SOURCE_DIR:?}/proton/lsteamclient/steamworks_sdk_142 \
.
make -e CC="winegcc -m32" CXX="wineg++ -m32" LIBRARIES="-L${SOURCE_DIR:?}/proton/steam_helper/32 -static-libgcc -static-libstdc++ -lsteam_api -lshlwapi -lmsi -lole32 -ldl" -j$(nproc)
# Собираем fake exe для steam_helper
touch steam.spec
winebuild --exe --fake-module -m32 -o steam.exe -E steam.spec
# Устанавливаем флаги для сборки 64 битных библиотек.
export CFLAGS="${BUILD_CFLAGS} -Wno-attributes"
export CXXFLAGS="${BUILD_CFLAGS} -fpermissive -Wno-attributes"
# Создаем директорию для сборки 32 битной версии lsteamclient, копируем исходный код и переходим в нее.
rm -fr "${BUILD_DIR:?}/lsteamclient.win64"
cp -r "${SOURCE_DIR:?}/proton/lsteamclient" "${BUILD_DIR:?}/lsteamclient.win64"
cd "${BUILD_DIR:?}/lsteamclient.win64"
# Собираем lsteamclient.
winemaker --dll ${MAKEFLAGS:?} \
-DSTEAM_API_EXPORTS \
-Dprivate=public \
-Dprotected=public \
.
sed -re 's@_LDFLAGS=@_LDFLAGS= -static-libgcc -static-libstdc++ -ldl @' -i Makefile
make -e CC="winegcc -m64" CXX="wineg++ -m64 -std=gnu++11" -j$(nproc)
# Собираем fake dll для lsteamclient.
winebuild --dll --fake-module -m64 -o lsteamclient.dll.fake -E lsteamclient.spec
mv lsteamclient.dll.fake lsteamclient.dll
# Создаем директорию для сборки 64 битной версии steam_helper, копируем исходный код и переходим в нее.
rm -fr "${BUILD_DIR:?}/steam.win64"
cp -r "${SOURCE_DIR:?}/proton/steam_helper" "${BUILD_DIR:?}/steam.win64"
cd "${BUILD_DIR:?}/steam.win64"
# Собираем steam_helper.
winemaker --guiexe ${MAKEFLAGS:?} \
-I${SOURCE_DIR:?}/proton/openvr/headers \
-I${SOURCE_DIR:?}/proton/lsteamclient/steamworks_sdk_142 \
.
make -e CC="winegcc -m64" CXX="wineg++ -m64" LIBRARIES="-L${SOURCE_DIR:?}/proton/steam_helper/64 -static-libgcc -static-libstdc++ -lsteam_api -lshlwapi -lmsi -lole32 -ldl" -j$(nproc)
# Собираем fake exe для steam_helper.
touch steam.spec
winebuild --exe --fake-module -m64 -o steam.exe -E steam.spec
# Установка библиотек.
cp -v "${BUILD_DIR:?}/lsteamclient.win32/lsteamclient.dll.so" "${INSTALL_DIR}/files/lib/wine/i386-unix/lsteamclient.dll.so"
cp -v "${BUILD_DIR:?}/lsteamclient.win32/lsteamclient.dll" "${INSTALL_DIR}/files/lib/wine/i386-windows/lsteamclient.dll"
cp -v "${BUILD_DIR:?}/steam.win32/steam.exe.so" "${INSTALL_DIR}/files/lib/wine/i386-unix/steam.exe.so"
cp -v "${BUILD_DIR:?}/steam.win32/steam.exe" "${INSTALL_DIR}/files/lib/wine/i386-windows/steam.exe"
cp -v "${BUILD_DIR:?}/steam.win32/32/libsteam_api.so" "${INSTALL_DIR}/files/lib/libsteam_api.so"
cp -v "${BUILD_DIR:?}/lsteamclient.win64/lsteamclient.dll.so" "${INSTALL_DIR}/files/lib64/wine/x86_64-unix/lsteamclient.dll.so"
cp -v "${BUILD_DIR:?}/lsteamclient.win64/lsteamclient.dll" "${INSTALL_DIR}/files/lib64/wine/x86_64-windows/lsteamclient.dll"
cp -v "${BUILD_DIR:?}/steam.win64/steam.exe.so" "${INSTALL_DIR}/files/lib64/wine/x86_64-unix/steam.exe.so"
cp -v "${BUILD_DIR:?}/steam.win64/steam.exe" "${INSTALL_DIR}/files/lib64/wine/x86_64-windows/steam.exe"
cp -v "${BUILD_DIR:?}/steam.win64/64/libsteam_api.so" "${INSTALL_DIR}/files/lib64/libsteam_api.so"
# Удаляем директории сборки.
rm -fr "${BUILD_DIR:?}/steam.win32"
rm -fr "${BUILD_DIR:?}/steam.win64"
rm -fr "${BUILD_DIR:?}/lsteamclient.win32"
rm -fr "${BUILD_DIR:?}/lsteamclient.win64"
rm -fr "${BUILD_DIR:?}"
Next, launch Steam. Go to the menu Steam->Settings
item Compatibility
.
We turn on all the switches and select our Proton from the list. Restart Steam.
Next, install the desired game. Tested games: Overwatch 2, Aimbeast, KovaaK’s, Apex Legends and these are the games I play myself.
After installing the game, in order for Proton-Wine to use the Wayland driver, we need to add the appropriate entries to the registry. It’s very easy to do. First we need to find out about the game ID. To do this, press the right mouse button on the game and select Properties
let’s go to the point Updates
let’s look App ID
. This is our ID. For Aimbeast it is equal 1100990
.
To run programs in our game prefix, for example winecfg
or regedit
we can use the command proton runinprefix
,
which will take the paths from the variables STEAM_COMPAT_DATA_PATH
, STEAM_COMPAT_INSTALL_PATH
, STEAM_COMPAT_LIBRARY_PATHS
, STEAM_COMPAT_CLIENT_INSTALL_PATH
and launch the required program.
# Путь где находится Wine префикс игры.
export STEAM_COMPAT_DATA_PATH="${HOME:?}/.local/share/Steam/steamapps/compatdata/1100990"
# Путь куда установлена игра.
export STEAM_COMPAT_INSTALL_PATH="${HOME:?}/.local/share/Steam/steamapps/common/Aimbeast"
# Директория steamapps в Steam.
export STEAM_COMPAT_LIBRARY_PATHS="${HOME:?}/.local/share/Steam/steamapps"
# Главная директория Steam.
export STEAM_COMPAT_CLIENT_INSTALL_PATH="${HOME:?}/.local/share/Steam"
# Перейдем в директорию нашего Proton.
cd "${HOME:?}/.steam/root/compatibilitytools.d/ProtonWay-9.2"
# Добавим необходимые записи в реестр.
./proton runinprefix reg.exe add HKCU\\Software\\Wine\\Drivers /v Graphics /d x11,wayland
./proton runinprefix reg.exe add HKCU\\Software\\Wine\\Wayland\ Driver /v unaccelerated_pointer /t REG_DWORD /d 1
Repeat for each installed game if you haven’t done it before.
The next step is to uncomment the line "WAYLAND": "1"
in settings.py
our Proton, which will enable Wayland for all games, or you can set game launch options DISPLAY="" %command%
for a specific game. You can also enable the launch of games with real-time scheduler priority "REALTIME": "1"
or set any custom environment variables. See settings.py
.
Now you can run the game and enjoy it in Wayland.
The Apex Legends game should preferably be run in Direct X 12 mode, so the performance of the game is better. You can do this using the startup options
%command% -eac_launcher_settings SettingsDX12.json
. I also recommend using the NtSync patches from the first part.
Congratulations, now you know how Wine and Proton work. You can create your own builds, run games, enjoy their smooth operation in Wayland. This is a good starting point. I hope that your path will not stop at reading this article and you will go further, be able to solve more difficult problems related to Wine and Proton.
PS. To prepare this article, a huge amount of work was done to study the operation of Proton, ported patches to Wine 9.0, and wrote scripts. Also, along the way, a lot of difficult problems were encountered, the solution of which took a lot of time, and this article is actually more complicated than the reader might think, where half-baked solutions are given. Thanks for reading and see you at Habra!