Compare commits

...

28 Commits

Author SHA1 Message Date
Proton Merge Bot
452828efa8 update submodules 2022-05-18 08:56:22 +00:00
Arkadiusz Hiler
eb60ff2f9f Add two more games to MFDXGI manager hack.
CW-Bug-Id: #19126
CW-Bug-Id: #20655
2022-05-18 11:53:03 +03:00
Arkadiusz Hiler
c5cb0daacd Add three more games to MFDXGI manager hack.
CW-Bug-Id: #19126
2022-05-16 18:58:44 +03:00
Proton Merge Bot
f2edf06c25 update submodules 2022-05-11 17:04:09 +03:00
Paul Gofman
111e78e0ab Add POSTAL4: No Regrets to MFDXGI manager hack.
CW-Bug-Id: #20611
2022-05-10 17:02:24 -05:00
Andrew Eikum
5721b87856 Add Disintegration to MFDXGI manager hack
CW-Bug-Id: #20592
2022-05-09 10:31:14 -05:00
Anna Lasky
bcb8420c1c Add Ember Knights to IMFDXGIDeviceManager hack
CW-Bug-Id: #19126
2022-04-27 12:49:16 -05:00
Arkadiusz Hiler
d3b1db53c1 update wine 2022-04-27 17:43:50 +03:00
Arkadiusz Hiler
50a2dc0557 update submodules 2022-04-27 15:11:59 +03:00
Andrew Eikum
f1985b21bb Ship libgstvpx
For VP8 and VP9 support.

CW-Bug-Id: #20379
2022-04-25 11:24:05 -05:00
Andrew Eikum
6dd8b53eb6 Makefile: Fix SDK build 2022-04-25 11:10:38 -05:00
Andrew Eikum
9cd9caa3e4 docker: Use full URLs for base images
podman doesn't automatically use the docker.io registry.
2022-04-25 11:10:38 -05:00
Arkadiusz Hiler
01fa5afe54 configure.sh: Update default Proton SDK image to 0.20220329.0-0 2022-04-22 18:57:56 +03:00
Arkadiusz Hiler
be2b39ec94 docker: Bump steamrt version to 0.20220329.0. 2022-04-22 18:57:56 +03:00
Esme Povirk
1e39d5838c Accept EINVAL result from copy_file_range.
Apparently, ecryptfs can give this result for regular files.

For #5769.
2022-04-22 18:57:56 +03:00
Esme Povirk
b62efa6a4e Fix getting errno in copy_file_range_ctypes.
For #5769.
2022-04-22 18:57:56 +03:00
Arkadiusz Hiler
3a9d57b6fa update vkd3d-proton to proton-v2.6-support branch 2022-04-22 18:57:56 +03:00
Esme Povirk
414f724aa0 Update Wine Mono to 7.2.0. 2022-04-22 18:57:56 +03:00
Arkadiusz Hiler
cabb81abf7 update dxvk-nvapi to v0.5.4 2022-04-22 18:57:56 +03:00
Paul Gofman
94af32c4a3 lsteamclient: HACK: Skip spurious overlay deactivation event.
CW-Bug-Id: #20169
2022-04-22 18:57:56 +03:00
Esme Povirk
8ff794f2d8 proton: Make reflinks for file copies when possible. 2022-04-22 18:57:55 +03:00
Georg Lehmann
447fb3d418 Set VKD3D_SHADER_DEBUG=none by default.
Link: https://github.com/ValveSoftware/Proton/pull/5326
2022-04-22 18:57:55 +03:00
Andrew Eikum
243c2fd2a1 Handle steampipe quirks in deploy builds 2022-04-22 18:57:55 +03:00
Andrew Eikum
3213456b1f Don't ship filenames with colons in them 2022-04-22 18:57:55 +03:00
Andrew Eikum
8f8069bb73 Don't ship proton dist files in a tarball anymore 2022-04-22 18:57:50 +03:00
Arkadiusz Hiler
952a238106 Makefile: Stop mentioning VMs. 2022-04-22 18:55:49 +03:00
Arkadiusz Hiler
b1225b9f24 Makefile: Get rid of install-internal target.
Since the migration off Vagrant we no longer need to copy Proton
installation from the VM to the host. This was replaced with a `make
install` invoked using the new build system which already puts things in
the right place. This render install-internal an unnecessary no-op.
2022-04-22 18:51:48 +03:00
Paul Gofman
9defdf97b8 Revert "lsteamclient: HACK Do not unset SteamAppId for 'Splitgate: Arena Warfare'."
This reverts commit 57dc9d706222ee68e502fcc53b2ff04427983a05.
2022-04-21 20:23:27 +03:00
13 changed files with 301 additions and 87 deletions

View File

