Initial commit: Windrose Dedicated Server
This commit is contained in:
commit
d4430ef869
14 files changed
+3718
No files matched your search
+11
@@ -0,0 +1,11 @@
|
|||||||
|
# Ignore environment variable files
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Ignore local runtime data
|
||||||
|
data/server/
|
||||||
|
data/logs/
|
||||||
|
data/wineprefix/
|
||||||
|
|
||||||
|
# Optional: ignore Docker build artifacts
|
||||||
|
*.pid
|
||||||
|
*.log
|
||||||
@@ -0,0 +1,302 @@
|
|||||||
|
Copyright (c) 2018-2020, Valve Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Browse the source code for more information
|
||||||
|
|
||||||
|
https://github.com/ValveSoftware/Proton
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains a modified version of Wine licensed under the LGPL 2.1. Wine is
|
||||||
|
|
||||||
|
Copyright (c) 1993-2020 the Wine project authors
|
||||||
|
|
||||||
|
Visit Wine at
|
||||||
|
|
||||||
|
https://winehq.org
|
||||||
|
|
||||||
|
View our modifications at
|
||||||
|
|
||||||
|
https://github.com/ValveSoftware/wine
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains a modified version of DXVK licensed under the zlib/libpng license. DXVK is
|
||||||
|
|
||||||
|
Copyright (c) 2017-2020 Philip Rebohle
|
||||||
|
Copyright (c) 2019-2020 Joshua Ashton
|
||||||
|
|
||||||
|
Visit DXVK at
|
||||||
|
|
||||||
|
https://github.com/doitsujin/dxvk
|
||||||
|
|
||||||
|
View our modifications at
|
||||||
|
|
||||||
|
https://github.com/ValveSoftware/dxvk
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains FAudio licensed under the zlib license. FAudio is
|
||||||
|
|
||||||
|
Copyright (c) 2011-2020 Ethan Lee, Luigi Auriemma, and the MonoGame Team
|
||||||
|
|
||||||
|
Visit FAudio at
|
||||||
|
|
||||||
|
https://github.com/FNA-XNA/FAudio
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains glib licensed under the LGPL 2.1.
|
||||||
|
|
||||||
|
Visit glib at
|
||||||
|
|
||||||
|
https://wiki.gnome.org/Projects/GLib
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains gstreamer, gst-plugins-base, and gst-plugins-good licensed under the LGPL 2.
|
||||||
|
|
||||||
|
Visit gstreamer at
|
||||||
|
|
||||||
|
https://gstreamer.freedesktop.org/
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains some Liberation Fonts licensed under the SIL Open Font License, available at LICENSE.OFL. These fonts are
|
||||||
|
|
||||||
|
Copyright (c) 2010 Google Corporation
|
||||||
|
Copyright (c) 2012 Red Hat, Inc.
|
||||||
|
|
||||||
|
Visit Liberation Fonts at
|
||||||
|
|
||||||
|
https://github.com/liberationfonts/liberation-fonts
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains Source Han Sans licensed under the SIL Open Font License, available at LICENSE.OFL. This font is
|
||||||
|
|
||||||
|
Copyright 2014-2019 Adobe (http://www.adobe.com/)
|
||||||
|
|
||||||
|
Visit Source Han Sans at
|
||||||
|
|
||||||
|
https://github.com/adobe-fonts/source-han-sans
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains wine-mono, parts of which are included under a variety of licenses.
|
||||||
|
|
||||||
|
Parts of Mono (mono/) are variously licensed under the GPL, LGPL, and MIT X11 licenses. All parts are available as LGPL or MIT X11 except for the following:
|
||||||
|
* The ICSharpCode.SharpZipLib library is available as GPL with an exception (see mono/mcs/class/ICSharpCode.SharpZipLib/README).
|
||||||
|
* mcs/jay is BSD-licensed.
|
||||||
|
|
||||||
|
The Visual Basic class libraries (mono-basic/) are MIT X11. The compiler is LGPL v2.
|
||||||
|
|
||||||
|
FNA is a mix of MSPL and MIT. It has the following library dependencies:
|
||||||
|
* FAudio, MojoShader, Theorafile, SDL2, SDL_image_compact, and SDL2-CS are zlib-licensed. SDL2-CS is built into FNA.dll.
|
||||||
|
* FNA.NetStub is MSPL.
|
||||||
|
|
||||||
|
The winforms and wpf libraries are MIT.
|
||||||
|
|
||||||
|
wine-mono itself is included under the MIT license. wine-mono is
|
||||||
|
|
||||||
|
Copyright (c) 2012 Vincent Povirk for CodeWeavers
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
Visit wine-mono at
|
||||||
|
|
||||||
|
https://github.com/madewokherd/wine-mono
|
||||||
|
|
||||||
|
View wine-mono's complete license at
|
||||||
|
|
||||||
|
https://github.com/madewokherd/wine-mono/blob/master/COPYING
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains wine-gecko, parts of which are included under a variety of licenses.
|
||||||
|
|
||||||
|
wine-gecko itself is included under the Mozilla Public License 2.0.
|
||||||
|
|
||||||
|
wine-gecko is available in Source Code form at
|
||||||
|
|
||||||
|
https://sourceforge.net/p/wine/wine-gecko
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains a modified version of Vkd3d licensed under the LGPL 2.1. Vkd3d is
|
||||||
|
|
||||||
|
Copyright 2016-2019 the Vkd3d project authors
|
||||||
|
|
||||||
|
Visit Vkd3d at
|
||||||
|
|
||||||
|
https://source.winehq.org/git/vkd3d.git
|
||||||
|
|
||||||
|
View our modifications at
|
||||||
|
|
||||||
|
https://github.com/ValveSoftware/vkd3d
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
This software contains orc. Orc is
|
||||||
|
|
||||||
|
Copyright 2002 - 2009 David A. Schleef <ds@schleef.org>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||||
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
The source code implementing the Mersenne Twister algorithm is
|
||||||
|
subject to the following license:
|
||||||
|
|
||||||
|
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Visit orc at
|
||||||
|
|
||||||
|
https://gitlab.freedesktop.org/gstreamer/orc
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
Parts of this software are based on the OpenVR SDK, which is
|
||||||
|
|
||||||
|
Copyright (c) 2015, Valve Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Visit OpenVR at
|
||||||
|
|
||||||
|
https://github.com/ValveSoftware/openvr
|
||||||
|
|
||||||
|
---- ---- ---- ----
|
||||||
|
|
||||||
|
Parts of this software are based on the AMD AGS library, which is
|
||||||
|
|
||||||
|
Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
Digitized data copyright (c) 2010 Google Corporation
|
||||||
|
with Reserved Font Arimo, Tinos and Cousine.
|
||||||
|
Copyright (c) 2012 Red Hat, Inc.
|
||||||
|
with Reserved Font Name Liberation.
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License,
|
||||||
|
Version 1.1.
|
||||||
|
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
|
||||||
|
PREAMBLE The goals of the Open Font License (OFL) are to stimulate
|
||||||
|
worldwide development of collaborative font projects, to support the font
|
||||||
|
creation efforts of academic and linguistic communities, and to provide
|
||||||
|
a free and open framework in which fonts may be shared and improved in
|
||||||
|
partnership with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves.
|
||||||
|
The fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply to
|
||||||
|
any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such.
|
||||||
|
This may include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components
|
||||||
|
as distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting ? in part or in whole ?
|
||||||
|
any of the components of the Original Version, by changing formats or
|
||||||
|
by porting the Font Software to a new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical writer
|
||||||
|
or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,in
|
||||||
|
Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the
|
||||||
|
corresponding Copyright Holder. This restriction only applies to the
|
||||||
|
primary font name as presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole, must
|
||||||
|
be distributed entirely under this license, and must not be distributed
|
||||||
|
under any other license. The requirement for fonts to remain under
|
||||||
|
this license does not apply to any document created using the Font
|
||||||
|
Software.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are not met.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
||||||
|
DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
|
||||||
@@ -0,0 +1,451 @@
|
|||||||
|
# This is free and unencumbered software released into the public domain.
|
||||||
|
#
|
||||||
|
# Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
# distribute this software, either in source code form or as a compiled
|
||||||
|
# binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
# means.
|
||||||
|
#
|
||||||
|
# In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
# of this software dedicate any and all copyright interest in the
|
||||||
|
# software to the public domain. We make this dedication for the benefit
|
||||||
|
# of the public at large and to the detriment of our heirs and
|
||||||
|
# successors. We intend this dedication to be an overt act of
|
||||||
|
# relinquishment in perpetuity of all present and future rights to this
|
||||||
|
# software under copyright law.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
# OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# For more information, please refer to <http://unlicense.org>
|
||||||
|
|
||||||
|
"""
|
||||||
|
A platform independent file lock that supports the with-statement.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
# Modules
|
||||||
|
# ------------------------------------------------
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
try:
|
||||||
|
import warnings
|
||||||
|
except ImportError:
|
||||||
|
warnings = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import msvcrt
|
||||||
|
except ImportError:
|
||||||
|
msvcrt = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import fcntl
|
||||||
|
except ImportError:
|
||||||
|
fcntl = None
|
||||||
|
|
||||||
|
|
||||||
|
# Backward compatibility
|
||||||
|
# ------------------------------------------------
|
||||||
|
try:
|
||||||
|
TimeoutError
|
||||||
|
except NameError:
|
||||||
|
TimeoutError = OSError
|
||||||
|
|
||||||
|
|
||||||
|
# Data
|
||||||
|
# ------------------------------------------------
|
||||||
|
__all__ = [
|
||||||
|
"Timeout",
|
||||||
|
"BaseFileLock",
|
||||||
|
"WindowsFileLock",
|
||||||
|
"UnixFileLock",
|
||||||
|
"SoftFileLock",
|
||||||
|
"FileLock"
|
||||||
|
]
|
||||||
|
|
||||||
|
__version__ = "3.0.12"
|
||||||
|
|
||||||
|
|
||||||
|
_logger = None
|
||||||
|
def logger():
|
||||||
|
"""Returns the logger instance used in this module."""
|
||||||
|
global _logger
|
||||||
|
_logger = _logger or logging.getLogger(__name__)
|
||||||
|
return _logger
|
||||||
|
|
||||||
|
|
||||||
|
# Exceptions
|
||||||
|
# ------------------------------------------------
|
||||||
|
class Timeout(TimeoutError):
|
||||||
|
"""
|
||||||
|
Raised when the lock could not be acquired in *timeout*
|
||||||
|
seconds.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, lock_file):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
#: The path of the file lock.
|
||||||
|
self.lock_file = lock_file
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
temp = "The file lock '{}' could not be acquired."\
|
||||||
|
.format(self.lock_file)
|
||||||
|
return temp
|
||||||
|
|
||||||
|
|
||||||
|
# Classes
|
||||||
|
# ------------------------------------------------
|
||||||
|
|
||||||
|
# This is a helper class which is returned by :meth:`BaseFileLock.acquire`
|
||||||
|
# and wraps the lock to make sure __enter__ is not called twice when entering
|
||||||
|
# the with statement.
|
||||||
|
# If we would simply return *self*, the lock would be acquired again
|
||||||
|
# in the *__enter__* method of the BaseFileLock, but not released again
|
||||||
|
# automatically.
|
||||||
|
#
|
||||||
|
# :seealso: issue #37 (memory leak)
|
||||||
|
class _Acquire_ReturnProxy(object):
|
||||||
|
|
||||||
|
def __init__(self, lock):
|
||||||
|
self.lock = lock
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self.lock
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
|
self.lock.release()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class BaseFileLock(object):
|
||||||
|
"""
|
||||||
|
Implements the base class of a file lock.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, lock_file, timeout = -1):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
# The path to the lock file.
|
||||||
|
self._lock_file = lock_file
|
||||||
|
|
||||||
|
# The file descriptor for the *_lock_file* as it is returned by the
|
||||||
|
# os.open() function.
|
||||||
|
# This file lock is only NOT None, if the object currently holds the
|
||||||
|
# lock.
|
||||||
|
self._lock_file_fd = None
|
||||||
|
|
||||||
|
# The default timeout value.
|
||||||
|
self.timeout = timeout
|
||||||
|
|
||||||
|
# We use this lock primarily for the lock counter.
|
||||||
|
self._thread_lock = threading.Lock()
|
||||||
|
|
||||||
|
# The lock counter is used for implementing the nested locking
|
||||||
|
# mechanism. Whenever the lock is acquired, the counter is increased and
|
||||||
|
# the lock is only released, when this value is 0 again.
|
||||||
|
self._lock_counter = 0
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lock_file(self):
|
||||||
|
"""
|
||||||
|
The path to the lock file.
|
||||||
|
"""
|
||||||
|
return self._lock_file
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timeout(self):
|
||||||
|
"""
|
||||||
|
You can set a default timeout for the filelock. It will be used as
|
||||||
|
fallback value in the acquire method, if no timeout value (*None*) is
|
||||||
|
given.
|
||||||
|
|
||||||
|
If you want to disable the timeout, set it to a negative value.
|
||||||
|
|
||||||
|
A timeout of 0 means, that there is exactly one attempt to acquire the
|
||||||
|
file lock.
|
||||||
|
|
||||||
|
.. versionadded:: 2.0.0
|
||||||
|
"""
|
||||||
|
return self._timeout
|
||||||
|
|
||||||
|
@timeout.setter
|
||||||
|
def timeout(self, value):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
self._timeout = float(value)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Platform dependent locking
|
||||||
|
# --------------------------------------------
|
||||||
|
|
||||||
|
def _acquire(self):
|
||||||
|
"""
|
||||||
|
Platform dependent. If the file lock could be
|
||||||
|
acquired, self._lock_file_fd holds the file descriptor
|
||||||
|
of the lock file.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def _release(self):
|
||||||
|
"""
|
||||||
|
Releases the lock and sets self._lock_file_fd to None.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
# Platform independent methods
|
||||||
|
# --------------------------------------------
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_locked(self):
|
||||||
|
"""
|
||||||
|
True, if the object holds the file lock.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.0.0
|
||||||
|
|
||||||
|
This was previously a method and is now a property.
|
||||||
|
"""
|
||||||
|
return self._lock_file_fd is not None
|
||||||
|
|
||||||
|
def acquire(self, timeout=None, poll_intervall=0.05):
|
||||||
|
"""
|
||||||
|
Acquires the file lock or fails with a :exc:`Timeout` error.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# You can use this method in the context manager (recommended)
|
||||||
|
with lock.acquire():
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Or use an equivalent try-finally construct:
|
||||||
|
lock.acquire()
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
|
||||||
|
:arg float timeout:
|
||||||
|
The maximum time waited for the file lock.
|
||||||
|
If ``timeout < 0``, there is no timeout and this method will
|
||||||
|
block until the lock could be acquired.
|
||||||
|
If ``timeout`` is None, the default :attr:`~timeout` is used.
|
||||||
|
|
||||||
|
:arg float poll_intervall:
|
||||||
|
We check once in *poll_intervall* seconds if we can acquire the
|
||||||
|
file lock.
|
||||||
|
|
||||||
|
:raises Timeout:
|
||||||
|
if the lock could not be acquired in *timeout* seconds.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.0.0
|
||||||
|
|
||||||
|
This method returns now a *proxy* object instead of *self*,
|
||||||
|
so that it can be used in a with statement without side effects.
|
||||||
|
"""
|
||||||
|
# Use the default timeout, if no timeout is provided.
|
||||||
|
if timeout is None:
|
||||||
|
timeout = self.timeout
|
||||||
|
|
||||||
|
# Increment the number right at the beginning.
|
||||||
|
# We can still undo it, if something fails.
|
||||||
|
with self._thread_lock:
|
||||||
|
self._lock_counter += 1
|
||||||
|
|
||||||
|
lock_id = id(self)
|
||||||
|
lock_filename = self._lock_file
|
||||||
|
start_time = time.time()
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
with self._thread_lock:
|
||||||
|
if not self.is_locked:
|
||||||
|
logger().debug('Attempting to acquire lock %s on %s', lock_id, lock_filename)
|
||||||
|
self._acquire()
|
||||||
|
|
||||||
|
if self.is_locked:
|
||||||
|
logger().info('Lock %s acquired on %s', lock_id, lock_filename)
|
||||||
|
break
|
||||||
|
elif timeout >= 0 and time.time() - start_time > timeout:
|
||||||
|
logger().debug('Timeout on acquiring lock %s on %s', lock_id, lock_filename)
|
||||||
|
raise Timeout(self._lock_file)
|
||||||
|
else:
|
||||||
|
logger().debug(
|
||||||
|
'Lock %s not acquired on %s, waiting %s seconds ...',
|
||||||
|
lock_id, lock_filename, poll_intervall
|
||||||
|
)
|
||||||
|
time.sleep(poll_intervall)
|
||||||
|
except:
|
||||||
|
# Something did go wrong, so decrement the counter.
|
||||||
|
with self._thread_lock:
|
||||||
|
self._lock_counter = max(0, self._lock_counter - 1)
|
||||||
|
|
||||||
|
raise
|
||||||
|
return _Acquire_ReturnProxy(lock = self)
|
||||||
|
|
||||||
|
def release(self, force = False):
|
||||||
|
"""
|
||||||
|
Releases the file lock.
|
||||||
|
|
||||||
|
Please note, that the lock is only completly released, if the lock
|
||||||
|
counter is 0.
|
||||||
|
|
||||||
|
Also note, that the lock file itself is not automatically deleted.
|
||||||
|
|
||||||
|
:arg bool force:
|
||||||
|
If true, the lock counter is ignored and the lock is released in
|
||||||
|
every case.
|
||||||
|
"""
|
||||||
|
with self._thread_lock:
|
||||||
|
|
||||||
|
if self.is_locked:
|
||||||
|
self._lock_counter -= 1
|
||||||
|
|
||||||
|
if self._lock_counter == 0 or force:
|
||||||
|
lock_id = id(self)
|
||||||
|
lock_filename = self._lock_file
|
||||||
|
|
||||||
|
logger().debug('Attempting to release lock %s on %s', lock_id, lock_filename)
|
||||||
|
self._release()
|
||||||
|
self._lock_counter = 0
|
||||||
|
logger().info('Lock %s released on %s', lock_id, lock_filename)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.acquire()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
|
self.release()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.release(force = True)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
# Windows locking mechanism
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
class WindowsFileLock(BaseFileLock):
|
||||||
|
"""
|
||||||
|
Uses the :func:`msvcrt.locking` function to hard lock the lock file on
|
||||||
|
windows systems.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _acquire(self):
|
||||||
|
open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC
|
||||||
|
|
||||||
|
try:
|
||||||
|
fd = os.open(self._lock_file, open_mode)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
|
||||||
|
except (IOError, OSError):
|
||||||
|
os.close(fd)
|
||||||
|
else:
|
||||||
|
self._lock_file_fd = fd
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _release(self):
|
||||||
|
fd = self._lock_file_fd
|
||||||
|
self._lock_file_fd = None
|
||||||
|
msvcrt.locking(fd, msvcrt.LK_UNLCK, 1)
|
||||||
|
os.close(fd)
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.remove(self._lock_file)
|
||||||
|
# Probably another instance of the application
|
||||||
|
# that acquired the file lock.
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Unix locking mechanism
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
class UnixFileLock(BaseFileLock):
|
||||||
|
"""
|
||||||
|
Uses the :func:`fcntl.flock` to hard lock the lock file on unix systems.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _acquire(self):
|
||||||
|
open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC
|
||||||
|
fd = os.open(self._lock_file, open_mode)
|
||||||
|
|
||||||
|
try:
|
||||||
|
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
|
except (IOError, OSError):
|
||||||
|
os.close(fd)
|
||||||
|
else:
|
||||||
|
self._lock_file_fd = fd
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _release(self):
|
||||||
|
# Do not remove the lockfile:
|
||||||
|
#
|
||||||
|
# https://github.com/benediktschmitt/py-filelock/issues/31
|
||||||
|
# https://stackoverflow.com/questions/17708885/flock-removing-locked-file-without-race-condition
|
||||||
|
fd = self._lock_file_fd
|
||||||
|
self._lock_file_fd = None
|
||||||
|
fcntl.flock(fd, fcntl.LOCK_UN)
|
||||||
|
os.close(fd)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Soft lock
|
||||||
|
# ~~~~~~~~~
|
||||||
|
|
||||||
|
class SoftFileLock(BaseFileLock):
|
||||||
|
"""
|
||||||
|
Simply watches the existence of the lock file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _acquire(self):
|
||||||
|
open_mode = os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_TRUNC
|
||||||
|
try:
|
||||||
|
fd = os.open(self._lock_file, open_mode)
|
||||||
|
except (IOError, OSError):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self._lock_file_fd = fd
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _release(self):
|
||||||
|
os.close(self._lock_file_fd)
|
||||||
|
self._lock_file_fd = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.remove(self._lock_file)
|
||||||
|
# The file is already deleted and that's what we want.
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
# Platform filelock
|
||||||
|
# ~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
#: Alias for the lock, which should be used for the current platform. On
|
||||||
|
#: Windows, this is an alias for :class:`WindowsFileLock`, on Unix for
|
||||||
|
#: :class:`UnixFileLock` and otherwise for :class:`SoftFileLock`.
|
||||||
|
FileLock = None
|
||||||
|
|
||||||
|
if msvcrt:
|
||||||
|
FileLock = WindowsFileLock
|
||||||
|
elif fcntl:
|
||||||
|
FileLock = UnixFileLock
|
||||||
|
else:
|
||||||
|
FileLock = SoftFileLock
|
||||||
|
|
||||||
|
if warnings is not None:
|
||||||
|
warnings.warn("only soft file lock is available")
|
||||||
@@ -0,0 +1,725 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
#script to launch Wine with the correct environment
|
||||||
|
|
||||||
|
import fcntl
|
||||||
|
import array
|
||||||
|
import filecmp
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import errno
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tarfile
|
||||||
|
|
||||||
|
from filelock import FileLock
|
||||||
|
|
||||||
|
#To enable debug logging, copy "user_settings.sample.py" to "user_settings.py"
|
||||||
|
#and edit it if needed.
|
||||||
|
|
||||||
|
CURRENT_PREFIX_VERSION="5.0-1"
|
||||||
|
|
||||||
|
PFX="Proton: "
|
||||||
|
ld_path_var = "LD_LIBRARY_PATH"
|
||||||
|
|
||||||
|
def nonzero(s):
|
||||||
|
return len(s) > 0 and s != "0"
|
||||||
|
|
||||||
|
def log(msg):
|
||||||
|
sys.stderr.write(PFX + msg + os.linesep)
|
||||||
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
def file_is_wine_fake_dll(path):
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
sfile = open(path, "rb")
|
||||||
|
sfile.seek(0x40)
|
||||||
|
tag = sfile.read(20)
|
||||||
|
return tag == b"Wine placeholder DLL"
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def makedirs(path):
|
||||||
|
try:
|
||||||
|
os.makedirs(path)
|
||||||
|
except OSError:
|
||||||
|
#already exists
|
||||||
|
pass
|
||||||
|
|
||||||
|
def try_copy(src, dst):
|
||||||
|
try:
|
||||||
|
if os.path.isdir(dst):
|
||||||
|
dstfile = dst + "/" + os.path.basename(src)
|
||||||
|
if os.path.lexists(dstfile):
|
||||||
|
os.remove(dstfile)
|
||||||
|
elif os.path.lexists(dst):
|
||||||
|
os.remove(dst)
|
||||||
|
shutil.copy(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
|
||||||
|
log('Error while copying to \"' + dst + '\": ' + e.strerror)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def real_copy(src, dst):
|
||||||
|
if os.path.islink(src):
|
||||||
|
os.symlink(os.readlink(src), dst)
|
||||||
|
else:
|
||||||
|
try_copy(src, dst)
|
||||||
|
|
||||||
|
EXT2_IOC_GETFLAGS = 0x80086601
|
||||||
|
EXT2_IOC_SETFLAGS = 0x40086602
|
||||||
|
|
||||||
|
EXT4_CASEFOLD_FL = 0x40000000
|
||||||
|
|
||||||
|
def set_dir_casefold_bit(dir_path):
|
||||||
|
dr = os.open(dir_path, 0o644)
|
||||||
|
if dr < 0:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
dat = array.array('I', [0])
|
||||||
|
if fcntl.ioctl(dr, EXT2_IOC_GETFLAGS, dat, True) >= 0:
|
||||||
|
dat[0] = dat[0] | EXT4_CASEFOLD_FL
|
||||||
|
fcntl.ioctl(dr, EXT2_IOC_SETFLAGS, dat, False)
|
||||||
|
except (OSError, IOError):
|
||||||
|
#no problem
|
||||||
|
pass
|
||||||
|
os.close(dr)
|
||||||
|
|
||||||
|
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.version_file = self.path("version")
|
||||||
|
self.default_pfx_dir = self.path("dist/share/default_pfx/")
|
||||||
|
self.user_settings_file = self.path("user_settings.py")
|
||||||
|
self.wine_bin = self.bin_dir + "wine"
|
||||||
|
self.wineserver_bin = self.bin_dir + "wineserver"
|
||||||
|
self.dist_lock = FileLock(self.path("dist.lock"), timeout=-1)
|
||||||
|
|
||||||
|
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 os.path.exists(self.dist_dir) or \
|
||||||
|
not os.path.exists(self.path("dist/version")) or \
|
||||||
|
not filecmp.cmp(self.version_file, self.path("dist/version"))
|
||||||
|
|
||||||
|
def extract_tarball(self):
|
||||||
|
with self.dist_lock:
|
||||||
|
if self.need_tarball_extraction():
|
||||||
|
if os.path.exists(self.dist_dir):
|
||||||
|
shutil.rmtree(self.dist_dir)
|
||||||
|
tar = None
|
||||||
|
for sf in ["", ".xz", ".bz2", ".gz"]:
|
||||||
|
if os.path.exists(self.path("proton_dist.tar" + sf)):
|
||||||
|
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 missing_default_prefix(self):
|
||||||
|
'''Check if the default prefix dir is missing. Returns true if missing, false if present'''
|
||||||
|
return not os.path.isdir(self.default_pfx_dir)
|
||||||
|
|
||||||
|
def make_default_prefix(self):
|
||||||
|
with self.dist_lock:
|
||||||
|
local_env = dict(g_session.env)
|
||||||
|
if self.missing_default_prefix():
|
||||||
|
#make default prefix
|
||||||
|
local_env["WINEPREFIX"] = self.default_pfx_dir
|
||||||
|
local_env["WINEDEBUG"] = "-all"
|
||||||
|
g_session.run_proc([self.wine_bin, "wineboot"], local_env)
|
||||||
|
g_session.run_proc([self.wineserver_bin, "-w"], local_env)
|
||||||
|
|
||||||
|
class CompatData:
|
||||||
|
def __init__(self, compatdata):
|
||||||
|
self.base_dir = compatdata + "/"
|
||||||
|
self.prefix_dir = self.path("pfx/")
|
||||||
|
self.version_file = self.path("version")
|
||||||
|
self.tracked_files_file = self.path("tracked_files")
|
||||||
|
self.prefix_lock = FileLock(self.path("pfx.lock"), timeout=-1)
|
||||||
|
|
||||||
|
def path(self, d):
|
||||||
|
return self.base_dir + d
|
||||||
|
|
||||||
|
def remove_tracked_files(self):
|
||||||
|
if not os.path.exists(self.tracked_files_file):
|
||||||
|
log("Prefix has no tracked_files??")
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(self.tracked_files_file, "r") as tracked_files:
|
||||||
|
dirs = []
|
||||||
|
for f in tracked_files:
|
||||||
|
path = self.prefix_dir + f.strip()
|
||||||
|
if os.path.exists(path):
|
||||||
|
if os.path.isfile(path) or os.path.islink(path):
|
||||||
|
os.remove(path)
|
||||||
|
else:
|
||||||
|
dirs.append(path)
|
||||||
|
for d in dirs:
|
||||||
|
try:
|
||||||
|
os.rmdir(d)
|
||||||
|
except OSError:
|
||||||
|
#not empty
|
||||||
|
pass
|
||||||
|
|
||||||
|
os.remove(self.tracked_files_file)
|
||||||
|
os.remove(self.version_file)
|
||||||
|
|
||||||
|
def upgrade_pfx(self, old_ver):
|
||||||
|
if old_ver == CURRENT_PREFIX_VERSION:
|
||||||
|
return
|
||||||
|
|
||||||
|
log("Upgrading prefix from " + str(old_ver) + " to " + CURRENT_PREFIX_VERSION + " (" + self.base_dir + ")")
|
||||||
|
|
||||||
|
if old_ver is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not '-' in old_ver:
|
||||||
|
#How can this happen??
|
||||||
|
log("Prefix has an invalid version?! You may want to back up user files and delete this prefix.")
|
||||||
|
#If it does, just let the Wine upgrade happen and hope it works...
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
old_proton_ver, old_prefix_ver = old_ver.split('-')
|
||||||
|
old_proton_maj, old_proton_min = old_proton_ver.split('.')
|
||||||
|
new_proton_ver, new_prefix_ver = CURRENT_PREFIX_VERSION.split('-')
|
||||||
|
new_proton_maj, new_proton_min = new_proton_ver.split('.')
|
||||||
|
|
||||||
|
if int(new_proton_maj) < int(old_proton_maj) or \
|
||||||
|
(int(new_proton_maj) == int(old_proton_maj) and \
|
||||||
|
int(new_proton_min) < int(old_proton_min)):
|
||||||
|
log("Removing newer prefix")
|
||||||
|
if old_proton_ver == "3.7" and not os.path.exists(self.tracked_files_file):
|
||||||
|
#proton 3.7 did not generate tracked_files, so copy it into place first
|
||||||
|
try_copy(g_proton.path("proton_3.7_tracked_files"), self.tracked_files_file)
|
||||||
|
self.remove_tracked_files()
|
||||||
|
return
|
||||||
|
|
||||||
|
if old_proton_ver == "3.7" and old_prefix_ver == "1":
|
||||||
|
if not os.path.exists(self.prefix_dir + "/drive_c/windows/syswow64/kernel32.dll"):
|
||||||
|
#shipped a busted 64-bit-only installation on 20180822. detect and wipe clean
|
||||||
|
log("Detected broken 64-bit-only installation, re-creating prefix.")
|
||||||
|
shutil.rmtree(self.prefix_dir)
|
||||||
|
return
|
||||||
|
|
||||||
|
#replace broken .NET installations with wine-mono support
|
||||||
|
if os.path.exists(self.prefix_dir + "/drive_c/windows/Microsoft.NET/NETFXRepair.exe") and \
|
||||||
|
file_is_wine_fake_dll(self.prefix_dir + "/drive_c/windows/system32/mscoree.dll"):
|
||||||
|
log("Broken .NET installation detected, switching to wine-mono.")
|
||||||
|
#deleting this directory allows wine-mono to work
|
||||||
|
shutil.rmtree(self.prefix_dir + "/drive_c/windows/Microsoft.NET")
|
||||||
|
|
||||||
|
#prior to prefix version 4.11-2, all controllers were xbox controllers. wipe out the old registry entries.
|
||||||
|
if (int(old_proton_maj) < 4 or (int(old_proton_maj) == 4 and int(old_proton_min) == 11)) and \
|
||||||
|
int(old_prefix_ver) < 2:
|
||||||
|
log("Removing old xinput registry entries.")
|
||||||
|
with open(self.prefix_dir + "system.reg", "r") as reg_in:
|
||||||
|
with open(self.prefix_dir + "system.reg.new", "w") as reg_out:
|
||||||
|
for line in reg_in:
|
||||||
|
if line[0] == '[' and "CurrentControlSet" in line and "IG_" in line:
|
||||||
|
if "DeviceClasses" in line:
|
||||||
|
reg_out.write(line.replace("DeviceClasses", "DeviceClasses_old"))
|
||||||
|
elif "Enum" in line:
|
||||||
|
reg_out.write(line.replace("Enum", "Enum_old"))
|
||||||
|
else:
|
||||||
|
reg_out.write(line)
|
||||||
|
try:
|
||||||
|
os.rename(self.prefix_dir + "system.reg", self.prefix_dir + "system.reg.old")
|
||||||
|
except OSError:
|
||||||
|
os.remove(self.prefix_dir + "system.reg")
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.rename(self.prefix_dir + "system.reg.new", self.prefix_dir + "system.reg")
|
||||||
|
except OSError:
|
||||||
|
log("Unable to write new registry file to " + self.prefix_dir + "system.reg")
|
||||||
|
pass
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
log("Prefix has an invalid version?! You may want to back up user files and delete this prefix.")
|
||||||
|
#Just let the Wine upgrade happen and hope it works...
|
||||||
|
return
|
||||||
|
|
||||||
|
def copy_pfx(self):
|
||||||
|
with open(self.tracked_files_file, "w") as tracked_files:
|
||||||
|
for src_dir, dirs, files in os.walk(g_proton.default_pfx_dir):
|
||||||
|
rel_dir = src_dir.replace(g_proton.default_pfx_dir, "", 1).lstrip('/')
|
||||||
|
if len(rel_dir) > 0:
|
||||||
|
rel_dir = rel_dir + "/"
|
||||||
|
dst_dir = src_dir.replace(g_proton.default_pfx_dir, self.prefix_dir, 1)
|
||||||
|
if not os.path.exists(dst_dir):
|
||||||
|
os.makedirs(dst_dir)
|
||||||
|
tracked_files.write(rel_dir + "\n")
|
||||||
|
for dir_ in dirs:
|
||||||
|
src_file = os.path.join(src_dir, dir_)
|
||||||
|
dst_file = os.path.join(dst_dir, dir_)
|
||||||
|
if os.path.islink(src_file) and not os.path.exists(dst_file):
|
||||||
|
real_copy(src_file, dst_file)
|
||||||
|
for file_ in files:
|
||||||
|
src_file = os.path.join(src_dir, file_)
|
||||||
|
dst_file = os.path.join(dst_dir, file_)
|
||||||
|
if not os.path.exists(dst_file):
|
||||||
|
real_copy(src_file, dst_file)
|
||||||
|
tracked_files.write(rel_dir + file_ + "\n")
|
||||||
|
|
||||||
|
def create_fonts_symlinks(self):
|
||||||
|
fontsmap = [
|
||||||
|
( "LiberationSans-Regular.ttf", "arial.ttf" ),
|
||||||
|
( "LiberationSans-Bold.ttf", "arialbd.ttf" ),
|
||||||
|
( "LiberationSerif-Regular.ttf", "times.ttf" ),
|
||||||
|
( "LiberationMono-Regular.ttf", "cour.ttf" ),
|
||||||
|
( "SourceHanSansSCRegular.otf", "msyh.ttf" ),
|
||||||
|
]
|
||||||
|
|
||||||
|
windowsfonts = self.prefix_dir + "/drive_c/windows/Fonts"
|
||||||
|
makedirs(windowsfonts)
|
||||||
|
for p in fontsmap:
|
||||||
|
lname = os.path.join(windowsfonts, p[1])
|
||||||
|
fname = os.path.join(g_proton.fonts_dir, p[0])
|
||||||
|
if os.path.lexists(lname):
|
||||||
|
if os.path.islink(lname):
|
||||||
|
os.remove(lname)
|
||||||
|
os.symlink(fname, lname)
|
||||||
|
else:
|
||||||
|
os.symlink(fname, lname)
|
||||||
|
|
||||||
|
def setup_prefix(self):
|
||||||
|
with self.prefix_lock:
|
||||||
|
if os.path.exists(self.version_file):
|
||||||
|
with open(self.version_file, "r") as f:
|
||||||
|
self.upgrade_pfx(f.readline().strip())
|
||||||
|
else:
|
||||||
|
self.upgrade_pfx(None)
|
||||||
|
|
||||||
|
if not os.path.exists(self.prefix_dir):
|
||||||
|
makedirs(self.prefix_dir + "/drive_c")
|
||||||
|
set_dir_casefold_bit(self.prefix_dir + "/drive_c")
|
||||||
|
|
||||||
|
if not os.path.exists(self.prefix_dir + "/user.reg"):
|
||||||
|
self.copy_pfx()
|
||||||
|
|
||||||
|
with open(self.version_file, "w") as f:
|
||||||
|
f.write(CURRENT_PREFIX_VERSION + "\n")
|
||||||
|
|
||||||
|
#create font files symlinks
|
||||||
|
self.create_fonts_symlinks()
|
||||||
|
|
||||||
|
#copy steam files into place
|
||||||
|
if "STEAM_COMPAT_CLIENT_INSTALL_PATH" in os.environ:
|
||||||
|
#modern steam client sets this
|
||||||
|
steamdir = os.environ["STEAM_COMPAT_CLIENT_INSTALL_PATH"]
|
||||||
|
else:
|
||||||
|
#linux-only fallback, really shouldn't get here
|
||||||
|
steamdir = os.environ["HOME"] + ".steam/root/"
|
||||||
|
dst = self.prefix_dir + "/drive_c/Program Files (x86)/"
|
||||||
|
makedirs(dst + "Steam")
|
||||||
|
filestocopy = ["steamclient.dll",
|
||||||
|
"steamclient64.dll",
|
||||||
|
"Steam.dll"]
|
||||||
|
for f in filestocopy:
|
||||||
|
if os.path.isfile(steamdir + "/legacycompat/" + f):
|
||||||
|
dstfile = dst + "Steam/" + f
|
||||||
|
if os.path.isfile(dstfile):
|
||||||
|
os.remove(dstfile)
|
||||||
|
try_copy(steamdir + "/legacycompat/" + f, dstfile)
|
||||||
|
|
||||||
|
#copy openvr files into place
|
||||||
|
dst = self.prefix_dir + "/drive_c/vrclient/bin/"
|
||||||
|
makedirs(dst)
|
||||||
|
try_copy(g_proton.lib_dir + "wine/fakedlls/vrclient.dll", dst)
|
||||||
|
try_copy(g_proton.lib64_dir + "wine/fakedlls/vrclient_x64.dll", dst)
|
||||||
|
|
||||||
|
try_copy(g_proton.lib_dir + "wine/dxvk/openvr_api_dxvk.dll", self.prefix_dir + "/drive_c/windows/syswow64/")
|
||||||
|
try_copy(g_proton.lib64_dir + "wine/dxvk/openvr_api_dxvk.dll", self.prefix_dir + "/drive_c/windows/system32/")
|
||||||
|
|
||||||
|
if "wined3d" in g_session.compat_config:
|
||||||
|
dxvkfiles = ["dxvk_config"]
|
||||||
|
wined3dfiles = ["d3d11", "d3d10", "d3d10core", "d3d10_1", "d3d9"]
|
||||||
|
else:
|
||||||
|
dxvkfiles = ["dxvk_config", "d3d11", "d3d10", "d3d10core", "d3d10_1", "d3d9"]
|
||||||
|
wined3dfiles = []
|
||||||
|
|
||||||
|
#if the user asked for dxvk's dxgi (dxgi=n), then copy it into place
|
||||||
|
if "WINEDLLOVERRIDES" in g_session.env and "dxgi=n" in g_session.env["WINEDLLOVERRIDES"]:
|
||||||
|
dxvkfiles.append("dxgi")
|
||||||
|
else:
|
||||||
|
wined3dfiles.append("dxgi")
|
||||||
|
|
||||||
|
for f in wined3dfiles:
|
||||||
|
try_copy(g_proton.default_pfx_dir + "drive_c/windows/system32/" + f + ".dll",
|
||||||
|
self.prefix_dir + "drive_c/windows/system32/" + f + ".dll")
|
||||||
|
try_copy(g_proton.default_pfx_dir + "drive_c/windows/syswow64/" + f + ".dll",
|
||||||
|
self.prefix_dir + "drive_c/windows/syswow64/" + f + ".dll")
|
||||||
|
|
||||||
|
for f in dxvkfiles:
|
||||||
|
try_copy(g_proton.lib64_dir + "wine/dxvk/" + f + ".dll",
|
||||||
|
self.prefix_dir + "drive_c/windows/system32/" + f + ".dll")
|
||||||
|
try_copy(g_proton.lib_dir + "wine/dxvk/" + f + ".dll",
|
||||||
|
self.prefix_dir + "drive_c/windows/syswow64/" + f + ".dll")
|
||||||
|
g_session.dlloverrides[f] = "n"
|
||||||
|
|
||||||
|
def comma_escaped(s):
|
||||||
|
escaped = False
|
||||||
|
idx = -1
|
||||||
|
while s[idx] == '\\':
|
||||||
|
escaped = not escaped
|
||||||
|
idx = idx - 1
|
||||||
|
return escaped
|
||||||
|
|
||||||
|
class Session:
|
||||||
|
def __init__(self):
|
||||||
|
self.log_file = None
|
||||||
|
self.env = dict(os.environ)
|
||||||
|
self.dlloverrides = {
|
||||||
|
"steam.exe": "b", #always use our special built-in steam.exe
|
||||||
|
"mfplay": "n" #disable built-in mfplay
|
||||||
|
}
|
||||||
|
|
||||||
|
self.compat_config = set()
|
||||||
|
self.cmdlineappend = []
|
||||||
|
|
||||||
|
if "STEAM_COMPAT_CONFIG" in os.environ:
|
||||||
|
config = os.environ["STEAM_COMPAT_CONFIG"]
|
||||||
|
|
||||||
|
while config:
|
||||||
|
(cur, sep, config) = config.partition(',')
|
||||||
|
if cur.startswith("cmdlineappend:"):
|
||||||
|
while comma_escaped(cur):
|
||||||
|
(a, b, c) = config.partition(',')
|
||||||
|
cur = cur[:-1] + ',' + a
|
||||||
|
config = c
|
||||||
|
self.cmdlineappend.append(cur[14:].replace('\\\\','\\'))
|
||||||
|
else:
|
||||||
|
self.compat_config.add(cur)
|
||||||
|
|
||||||
|
#turn forcelgadd on by default unless it is disabled in compat config
|
||||||
|
if not "noforcelgadd" in self.compat_config:
|
||||||
|
self.compat_config.add("forcelgadd")
|
||||||
|
|
||||||
|
def init_wine(self):
|
||||||
|
if "HOST_LC_ALL" in self.env and len(self.env["HOST_LC_ALL"]) > 0:
|
||||||
|
#steam sets LC_ALL=C to help some games, but Wine requires the real value
|
||||||
|
#in order to do path conversion between win32 and host. steam sets
|
||||||
|
#HOST_LC_ALL to allow us to use the real value.
|
||||||
|
self.env["LC_ALL"] = self.env["HOST_LC_ALL"]
|
||||||
|
else:
|
||||||
|
self.env.pop("LC_ALL", "")
|
||||||
|
|
||||||
|
self.env.pop("WINEARCH", "")
|
||||||
|
|
||||||
|
if 'ORIG_'+ld_path_var not in os.environ:
|
||||||
|
# Allow wine to restore this when calling an external app.
|
||||||
|
self.env['ORIG_'+ld_path_var] = os.environ.get(ld_path_var, '')
|
||||||
|
|
||||||
|
if ld_path_var in os.environ:
|
||||||
|
self.env[ld_path_var] = g_proton.lib64_dir + ":" + g_proton.lib_dir + ":" + os.environ[ld_path_var]
|
||||||
|
else:
|
||||||
|
self.env[ld_path_var] = g_proton.lib64_dir + ":" + g_proton.lib_dir
|
||||||
|
|
||||||
|
self.env["WINEDLLPATH"] = g_proton.lib64_dir + "/wine:" + g_proton.lib_dir + "/wine"
|
||||||
|
|
||||||
|
self.env["GST_PLUGIN_SYSTEM_PATH_1_0"] = g_proton.lib64_dir + "gstreamer-1.0" + ":" + g_proton.lib_dir + "gstreamer-1.0"
|
||||||
|
self.env["WINE_GST_REGISTRY_DIR"] = g_compatdata.path("gstreamer-1.0/")
|
||||||
|
|
||||||
|
if "PATH" in os.environ:
|
||||||
|
self.env["PATH"] = g_proton.bin_dir + ":" + os.environ["PATH"]
|
||||||
|
else:
|
||||||
|
self.env["PATH"] = g_proton.bin_dir
|
||||||
|
|
||||||
|
def check_environment(self, env_name, config_name):
|
||||||
|
if not env_name in self.env:
|
||||||
|
return False
|
||||||
|
if nonzero(self.env[env_name]):
|
||||||
|
self.compat_config.add(config_name)
|
||||||
|
else:
|
||||||
|
self.compat_config.discard(config_name)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def init_session(self):
|
||||||
|
self.env["WINEPREFIX"] = g_compatdata.prefix_dir
|
||||||
|
|
||||||
|
#load environment overrides
|
||||||
|
if os.path.exists(g_proton.user_settings_file):
|
||||||
|
try:
|
||||||
|
import user_settings
|
||||||
|
for key, value in user_settings.user_settings.items():
|
||||||
|
self.env.setdefault(key, value)
|
||||||
|
except:
|
||||||
|
log("************************************************")
|
||||||
|
log("THERE IS AN ERROR IN YOUR user_settings.py FILE:")
|
||||||
|
log("%s" % sys.exc_info()[1])
|
||||||
|
log("************************************************")
|
||||||
|
|
||||||
|
if "PROTON_LOG" in self.env and nonzero(self.env["PROTON_LOG"]):
|
||||||
|
self.env.setdefault("WINEDEBUG", "+timestamp,+pid,+tid,+seh,+debugstr,+loaddll,+mscoree")
|
||||||
|
self.env.setdefault("DXVK_LOG_LEVEL", "info")
|
||||||
|
self.env.setdefault("VKD3D_DEBUG", "warn")
|
||||||
|
self.env.setdefault("WINE_MONO_TRACE", "E:System.NotImplementedException")
|
||||||
|
|
||||||
|
#for performance, logging is disabled by default; override with user_settings.py
|
||||||
|
self.env.setdefault("WINEDEBUG", "-all")
|
||||||
|
self.env.setdefault("DXVK_LOG_LEVEL", "none")
|
||||||
|
self.env.setdefault("VKD3D_DEBUG", "none")
|
||||||
|
|
||||||
|
#default wine-mono override for FNA games
|
||||||
|
self.env.setdefault("WINE_MONO_OVERRIDES", "Microsoft.Xna.Framework.*,Gac=n")
|
||||||
|
|
||||||
|
if "wined3d11" in self.compat_config:
|
||||||
|
self.compat_config.add("wined3d")
|
||||||
|
|
||||||
|
if not self.check_environment("PROTON_USE_WINED3D", "wined3d"):
|
||||||
|
self.check_environment("PROTON_USE_WINED3D11", "wined3d")
|
||||||
|
self.check_environment("PROTON_NO_D3D11", "nod3d11")
|
||||||
|
self.check_environment("PROTON_NO_D3D10", "nod3d10")
|
||||||
|
self.check_environment("PROTON_NO_ESYNC", "noesync")
|
||||||
|
self.check_environment("PROTON_NO_FSYNC", "nofsync")
|
||||||
|
self.check_environment("PROTON_FORCE_LARGE_ADDRESS_AWARE", "forcelgadd")
|
||||||
|
self.check_environment("PROTON_OLD_GL_STRING", "oldglstr")
|
||||||
|
self.check_environment("PROTON_USE_SECCOMP", "seccomp")
|
||||||
|
self.check_environment("PROTON_NO_WRITE_WATCH", "nowritewatch")
|
||||||
|
|
||||||
|
if "noesync" in self.compat_config:
|
||||||
|
self.env.pop("WINEESYNC", "")
|
||||||
|
else:
|
||||||
|
self.env["WINEESYNC"] = "1"
|
||||||
|
|
||||||
|
if "nofsync" in self.compat_config:
|
||||||
|
self.env.pop("WINEFSYNC", "")
|
||||||
|
else:
|
||||||
|
self.env["WINEFSYNC"] = "1"
|
||||||
|
|
||||||
|
if "seccomp" in self.compat_config:
|
||||||
|
self.env["WINESECCOMP"] = "1"
|
||||||
|
|
||||||
|
if "nowritewatch" in self.compat_config:
|
||||||
|
self.env["WINE_DISABLE_WRITE_WATCH"] = "1"
|
||||||
|
|
||||||
|
if "oldglstr" in self.compat_config:
|
||||||
|
#mesa override
|
||||||
|
self.env["MESA_EXTENSION_MAX_YEAR"] = "2003"
|
||||||
|
#nvidia override
|
||||||
|
self.env["__GL_ExtensionStringVersion"] = "17700"
|
||||||
|
|
||||||
|
if "forcelgadd" in self.compat_config:
|
||||||
|
self.env["WINE_LARGE_ADDRESS_AWARE"] = "1"
|
||||||
|
|
||||||
|
if "SteamGameId" in self.env:
|
||||||
|
if self.env["WINEDEBUG"] != "-all":
|
||||||
|
basedir = self.env.get("PROTON_LOG_DIR", os.environ["HOME"])
|
||||||
|
makedirs(basedir)
|
||||||
|
lfile_path = basedir + "/steam-" + os.environ["SteamGameId"] + ".log"
|
||||||
|
if os.path.exists(lfile_path):
|
||||||
|
os.remove(lfile_path)
|
||||||
|
self.log_file = open(lfile_path, "w+")
|
||||||
|
self.log_file.write("======================\n")
|
||||||
|
with open(g_proton.version_file, "r") as f:
|
||||||
|
self.log_file.write("Proton: " + f.readline().strip() + "\n")
|
||||||
|
self.log_file.write("SteamGameId: " + self.env["SteamGameId"] + "\n")
|
||||||
|
self.log_file.write("Command: " + str(sys.argv[2:] + self.cmdlineappend) + "\n")
|
||||||
|
self.log_file.write("Options: " + str(self.compat_config) + "\n")
|
||||||
|
self.log_file.write("======================\n")
|
||||||
|
self.log_file.flush()
|
||||||
|
else:
|
||||||
|
self.env["WINEDEBUG"] = "-all"
|
||||||
|
|
||||||
|
g_compatdata.setup_prefix()
|
||||||
|
|
||||||
|
if "nod3d11" in self.compat_config:
|
||||||
|
self.dlloverrides["d3d11"] = ""
|
||||||
|
if "dxgi" in self.dlloverrides:
|
||||||
|
del self.dlloverrides["dxgi"]
|
||||||
|
|
||||||
|
if "nod3d10" in self.compat_config:
|
||||||
|
self.dlloverrides["d3d10_1"] = ""
|
||||||
|
self.dlloverrides["d3d10"] = ""
|
||||||
|
self.dlloverrides["dxgi"] = ""
|
||||||
|
|
||||||
|
s = ""
|
||||||
|
for dll in self.dlloverrides:
|
||||||
|
setting = self.dlloverrides[dll]
|
||||||
|
if len(s) > 0:
|
||||||
|
s = s + ";" + dll + "=" + setting
|
||||||
|
else:
|
||||||
|
s = dll + "=" + setting
|
||||||
|
if "WINEDLLOVERRIDES" in self.env:
|
||||||
|
self.env["WINEDLLOVERRIDES"] = self.env["WINEDLLOVERRIDES"] + ";" + s
|
||||||
|
else:
|
||||||
|
self.env["WINEDLLOVERRIDES"] = s
|
||||||
|
|
||||||
|
def dump_dbg_env(self, f):
|
||||||
|
f.write("PATH=\"" + self.env["PATH"] + "\" \\\n")
|
||||||
|
f.write("\tTERM=\"xterm\" \\\n") #XXX
|
||||||
|
f.write("\tWINEDEBUG=\"-all\" \\\n")
|
||||||
|
f.write("\tWINEDLLPATH=\"" + self.env["WINEDLLPATH"] + "\" \\\n")
|
||||||
|
f.write("\t" + ld_path_var + "=\"" + self.env[ld_path_var] + "\" \\\n")
|
||||||
|
f.write("\tWINEPREFIX=\"" + self.env["WINEPREFIX"] + "\" \\\n")
|
||||||
|
if "WINEESYNC" in self.env:
|
||||||
|
f.write("\tWINEESYNC=\"" + self.env["WINEESYNC"] + "\" \\\n")
|
||||||
|
if "WINEFSYNC" in self.env:
|
||||||
|
f.write("\tWINEFSYNC=\"" + self.env["WINEFSYNC"] + "\" \\\n")
|
||||||
|
if "SteamGameId" in self.env:
|
||||||
|
f.write("\tSteamGameId=\"" + self.env["SteamGameId"] + "\" \\\n")
|
||||||
|
if "SteamAppId" in self.env:
|
||||||
|
f.write("\tSteamAppId=\"" + self.env["SteamAppId"] + "\" \\\n")
|
||||||
|
if "WINEDLLOVERRIDES" in self.env:
|
||||||
|
f.write("\tWINEDLLOVERRIDES=\"" + self.env["WINEDLLOVERRIDES"] + "\" \\\n")
|
||||||
|
if "STEAM_COMPAT_CLIENT_INSTALL_PATH" in self.env:
|
||||||
|
f.write("\tSTEAM_COMPAT_CLIENT_INSTALL_PATH=\"" + self.env["STEAM_COMPAT_CLIENT_INSTALL_PATH"] + "\" \\\n")
|
||||||
|
if "WINE_LARGE_ADDRESS_AWARE" in self.env:
|
||||||
|
f.write("\tWINE_LARGE_ADDRESS_AWARE=\"" + self.env["WINE_LARGE_ADDRESS_AWARE"] + "\" \\\n")
|
||||||
|
|
||||||
|
def dump_dbg_scripts(self):
|
||||||
|
exe_name = os.path.basename(sys.argv[2])
|
||||||
|
|
||||||
|
tmpdir = self.env.get("PROTON_DEBUG_DIR", "/tmp") + "/proton_" + os.environ["USER"] + "/"
|
||||||
|
makedirs(tmpdir)
|
||||||
|
|
||||||
|
with open(tmpdir + "winedbg", "w") as f:
|
||||||
|
f.write("#!/bin/bash\n")
|
||||||
|
f.write("#Run winedbg with args\n\n")
|
||||||
|
f.write("cd \"" + os.getcwd() + "\"\n")
|
||||||
|
self.dump_dbg_env(f)
|
||||||
|
f.write("\t\"" + g_proton.wine_bin + "\" winedbg \"$@\"\n")
|
||||||
|
os.chmod(tmpdir + "winedbg", 0o755)
|
||||||
|
|
||||||
|
with open(tmpdir + "winedbg_run", "w") as f:
|
||||||
|
f.write("#!/bin/bash\n")
|
||||||
|
f.write("#Run winedbg and prepare to run game or given program\n\n")
|
||||||
|
f.write("cd \"" + os.getcwd() + "\"\n")
|
||||||
|
f.write("DEF_CMD=(")
|
||||||
|
first = True
|
||||||
|
for arg in sys.argv[2:]:
|
||||||
|
if first:
|
||||||
|
f.write("\"" + arg + "\"")
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
f.write(" \"" + arg + "\"")
|
||||||
|
f.write(")\n")
|
||||||
|
self.dump_dbg_env(f)
|
||||||
|
f.write("\t\"" + g_proton.wine_bin + "\" winedbg \"${@:-${DEF_CMD[@]}}\"\n")
|
||||||
|
os.chmod(tmpdir + "winedbg_run", 0o755)
|
||||||
|
|
||||||
|
with open(tmpdir + "gdb_attach", "w") as f:
|
||||||
|
f.write("#!/bin/bash\n")
|
||||||
|
f.write("#Run winedbg in gdb mode and auto-attach to already-running program\n\n")
|
||||||
|
f.write("cd \"" + os.getcwd() + "\"\n")
|
||||||
|
f.write("EXE_NAME=${1:-\"" + exe_name + "\"}\n")
|
||||||
|
f.write("WPID_HEX=$(\"" + tmpdir + "winedbg\" --command 'info process' | grep -i \"$EXE_NAME\" | cut -f2 -d' ' | tr -d '0')\n")
|
||||||
|
f.write("if [ -z \"$WPID_HEX\" ]; then \n")
|
||||||
|
f.write(" echo \"Program does not appear to be running: \\\"$EXE_NAME\\\"\"\n")
|
||||||
|
f.write(" exit 1\n")
|
||||||
|
f.write("fi\n")
|
||||||
|
f.write("WPID_DEC=$(printf %d 0x$WPID_HEX)\n")
|
||||||
|
self.dump_dbg_env(f)
|
||||||
|
f.write("\t\"" + g_proton.wine_bin + "\" winedbg --gdb $WPID_DEC\n")
|
||||||
|
os.chmod(tmpdir + "gdb_attach", 0o755)
|
||||||
|
|
||||||
|
with open(tmpdir + "gdb_run", "w") as f:
|
||||||
|
f.write("#!/bin/bash\n")
|
||||||
|
f.write("#Run winedbg in gdb mode and prepare to run game or given program\n\n")
|
||||||
|
f.write("cd \"" + os.getcwd() + "\"\n")
|
||||||
|
f.write("DEF_CMD=(")
|
||||||
|
first = True
|
||||||
|
for arg in sys.argv[2:]:
|
||||||
|
if first:
|
||||||
|
f.write("\"" + arg + "\"")
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
f.write(" \"" + arg + "\"")
|
||||||
|
f.write(")\n")
|
||||||
|
self.dump_dbg_env(f)
|
||||||
|
f.write("\t\"" + g_proton.wine_bin + "\" winedbg --gdb \"${@:-${DEF_CMD[@]}}\"\n")
|
||||||
|
os.chmod(tmpdir + "gdb_run", 0o755)
|
||||||
|
|
||||||
|
with open(tmpdir + "run", "w") as f:
|
||||||
|
f.write("#!/bin/bash\n")
|
||||||
|
f.write("#Run game or given command in environment\n\n")
|
||||||
|
f.write("cd \"" + os.getcwd() + "\"\n")
|
||||||
|
f.write("DEF_CMD=(")
|
||||||
|
first = True
|
||||||
|
for arg in sys.argv[2:]:
|
||||||
|
if first:
|
||||||
|
f.write("\"" + arg + "\"")
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
f.write(" \"" + arg + "\"")
|
||||||
|
f.write(")\n")
|
||||||
|
self.dump_dbg_env(f)
|
||||||
|
f.write("\t\"" + g_proton.wine_bin + "\" steam.exe \"${@:-${DEF_CMD[@]}}\"\n")
|
||||||
|
os.chmod(tmpdir + "run", 0o755)
|
||||||
|
|
||||||
|
def run_proc(self, args, local_env=None):
|
||||||
|
if local_env is None:
|
||||||
|
local_env = self.env
|
||||||
|
subprocess.call(args, env=local_env, stderr=self.log_file, stdout=self.log_file)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if "PROTON_DUMP_DEBUG_COMMANDS" in self.env and nonzero(self.env["PROTON_DUMP_DEBUG_COMMANDS"]):
|
||||||
|
try:
|
||||||
|
self.dump_dbg_scripts()
|
||||||
|
except OSError:
|
||||||
|
log("Unable to write debug scripts! " + str(sys.exc_info()[1]))
|
||||||
|
self.run_proc([g_proton.wine_bin, "steam"] + sys.argv[2:] + self.cmdlineappend)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if not "STEAM_COMPAT_DATA_PATH" in os.environ:
|
||||||
|
log("No compat data path?")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
g_proton = Proton(os.path.dirname(sys.argv[0]))
|
||||||
|
|
||||||
|
if g_proton.need_tarball_extraction():
|
||||||
|
g_proton.extract_tarball()
|
||||||
|
|
||||||
|
g_compatdata = CompatData(os.environ["STEAM_COMPAT_DATA_PATH"])
|
||||||
|
|
||||||
|
g_session = Session()
|
||||||
|
|
||||||
|
g_session.init_wine()
|
||||||
|
|
||||||
|
if g_proton.missing_default_prefix():
|
||||||
|
g_proton.make_default_prefix()
|
||||||
|
|
||||||
|
g_session.init_session()
|
||||||
|
|
||||||
|
#determine mode
|
||||||
|
if sys.argv[1] == "run":
|
||||||
|
#start target app
|
||||||
|
g_session.run()
|
||||||
|
elif sys.argv[1] == "waitforexitandrun":
|
||||||
|
#wait for wineserver to shut down
|
||||||
|
g_session.run_proc([g_proton.wineserver_bin, "-w"])
|
||||||
|
#then run
|
||||||
|
g_session.run()
|
||||||
|
elif sys.argv[1] == "getcompatpath":
|
||||||
|
#linux -> windows path
|
||||||
|
path = subprocess.check_output([g_proton.wine_bin, "winepath", "-w", sys.argv[2]], env=g_session.env, stderr=g_session.log_file)
|
||||||
|
sys.stdout.buffer.write(path)
|
||||||
|
elif sys.argv[1] == "getnativepath":
|
||||||
|
#windows -> linux path
|
||||||
|
path = subprocess.check_output([g_proton.wine_bin, "winepath", sys.argv[2]], env=g_session.env, stderr=g_session.log_file)
|
||||||
|
sys.stdout.buffer.write(path)
|
||||||
|
else:
|
||||||
|
log("Need a verb.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
#pylint --disable=C0301,C0326,C0330,C0111,C0103,R0902,C1801,R0914,R0912,R0915
|
||||||
|
# vim: set syntax=python:
|
||||||
File diff suppressed because it is too large.
Load diff
Binary file not shown.
@@ -0,0 +1,39 @@
|
|||||||
|
"AppState"
|
||||||
|
{
|
||||||
|
"appid" "1245040"
|
||||||
|
"Universe" "1"
|
||||||
|
"name" "Proton 5.0"
|
||||||
|
"StateFlags" "4"
|
||||||
|
"installdir" "Proton 5.0"
|
||||||
|
"LastUpdated" "1790875434"
|
||||||
|
"LastPlayed" "0"
|
||||||
|
"SizeOnDisk" "1036890088"
|
||||||
|
"StagingSize" "0"
|
||||||
|
"buildid" "5755554"
|
||||||
|
"LastOwner" "76561197969502926"
|
||||||
|
"DownloadType" "1"
|
||||||
|
"UpdateResult" "0"
|
||||||
|
"BytesToDownload" "0"
|
||||||
|
"BytesDownloaded" "0"
|
||||||
|
"BytesToStage" "0"
|
||||||
|
"BytesStaged" "0"
|
||||||
|
"TargetBuildID" "5755554"
|
||||||
|
"AutoUpdateBehavior" "0"
|
||||||
|
"AllowOtherDownloadsWhileRunning" "0"
|
||||||
|
"ScheduledAutoUpdate" "0"
|
||||||
|
"FullValidateAfterNextUpdate" "1"
|
||||||
|
"InstalledDepots"
|
||||||
|
{
|
||||||
|
"1245041"
|
||||||
|
{
|
||||||
|
"manifest" "6622838934188638130"
|
||||||
|
"size" "1036890088"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"UserConfig"
|
||||||
|
{
|
||||||
|
}
|
||||||
|
"MountedConfig"
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
"manifest"
|
||||||
|
{
|
||||||
|
"commandline" "/proton run"
|
||||||
|
"commandline_getnativepath" "/proton getnativepath"
|
||||||
|
"commandline_getcompatpath" "/proton getcompatpath"
|
||||||
|
"commandline_waitforexitandrun" "/proton waitforexitandrun"
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#To enable these settings, name this file "user_settings.py".
|
||||||
|
|
||||||
|
#Settings here will take effect for all games run in this Proton version.
|
||||||
|
|
||||||
|
user_settings = {
|
||||||
|
#By default, logs are saved to $HOME/steam-<STEAM_GAME_ID>.log, overwriting any previous log with that name.
|
||||||
|
#Log directory can be overridden with $PROTON_LOG_DIR.
|
||||||
|
|
||||||
|
#Wine debug logging
|
||||||
|
"WINEDEBUG": "+timestamp,+pid,+tid,+seh,+debugstr,+loaddll,+mscoree",
|
||||||
|
|
||||||
|
#DXVK debug logging
|
||||||
|
"DXVK_LOG_LEVEL": "info",
|
||||||
|
|
||||||
|
#vkd3d debug logging
|
||||||
|
"VKD3D_DEBUG": "warn",
|
||||||
|
|
||||||
|
#wine-mono debug logging (Wine's .NET replacement)
|
||||||
|
"WINE_MONO_TRACE": "E:System.NotImplementedException",
|
||||||
|
#"MONO_LOG_LEVEL": "info",
|
||||||
|
|
||||||
|
#Enable DXVK's HUD
|
||||||
|
# "DXVK_HUD": "devinfo,fps",
|
||||||
|
|
||||||
|
#Use OpenGL-based wined3d for d3d11, d3d10, and d3d9 instead of Vulkan-based DXVK
|
||||||
|
# "PROTON_USE_WINED3D": "1",
|
||||||
|
|
||||||
|
#Disable d3d11 entirely
|
||||||
|
# "PROTON_NO_D3D11": "1",
|
||||||
|
|
||||||
|
#Disable eventfd-based in-process synchronization primitives
|
||||||
|
# "PROTON_NO_ESYNC": "1",
|
||||||
|
|
||||||
|
#Disable futex-based in-process synchronization primitives
|
||||||
|
# "PROTON_NO_FSYNC": "1",
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
1603141982 proton-5.0-10b
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
services:
|
||||||
|
windrose:
|
||||||
|
build: .
|
||||||
|
container_name: windrose-servermanager
|
||||||
|
|
||||||
|
# IMPORTANT: Linux/TrueNAS paths ONLY
|
||||||
|
volumes:
|
||||||
|
- /mnt/tank/windrose/server:/server:rw
|
||||||
|
- /mnt/tank/windrose/server/R5:/server/R5:rw
|
||||||
|
- /mnt/tank/windrose/data/Saved:/data/Saved:rw
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "27015:27015/udp"
|
||||||
|
- "27015:27015/tcp"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- WINEPREFIX=/data/wine/wineprefix
|
||||||
|
- WINEARCH=win64
|
||||||
|
- WINDROSE_HOME=/server
|
||||||
|
- WINDROSE_R5=/server/R5
|
||||||
|
- SAVED_DIR=/data/Saved
|
||||||
|
|
||||||
|
# Intel ARC GPU Vulkan
|
||||||
|
- LIBVA_DRIVER_NAME=iHD
|
||||||
|
- VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/intel_icd.x86_64.json:/usr/share/vulkan/icd.d/intel_icd.i686.json
|
||||||
|
|
||||||
|
# DXVK overrides
|
||||||
|
- WINEDLLOVERRIDES=d3d11,dxgi,d3d10core,d3d9=native,builtin
|
||||||
|
|
||||||
|
# GPU passthrough
|
||||||
|
devices:
|
||||||
|
- /dev/dri:/dev/dri
|
||||||
|
|
||||||
|
# Required for Wine + GPU access
|
||||||
|
cap_add:
|
||||||
|
- SYS_ADMIN
|
||||||
|
|
||||||
|
tty: true
|
||||||
|
stdin_open: true
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
# Dockerfile
|
||||||
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV WINEPREFIX=/data/wine/wineprefix
|
||||||
|
ENV WINEARCH=win64
|
||||||
|
ENV WINDROSE_HOME=/server
|
||||||
|
ENV WINDROSE_R5=/server/R5
|
||||||
|
ENV SAVED_DIR=/data/Saved
|
||||||
|
|
||||||
|
# Install WineHQ (correct method for Ubuntu 22.04)
|
||||||
|
RUN dpkg --add-architecture i386 \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates wget curl gnupg2 software-properties-common \
|
||||||
|
xvfb x11vnc pulseaudio cabextract unzip p7zip-full \
|
||||||
|
&& mkdir -pm755 /etc/apt/keyrings \
|
||||||
|
&& wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key \
|
||||||
|
&& wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y --install-recommends winehq-stable \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Intel ARC GPU + Vulkan support
|
||||||
|
RUN dpkg --add-architecture i386 \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
mesa-vulkan-drivers mesa-vulkan-drivers:i386 \
|
||||||
|
libvulkan1 libvulkan1:i386 \
|
||||||
|
intel-media-va-driver-non-free vainfo \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install DXVK 2.3 (runtime DLLs only)
|
||||||
|
RUN wget -O dxvk.tar.gz https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz \
|
||||||
|
&& tar -xvf dxvk.tar.gz \
|
||||||
|
&& rm dxvk.tar.gz \
|
||||||
|
&& mv dxvk-2.3 /opt/dxvk
|
||||||
|
|
||||||
|
# Create directories for mounts
|
||||||
|
RUN mkdir -p ${WINDROSE_HOME} ${WINDROSE_R5}
|
||||||
|
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
WINEPREFIX=${WINEPREFIX:-/data/wine/wineprefix}
|
||||||
|
WINDROSE_HOME=${WINDROSE_HOME:-/server}
|
||||||
|
WINDROSE_R5=${WINDROSE_R5:-/server/R5}
|
||||||
|
SAVED_DIR=${SAVED_DIR:-/data/Saved}
|
||||||
|
|
||||||
|
SERVER_EXE="${WINDROSE_R5}/Binaries/Win64/WindroseServer-Win64-Shipping.exe"
|
||||||
|
|
||||||
|
export WINEDEBUG=-all
|
||||||
|
export DISPLAY=
|
||||||
|
export XDG_RUNTIME_DIR=/tmp/runtime-wine
|
||||||
|
mkdir -p "$XDG_RUNTIME_DIR"
|
||||||
|
|
||||||
|
# Intel ARC Vulkan ICDs
|
||||||
|
export VK_ICD_FILENAMES="/usr/share/vulkan/icd.d/intel_icd.x86_64.json:/usr/share/vulkan/icd.d/intel_icd.i686.json"
|
||||||
|
export LIBVA_DRIVER_NAME=iHD
|
||||||
|
|
||||||
|
DXVK_32="/opt/dxvk/x32"
|
||||||
|
DXVK_64="/opt/dxvk/x64"
|
||||||
|
|
||||||
|
# Initialize wineprefix if missing
|
||||||
|
if [ ! -d "$WINEPREFIX" ] || [ ! -f "$WINEPREFIX/system.reg" ]; then
|
||||||
|
echo "Initializing wineprefix at $WINEPREFIX"
|
||||||
|
mkdir -p "$WINEPREFIX"
|
||||||
|
wineboot --init || true
|
||||||
|
|
||||||
|
echo "Installing DXVK DLLs into wineprefix..."
|
||||||
|
WIN_SYS32="$WINEPREFIX/drive_c/windows/system32"
|
||||||
|
WIN_SYSWOW64="$WINEPREFIX/drive_c/windows/syswow64"
|
||||||
|
|
||||||
|
mkdir -p "$WIN_SYS32" "$WIN_SYSWOW64"
|
||||||
|
|
||||||
|
cp "$DXVK_64"/*.dll "$WIN_SYS32"/
|
||||||
|
cp "$DXVK_32"/*.dll "$WIN_SYSWOW64"/
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Force DXVK to be used
|
||||||
|
export WINEDLLOVERRIDES="d3d11,dxgi,d3d10core,d3d9=native,builtin"
|
||||||
|
|
||||||
|
mkdir -p "$SAVED_DIR"
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
run-server)
|
||||||
|
echo "Starting Windrose dedicated server..."
|
||||||
|
|
||||||
|
if [ ! -f "$SERVER_EXE" ]; then
|
||||||
|
echo "ERROR: Windrose server binary not found:"
|
||||||
|
echo " $SERVER_EXE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$(dirname "$SERVER_EXE")"
|
||||||
|
|
||||||
|
exec wine "$SERVER_EXE" \
|
||||||
|
-log \
|
||||||
|
-unattended \
|
||||||
|
-nosteam \
|
||||||
|
-savedir "$SAVED_DIR"
|
||||||
|
;;
|
||||||
|
|
||||||
|
bash)
|
||||||
|
exec /bin/bash
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
exec "$@"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in new issue
Block a user