@ -110,7 +110,7 @@ clean:
rm -rf $(BUILD_DIR)
protonsdk:
$(MAKE) $(MFLAGS) $(MAKEOVERRIDES) -C proton/docker $(UNSTRIPPED) PROTONSDK_VERSION=$(protonsdk_version) proton
$(MAKE) $(MFLAGS) $(MAKEOVERRIDES) -C docker $(UNSTRIPPED) PROTONSDK_VERSION=$(protonsdk_version) proton
configure: | $(BUILD_DIR)
if [ ! -e $(BUILD_DIR)/Makefile ]; then \
@ -126,15 +126,11 @@ downloads: configure
proton: downloads
$(MAKE) $(MFLAGS) $(MAKEOVERRIDES) -C $(BUILD_DIR)/ $(UNSTRIPPED) dist && \
echo "Proton built in VM. Use 'install' or 'deploy' targets to retrieve the build."
echo "Proton built locally. Use 'install', 'deploy' or 'redist' targets."
install-internal: | $(BUILD_ROOT)/compatibilitytools.d/$(_build_name)
install-internal: downloads
install: downloads
rm -rf $(STEAM_DIR)/compatibilitytools.d/$(_build_name)/files/ #remove proton's internal files, but preserve user_settings etc from top-level
$(MAKE) $(MFLAGS) $(MAKEOVERRIDES) -C $(BUILD_DIR)/ $(UNSTRIPPED) install
install: install-internal
mkdir -p $(STEAM_DIR)/compatibilitytools.d/
cp -Rf --no-dereference --preserve=mode,links $(BUILD_ROOT)/compatibilitytools.d/$(_build_name) $(STEAM_DIR)/compatibilitytools.d/
echo "Proton installed to your local Steam installation"
redist: | $(BUILD_ROOT)/$(DEPLOY_DIR)
@ -172,8 +168,8 @@ dxvk: | $(BUILD_ROOT)/dxvk/lib/wine/dxvk
dxvk: | $(BUILD_ROOT)/dxvk/lib64/wine/dxvk
dxvk: downloads
$(MAKE) $(MFLAGS) $(MAKEOVERRIDES) -C $(BUILD_DIR)/ $(UNSTRIPPED) dxvk && \
cp -f $(BUILD_DIR)/dist/dist/lib/wine/dxvk/*.dll $(BUILD_ROOT)/dxvk/lib/wine/dxvk/ && \
cp -f $(BUILD_DIR)/dist/dist/lib64/wine/dxvk/*.dll $(BUILD_ROOT)/dxvk/lib64/wine/dxvk/
cp -f $(BUILD_DIR)/dist/files/lib/wine/dxvk/*.dll $(BUILD_ROOT)/dxvk/lib/wine/dxvk/ && \
cp -f $(BUILD_DIR)/dist/files/lib64/wine/dxvk/*.dll $(BUILD_ROOT)/dxvk/lib64/wine/dxvk/
dxvk-nvapi: | $(BUILD_ROOT)/dxvk-nvapi/lib/wine/nvapi
dxvk-nvapi: | $(BUILD_ROOT)/dxvk-nvapi/lib64/wine/nvapi
@ -186,8 +182,8 @@ vkd3d-proton: | $(BUILD_ROOT)/vkd3d-proton/lib/wine/vkd3d-proton
vkd3d-proton: | $(BUILD_ROOT)/vkd3d-proton/lib64/wine/vkd3d-proton
vkd3d-proton: downloads
$(MAKE) $(MFLAGS) $(MAKEOVERRIDES) -C $(BUILD_DIR)/ $(UNSTRIPPED) vkd3d-proton && \
cp -f $(BUILD_DIR)/dist/dist/lib/wine/vkd3d-proton/*.dll $(BUILD_ROOT)/vkd3d-proton/lib/wine/vkd3d-proton/ && \
cp -f $(BUILD_DIR)/dist/dist/lib64/wine/vkd3d-proton/*.dll $(BUILD_ROOT)/vkd3d-proton/lib64/wine/vkd3d-proton/
cp -f $(BUILD_DIR)/dist/files/lib/wine/vkd3d-proton/*.dll $(BUILD_ROOT)/vkd3d-proton/lib/wine/vkd3d-proton/ && \
cp -f $(BUILD_DIR)/dist/files/lib64/wine/vkd3d-proton/*.dll $(BUILD_ROOT)/vkd3d-proton/lib64/wine/vkd3d-proton/
lsteamclient: | $(BUILD_ROOT)/lsteamclient/lib/wine/i386-windows
lsteamclient: | $(BUILD_ROOT)/lsteamclient/lib/wine/i386-unix
@ -195,10 +191,10 @@ lsteamclient: | $(BUILD_ROOT)/lsteamclient/lib64/wine/x86_64-windows
lsteamclient: | $(BUILD_ROOT)/lsteamclient/lib64/wine/x86_64-unix
lsteamclient: downloads
$(MAKE) $(MFLAGS) $(MAKEOVERRIDES) -C $(BUILD_DIR)/ $(UNSTRIPPED) lsteamclient && \
cp -f $(BUILD_DIR)/dist/dist/lib/wine/i386-windows/lsteamclient.dll $(BUILD_ROOT)/lsteamclient/lib/wine/i386-windows/ && \
cp -f $(BUILD_DIR)/dist/dist/lib/wine/i386-unix/lsteamclient.dll.so $(BUILD_ROOT)/lsteamclient/lib/wine/i386-unix/ && \
cp -f $(BUILD_DIR)/dist/dist/lib64/wine/x86_64-windows/lsteamclient.dll $(BUILD_ROOT)/lsteamclient/lib64/wine/x86_64-windows/ && \
cp -f $(BUILD_DIR)/dist/dist/lib64/wine/x86_64-unix/lsteamclient.dll.so $(BUILD_ROOT)/lsteamclient/lib64/wine/x86_64-unix/
cp -f $(BUILD_DIR)/dist/files/lib/wine/i386-windows/lsteamclient.dll $(BUILD_ROOT)/lsteamclient/lib/wine/i386-windows/ && \
cp -f $(BUILD_DIR)/dist/files/lib/wine/i386-unix/lsteamclient.dll.so $(BUILD_ROOT)/lsteamclient/lib/wine/i386-unix/ && \
cp -f $(BUILD_DIR)/dist/files/lib64/wine/x86_64-windows/lsteamclient.dll $(BUILD_ROOT)/lsteamclient/lib64/wine/x86_64-windows/ && \
cp -f $(BUILD_DIR)/dist/files/lib64/wine/x86_64-unix/lsteamclient.dll.so $(BUILD_ROOT)/lsteamclient/lib64/wine/x86_64-unix/
vrclient: | $(BUILD_ROOT)/vrclient/lib/wine/i386-windows
vrclient: | $(BUILD_ROOT)/vrclient/lib/wine/i386-unix
@ -206,17 +202,17 @@ vrclient: | $(BUILD_ROOT)/vrclient/lib64/wine/x86_64-windows
vrclient: | $(BUILD_ROOT)/vrclient/lib64/wine/x86_64-unix
vrclient: downloads
$(MAKE) $(MFLAGS) $(MAKEOVERRIDES) -C $(BUILD_DIR)/ $(UNSTRIPPED) vrclient && \
cp -f $(BUILD_DIR)/dist/dist/lib/wine/i386-windows/vrclient.dll $(BUILD_ROOT)/vrclient/lib/wine/i386-windows/ && \
cp -f $(BUILD_DIR)/dist/dist/lib/wine/i386-unix/vrclient.dll.so $(BUILD_ROOT)/vrclient/lib/wine/i386-unix/ && \
cp -f $(BUILD_DIR)/dist/dist/lib64/wine/x86_64-windows/vrclient_x64.dll $(BUILD_ROOT)/vrclient/lib64/wine/x86_64-windows/ && \
cp -f $(BUILD_DIR)/dist/dist/lib64/wine/x86_64-unix/vrclient_x64.dll.so $(BUILD_ROOT)/vrclient/lib64/wine/x86_64-unix/
cp -f $(BUILD_DIR)/dist/files/lib/wine/i386-windows/vrclient.dll $(BUILD_ROOT)/vrclient/lib/wine/i386-windows/ && \
cp -f $(BUILD_DIR)/dist/files/lib/wine/i386-unix/vrclient.dll.so $(BUILD_ROOT)/vrclient/lib/wine/i386-unix/ && \
cp -f $(BUILD_DIR)/dist/files/lib64/wine/x86_64-windows/vrclient_x64.dll $(BUILD_ROOT)/vrclient/lib64/wine/x86_64-windows/ && \
cp -f $(BUILD_DIR)/dist/files/lib64/wine/x86_64-unix/vrclient_x64.dll.so $(BUILD_ROOT)/vrclient/lib64/wine/x86_64-unix/
wineopenxr: | $(BUILD_ROOT)/wineopenxr/lib64/wine/x86_64-windows
wineopenxr: | $(BUILD_ROOT)/wineopenxr/lib64/wine/x86_64-unix
wineopenxr: downloads
$(MAKE) $(MFLAGS) $(MAKEOVERRIDES) -C $(BUILD_DIR)/ $(UNSTRIPPED) wineopenxr && \
cp -f $(BUILD_DIR)/dist/dist/lib64/wine/x86_64-windows/wineopenxr.dll $(BUILD_ROOT)/wineopenxr/lib64/wine/x86_64-windows/ && \
cp -f $(BUILD_DIR)/dist/dist/lib64/wine/x86_64-unix/wineopenxr.dll.so $(BUILD_ROOT)/wineopenxr/lib64/wine/x86_64-unix/
cp -f $(BUILD_DIR)/dist/files/lib64/wine/x86_64-windows/wineopenxr.dll $(BUILD_ROOT)/wineopenxr/lib64/wine/x86_64-windows/ && \
cp -f $(BUILD_DIR)/dist/files/lib64/wine/x86_64-unix/wineopenxr.dll.so $(BUILD_ROOT)/wineopenxr/lib64/wine/x86_64-unix/
battleye: | $(BUILD_ROOT)/battleye/v1/lib/wine/i386-windows
battleye: | $(BUILD_ROOT)/battleye/v1/lib/wine/i386-unix

View File

@ -147,7 +147,7 @@ endif
##
DST_BASE := $(OBJ)/dist
DST_DIR := $(DST_BASE)/dist
DST_DIR := $(DST_BASE)/files
DST_LIBDIR32 := $(DST_DIR)/lib
DST_LIBDIR64 := $(DST_DIR)/lib64
DEPLOY_DIR := ./deploy
@ -190,12 +190,13 @@ COMPAT_MANIFEST_TEMPLATE := $(SRCDIR)/compatibilitytool.vdf.template
LICENSE := $(SRCDIR)/dist.LICENSE
OFL_LICENSE := $(SRCDIR)/fonts/liberation-fonts/LICENSE
AV1_PATENTS := $(SRCDIR)/dav1d/doc/PATENTS
STEAMPIPE_FIXUPS_PY := $(SRCDIR)/steampipe_fixups.py
GECKO_VER := 2.47.2
GECKO32_TARBALL := wine-gecko-$(GECKO_VER)-x86.tar.xz
GECKO64_TARBALL := wine-gecko-$(GECKO_VER)-x86_64.tar.xz
WINEMONO_VER := 7.1.2
WINEMONO_VER := 7.2.0
WINEMONO_TARBALL := wine-mono-$(WINEMONO_VER)-x86.tar.xz
FONTS := $(SRCDIR)/fonts
@ -278,9 +279,10 @@ DIST_TARGETS := $(DIST_COPY_TARGETS) $(DIST_OVR32) $(DIST_OVR64) \
$(DIST_COMPAT_MANIFEST) $(DIST_LICENSE) $(DIST_TOOLMANIFEST) \
$(DIST_OFL_LICENSE) $(DIST_AV1_PATENTS) $(DIST_FONTS)
DEPLOY_COPY_TARGETS := $(DIST_COPY_TARGETS) $(DIST_VERSION) $(DIST_LICENSE) \
$(DIST_TOOLMANIFEST) $(DIST_OFL_LICENSE) $(DIST_AV1_PATENTS)
REDIST_COPY_TARGETS := $(DEPLOY_COPY_TARGETS) $(DIST_COMPAT_MANIFEST)
BASE_COPY_TARGETS := $(DIST_COPY_TARGETS) $(DIST_VERSION) $(DIST_LICENSE) \
$(DIST_TOOLMANIFEST) $(DIST_OFL_LICENSE) $(DIST_AV1_PATENTS) $(DST_DIR)
DEPLOY_COPY_TARGETS := $(BASE_COPY_TARGETS) $(STEAMPIPE_FIXUPS_PY)
REDIST_COPY_TARGETS := $(BASE_COPY_TARGETS) $(DIST_COMPAT_MANIFEST)
$(DIST_LICENSE): $(LICENSE)
cp -a $< $@
@ -375,24 +377,21 @@ dist: $(DIST_TARGETS) all-dist dist_wineopenxr | $(DST_DIR)
echo `date '+%s'` `GIT_DIR=$(abspath $(SRCDIR)/.git) git describe --tags` > $(DIST_VERSION)
deploy: dist | $(filter-out dist deploy install redist,$(MAKECMDGOALS))
mkdir -p $(DEPLOY_DIR) && \
cp -a $(DEPLOY_COPY_TARGETS) $(DEPLOY_DIR) && \
tar -C $(DST_DIR) -c . > $(DEPLOY_DIR)/proton_dist.tar
@echo "Created deployment archive at "$(DEPLOY_DIR)"/proton_dist.tar"
mkdir -p $(DEPLOY_DIR)
cp -af --no-dereference --preserve=mode,links $(DEPLOY_COPY_TARGETS) $(DEPLOY_DIR)
python3 $(STEAMPIPE_FIXUPS_PY) process $(DEPLOY_DIR)
install: dist | $(filter-out dist deploy install redist,$(MAKECMDGOALS))
if [ ! -d $(STEAM_DIR) ]; then echo >&2 "!! "$(STEAM_DIR)" does not exist, cannot install"; return 1; fi
mkdir -p $(STEAM_DIR)/compatibilitytools.d/$(BUILD_NAME)
# Use -r instead of -a for sshfs
cp -rf --no-dereference --preserve=mode,links $(DST_BASE)/* $(STEAM_DIR)/compatibilitytools.d/$(BUILD_NAME)
cp -f $(DIST_VERSION) $(STEAM_DIR)/compatibilitytools.d/$(BUILD_NAME)/dist/
@echo "Installed Proton to "$(STEAM_DIR)/compatibilitytools.d/$(BUILD_NAME)
@echo "You may need to restart Steam to select this tool"
redist: dist | $(filter-out dist deploy install redist,$(MAKECMDGOALS))
mkdir -p $(REDIST_DIR)
cp -a $(REDIST_COPY_TARGETS) $(REDIST_DIR)
tar -C $(DST_DIR) -c . | gzip -c -1 > $(REDIST_DIR)/proton_dist.tar.gz
@echo "Created redistribution tarball at "$(REDIST_DIR)"/proton_dist.tar.gz"
cp -af --no-dereference --preserve=mode,links $(REDIST_COPY_TARGETS) $(REDIST_DIR)
.PHONY: module32 module64 module
@ -504,6 +503,7 @@ GST_GOOD_MESON_ARGS := \
-Dmpg123=enabled \
-Dvideobox=enabled \
-Dvideofilter=enabled \
-Dvpx=enabled \
-Dwavparse=enabled \
$(GST_COMMON_MESON_ARGS)

View File

@ -182,7 +182,7 @@ function configure() {
#
arg_steamrt="soldier"
arg_protonsdk_image="registry.gitlab.steamos.cloud/proton/soldier/sdk:0.20220119.0-1"
arg_protonsdk_image="registry.gitlab.steamos.cloud/proton/soldier/sdk:0.20220329.0-0"
arg_no_protonsdk=""
arg_build_name=""
arg_container_engine=""

View File

@ -71,6 +71,14 @@ def setup_dll_symlinks(default_pfx_dir, dist_dir):
os.unlink(filename)
make_relative_symlink(target, filename)
#steampipe can't handle filenames with colons, so we remove them here
#and restore them in the proton script
def fixup_drive_links(default_pfx_dir):
for walk_dir, dirs, files in os.walk(os.path.join(default_pfx_dir, "dosdevices")):
for dir_ in dirs:
if ":" in dir_:
os.remove(os.path.join(walk_dir, dir_))
def make_default_pfx(default_pfx_dir, dist_dir, runtime):
local_env = dict(os.environ)
@ -94,6 +102,7 @@ def make_default_pfx(default_pfx_dir, dist_dir, runtime):
env=local_env, check=True)
setup_dll_symlinks(default_pfx_dir, dist_dir)
fixup_drive_links(default_pfx_dir)
if __name__ == '__main__':
import sys

View File

@ -1,4 +1,4 @@
STEAMRT_VERSION = 0.20220119.0
STEAMRT_VERSION = 0.20220329.0
STEAMRT_URLBASE = registry.gitlab.steamos.cloud
PROTONSDK_URLBASE = $(STEAMRT_URLBASE)/proton/soldier/sdk
@ -7,8 +7,8 @@ PROTONSDK_VERSION = $(STEAMRT_VERSION)-0-dev
# this is just for building toolchain, as we do static builds it should
# not have any impact on the end result, but changing it will invalidate
# docker caches, so we need something that don't change much
BASE_IMAGE_i686 = i386/ubuntu:18.04
BASE_IMAGE_x86_64 = ubuntu:18.04
BASE_IMAGE_i686 = docker.io/i386/ubuntu:18.04
BASE_IMAGE_x86_64 = docker.io/amd64/ubuntu:18.04
BINUTILS_VERSION = 2.37
GCC_VERSION = 10.3.0

2
dxvk

@ -1 +1 @@
Subproject commit a72463c5afcb41d0b2f6459c87d396543053b983
Subproject commit 5b7406fed5b77fb440d43081bc1d5389bc46b2e6

@ -1 +1 @@
Subproject commit 87c043d7205b29cbba7610f0d88c7532ae32d736
Subproject commit ac312ac21bb1ca108a149849adba9fd1c77e3a9d

View File

@ -59,12 +59,9 @@ void sync_environment(void)
for (unsigned int i = 0; i < ARRAY_SIZE(steamapi_envs); i++)
{
const char *env_str;
if (!GetEnvironmentVariableA(steamapi_envs[i], value, ARRAY_SIZE(value)))
{
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND
&& !((env_str = getenv("SteamAppId")) && !strcmp(env_str, "677620")))
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
{
TRACE("unsetenv(\"%s\")\n", steamapi_envs[i]);
unsetenv(steamapi_envs[i]);
@ -683,6 +680,7 @@ bool CDECL Steam_BGetCallback(HSteamPipe pipe, struct winCallbackMsg_t *win_msg,
if(!load_steamclient())
return 0;
next_event:
ret = steamclient_BGetCallback(pipe, &lin_msg, ignored);
if(ret){
@ -701,7 +699,16 @@ bool CDECL Steam_BGetCallback(HSteamPipe pipe, struct winCallbackMsg_t *win_msg,
keybd_event(VK_RSHIFT, 0x36 /* rshift scancode */, KEYEVENTF_KEYUP, 0);
keybd_event(VK_TAB, 0x0f /* tab scancode */, KEYEVENTF_KEYUP, 0);
}
else ResetEvent(steam_overlay_event);
else
{
if (WaitForSingleObject(steam_overlay_event, 0) == WAIT_TIMEOUT)
{
FIXME("Spurious steam overlay deactivate event, skipping.\n");
steamclient_FreeLastCallback(pipe);
goto next_event;
}
ResetEvent(steam_overlay_event);
}
}
switch(win_msg->m_iCallback | (lin_msg.m_cubParam << 16)){

161
proton
View File

@ -10,6 +10,7 @@ import json
import os
import shutil
import errno
import platform
import stat
import subprocess
import sys
@ -17,13 +18,21 @@ import tarfile
import shlex
from ctypes import CDLL
from ctypes import CFUNCTYPE
from ctypes import POINTER
from ctypes import Structure
from ctypes import addressof
from ctypes import cast
from ctypes import get_errno
from ctypes import sizeof
from ctypes import c_int
from ctypes import c_int64
from ctypes import c_uint
from ctypes import c_long
from ctypes import c_char_p
from ctypes import c_void_p
from ctypes import c_size_t
from ctypes import c_ssize_t
from filelock import FileLock
from random import randrange
@ -142,10 +151,15 @@ def try_copy(src, dst, prefix=None, add_write_perm=True, copy_metadata=False, op
elif track_file and prefix is not None:
track_file.write(os.path.relpath(dst, prefix) + '\n')
if copy_metadata:
shutil.copy2(src, dst, follow_symlinks=follow_symlinks)
if os.path.islink(src) and not follow_symlinks:
shutil.copyfile(src, dst, follow_symlinks=False)
else:
shutil.copy(src, dst, follow_symlinks=follow_symlinks)
copyfile(src, dst)
if copy_metadata:
shutil.copystat(src, dst, follow_symlinks=follow_symlinks)
else:
shutil.copymode(src, dst, follow_symlinks=follow_symlinks)
if add_write_perm:
new_mode = os.lstat(dst).st_mode | stat.S_IWUSR | stat.S_IWGRP
@ -175,15 +189,62 @@ def try_copy(src, dst, prefix=None, add_write_perm=True, copy_metadata=False, op
else:
raise
# copy_file_range implementation for old Python versions
__syscall__copy_file_range = None
def copy_file_range_ctypes(fd_in, fd_out, count):
"Copy data using the copy_file_range syscall through ctypes, assuming x86_64 Linux"
global __syscall__copy_file_range
__NR_copy_file_range = 326
if __syscall__copy_file_range is None:
c_int64_p = POINTER(c_int64)
prototype = CFUNCTYPE(c_ssize_t, c_long, c_int, c_int64_p,
c_int, c_int64_p, c_size_t, c_uint, use_errno=True)
__syscall__copy_file_range = prototype(('syscall', CDLL(None, use_errno=True)))
while True:
ret = __syscall__copy_file_range(__NR_copy_file_range, fd_in, None, fd_out, None, count, 0)
if ret >= 0 or get_errno() != errno.EINTR:
break
if ret < 0:
raise OSError(get_errno(), errno.errorcode.get(get_errno(), 'unknown'))
return ret
def copyfile_reflink(srcname, dstname):
"Copy srcname to dstname, making reflink if possible"
global copyfile
with open(srcname, 'rb', buffering=0) as src:
bytes_to_copy = os.fstat(src.fileno()).st_size
try:
with open(dstname, 'wb', buffering=0) as dst:
while bytes_to_copy > 0:
bytes_to_copy -= copy_file_range(src.fileno(), dst.fileno(), bytes_to_copy)
except OSError as e:
if e.errno not in (errno.EXDEV, errno.ENOSYS, errno.EINVAL):
raise e
if e.errno == errno.ENOSYS:
copyfile = shutil.copyfile
shutil.copyfile(srcname, dstname)
if hasattr(os, 'copy_file_range'):
copyfile = copyfile_reflink
copy_file_range = os.copy_file_range
elif sys.platform == 'linux' and platform.machine() == 'x86_64' and sizeof(c_void_p) == 8:
copyfile = copyfile_reflink
copy_file_range = copy_file_range_ctypes
else:
copyfile = shutil.copyfile
def try_copyfile(src, dst):
try:
if os.path.isdir(dst):
dstfile = dst + "/" + os.path.basename(src)
if file_exists(dstfile, follow_symlinks=False):
os.remove(dstfile)
elif file_exists(dst, follow_symlinks=False):
dst = dst + "/" + os.path.basename(src)
if file_exists(dst, follow_symlinks=False):
os.remove(dst)
shutil.copyfile(src, dst)
copyfile(src, dst)
except PermissionError as e:
if e.errno == errno.EPERM:
#be forgiving about permissions errors; if it's a real problem, things will explode later anyway
@ -343,15 +404,15 @@ def set_dir_casefold_bit(dir_path):
class Proton:
def __init__(self, base_dir):
self.base_dir = base_dir + "/"
self.dist_dir = self.path("dist/")
self.bin_dir = self.path("dist/bin/")
self.lib_dir = self.path("dist/lib/")
self.lib64_dir = self.path("dist/lib64/")
self.fonts_dir = self.path("dist/share/fonts/")
self.wine_fonts_dir = self.path("dist/share/wine/fonts/")
self.wine_inf = self.path("dist/share/wine/wine.inf")
self.dist_dir = self.path("files/")
self.bin_dir = self.path("files/bin/")
self.lib_dir = self.path("files/lib/")
self.lib64_dir = self.path("files/lib64/")
self.fonts_dir = self.path("files/share/fonts/")
self.wine_fonts_dir = self.path("files/share/wine/fonts/")
self.wine_inf = self.path("files/share/wine/wine.inf")
self.version_file = self.path("version")
self.default_pfx_dir = self.path("dist/share/default_pfx/")
self.default_pfx_dir = self.path("files/share/default_pfx/")
self.user_settings_file = self.path("user_settings.py")
self.wine_bin = self.bin_dir + "wine"
self.wine64_bin = self.bin_dir + "wine64"
@ -361,28 +422,34 @@ class Proton:
def path(self, d):
return self.base_dir + d
def need_tarball_extraction(self):
'''Checks if the proton_dist tarball archive must be extracted. Returns true if extraction is needed, false otherwise'''
return not file_exists(self.dist_dir, follow_symlinks=True) or \
not file_exists(self.path("dist/version"), follow_symlinks=True) or \
not filecmp.cmp(self.version_file, self.path("dist/version"))
def cleanup_legacy_dist(self):
old_dist_dir = self.path("dist/")
if file_exists(old_dist_dir, follow_symlinks=True):
with self.dist_lock:
if file_exists(old_dist_dir, follow_symlinks=True):
shutil.rmtree(old_dist_dir)
def extract_tarball(self):
with self.dist_lock:
if self.need_tarball_extraction():
if file_exists(self.dist_dir, follow_symlinks=True):
shutil.rmtree(self.dist_dir)
tar = None
for sf in ["", ".xz", ".bz2", ".gz"]:
if file_exists(self.path("proton_dist.tar" + sf), follow_symlinks=True):
tar = tarfile.open(self.path("proton_dist.tar" + sf), mode="r:*")
break
if not tar:
log("No proton_dist tarball??")
sys.exit(1)
tar.extractall(path=self.dist_dir)
tar.close()
try_copy(self.version_file, self.dist_dir)
def do_steampipe_fixups(self):
fixups_json = self.path("steampipe_fixups.json")
fixups_mtime = self.path("files/steampipe_fixups_mtime")
if file_exists(fixups_json, follow_symlinks=True):
with self.dist_lock:
import steampipe_fixups
current_fixup_mtime = None
if file_exists(fixups_mtime, follow_symlinks=True):
with open(fixups_mtime, "r") as f:
current_fixup_mtime = f.readline().strip()
new_fixup_mtime = getmtimestr(fixups_json)
if current_fixup_mtime != new_fixup_mtime:
result_code = steampipe_fixups.do_restore(self.base_dir, fixups_json)
if result_code == 0:
with open(fixups_mtime, "w") as f:
f.write(new_fixup_mtime + "\n")
def missing_default_prefix(self):
'''Check if the default prefix dir is missing. Returns true if missing, false if present'''
@ -719,6 +786,12 @@ class CompatData:
self.migrate_user_paths()
if not file_exists(self.prefix_dir + "/dosdevices/c:", follow_symlinks=False):
os.symlink("../drive_c", self.prefix_dir + "/dosdevices/c:")
if not file_exists(self.prefix_dir + "/dosdevices/z:", follow_symlinks=False):
os.symlink("/", self.prefix_dir + "/dosdevices/z:")
# collect configuration info
steamdir = os.environ["STEAM_COMPAT_CLIENT_INSTALL_PATH"]
@ -920,18 +993,26 @@ def default_compat_config():
#affected by CW bug 19126
"252490", #Rust
"305620", #The Long Dark
"536280", #Disintegration
"585420", #Trailmakers
"684450", #Surviving the Aftermath
"700580", #Rust Staging
"707030", #POSTAL 4: No Regerts
"780290", #Gloomhaven
"844260", #Rustler
"960170", #DJMAX RESPECT V
"983970", #Haven
"1075200", #TOHU
"1096530", #Solasta: Crown of the Magister
"1102190", #Monster Train
"1107790", #The Complex
"1110100", #Power Rangers: Battle for the Grid
"1135230", #Ember Knights
"1161580", #Hardspace: Shipbreaker
"1190000", #Car Mechanic Simulator 2021
"1331440", #FUSER
"1341290", #We Were Here Forever
"1361320", #The Room 4: Old Sins
"1523720", #Cook-Out
"1913910", #Nine Sols Demo
@ -1071,6 +1152,7 @@ class Session:
self.env.setdefault("WINEDEBUG", "+timestamp,+pid,+tid,+seh,+unwind,+debugstr,+loaddll,+mscoree")
self.env.setdefault("DXVK_LOG_LEVEL", "info")
self.env.setdefault("VKD3D_DEBUG", "warn")
self.env.setdefault("VKD3D_SHADER_DEBUG", "fixme")
self.env.setdefault("WINE_MONO_TRACE", "E:System.NotImplementedException")
if self.env["PROTON_LOG"] != "1":
@ -1080,6 +1162,7 @@ class Session:
self.env.setdefault("WINEDEBUG", "-all")
self.env.setdefault("DXVK_LOG_LEVEL", "none")
self.env.setdefault("VKD3D_DEBUG", "none")
self.env.setdefault("VKD3D_SHADER_DEBUG", "none")
#disable XIM support until libx11 >= 1.7 is widespread
self.env.setdefault("WINE_ALLOW_XIM", "0")
@ -1377,8 +1460,8 @@ if __name__ == "__main__":
g_proton = Proton(os.path.dirname(sys.argv[0]))
if g_proton.need_tarball_extraction():
g_proton.extract_tarball()
g_proton.cleanup_legacy_dist()
g_proton.do_steampipe_fixups()
g_compatdata = CompatData(os.environ["STEAM_COMPAT_DATA_PATH"])

116
steampipe_fixups.py Executable file
View File

@ -0,0 +1,116 @@
#!/usr/bin/env python3
#Steampipe doesn't support certain unix-y things which may be required by
#native Linux applications. This file will process a directory of Linux files
#and store the file properties into a manifest file. After a round trip through
#Steampipe, the original file properties can be restored using this same
#script.
import json
import os
import secrets
import stat
DEFAULT_MANIFEST_NAME = "steampipe_fixups.json"
def usage():
print("Usage:")
print("\t" + sys.argv[0] + "\tprepare\t<path to directory to process>\t[manifest output file]")
print("\t\tProcess the given path and output the manifest file to the given path, or <path/" + DEFAULT_MANIFEST_NAME + "> if unspecified.")
print("")
print("\t" + sys.argv[0] + "\trestore\t<path to directory to process>\t[manifest file]")
print("\t\tRestore the given path using the manifest file, or <path/" + DEFAULT_MANIFEST_NAME + "> if unspecified.")
empty_dirs = []
no_write_paths = []
def canonicalize(path, prefix):
return path.replace(prefix, "", 1).lstrip('/')
def process_dir(path):
for root, subdirs, files in os.walk(path):
if len(subdirs) == 0 and len(files) == 0:
empty_dirs.append(canonicalize(root, path))
for file_ in files:
this_file = os.path.join(root, file_)
stat_result = os.lstat(this_file)
if (stat_result.st_mode & stat.S_IWUSR) == 0:
no_write_paths.append(canonicalize(this_file, path))
return 0
def write_manifest(manifest):
out = open(manifest, "w")
json.dump(
{
"id": str(secrets.randbits(32)), #we need steampipe to update this file for every build
"empty_dirs": empty_dirs,
"no_write_paths": no_write_paths,
},
out,
indent = 4,
sort_keys = True
)
return 0
def do_process(path, manifest):
if os.path.exists(manifest):
os.remove(manifest)
ret = process_dir(path)
if ret != 0:
return ret
#output should be deterministic
empty_dirs.sort()
no_write_paths.sort()
ret = write_manifest(manifest)
if ret != 0:
return ret
return 0
def do_restore(path, manifest):
loaded = json.load(open(manifest, "r"))
empty_dirs = loaded["empty_dirs"]
no_write_paths = loaded["no_write_paths"]
for empty_dir in empty_dirs:
try:
os.makedirs(os.path.join(path, empty_dir))
except OSError:
#already exists
pass
for file_ in no_write_paths:
this_file = os.path.join(path, file_)
stat_result = os.lstat(this_file)
os.chmod(this_file,
stat_result.st_mode & ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH))
return 0
if __name__ == '__main__':
import sys
if len(sys.argv) < 3 or len(sys.argv) > 4:
usage()
sys.exit(1)
verb = sys.argv[1]
path = sys.argv[2]
if len(sys.argv) >= 4:
manifest = sys.argv[3]
else:
manifest = os.path.join(path, DEFAULT_MANIFEST_NAME)
if verb == "process":
sys.exit(do_process(path, manifest))
if verb == "restore":
sys.exit(do_restore(path, manifest))
usage()
sys.exit(1)

View File

@ -15,6 +15,9 @@ user_settings = {
#vkd3d debug logging
"VKD3D_DEBUG": "warn",
#vkd3d-shader debug logging
"VKD3D_SHADER_DEBUG": "fixme",
#wine-mono debug logging (Wine's .NET replacement)
"WINE_MONO_TRACE": "E:System.NotImplementedException",
#"MONO_LOG_LEVEL": "info",

@ -1 +1 @@
Subproject commit 3e5aab6fb3e18f81a71b339be4cb5cdf55140980
Subproject commit 1a773cfb713366948c0c76cada6453b2687f49cd

2
wine

@ -1 +1 @@
Subproject commit df982e6865c2041ae994ee20ed2a2075ae7ddfb7
Subproject commit c112726751518c818fb4cb5bcf4212c9cb14af22