TDF is a small project aiming to make it easy to install, package and safely run Windows games on GNU/Linux. You can think of it as a portable (as in requiring no installation) version of Proton, based on most of the same technology.
TDF is based on the following awesome projects:
TDF's main goals are are:
If you're happy with Lutris, you probably don't need TDF.
This section explains how to use TDF to install, play and optionally package a game.
template-YYYYMMDD
to something more descriptive. We'll call
this folder a TDF instance, you can have as many instances as you want
run.sh
: the script that starts all the TDF magic, we'll
use this in a momentvars.conf
: TDF's main configuration file for this
instance, you'll use this to tell TDF where to find the game and to
change emulation settingssystem
: a folder containing all the TDF files and
scripts, leave it alone for nowconfs
: we'll talk about folder this laterrun.sh
, it will automatically initialize
everything for you and open a Windows command prompt
vars.conf
and place the location of the game's exe
file in the game_exe variablerun.sh
(or create
links to it) to launch this game.vars.conf
, which we'll discuss laterHere's a video showing how to install a game from GOG that requires no additional configuration: Basic usage - Installing a game from GOG
You can find more video examples at the end of this document.
The following lists contain all the variables that can be added in
vars.conf
to configure emulation settings, work around
issues, improve performance, etc.
game_exe
Specifies the Windows-style path to the game's exe file. If no value is
set, the command prompt will be launched instead.
Example: game_exe='C:\GTAV\PlayGTAV.exe'
game_args
Arguments to be passed to the game.
Example: game_args='-iwad doom2.wad -file mymod.wad'
game_workingDir
The working directory of the game. By default this is set to the same
folder where the game_exe
resides. All paths must be
Windows-style.
Example:
game_exe='bin\indy.exe'
game_workingDir='C:\Indy'
TDF_TITLE
The title to show on the title bar of the TDF windows. By default it's
set to "Launcher"
.
TDF_DETAILED_PROGRESS
Whether to show the details of what's happening above the progress bar
in the TDF window.
Possible values:
1
(default): show details like "Starting wine",
"Registering DLLs", etc.0
: show a generic message like "Launching..." or
"Creating a new wineprefix, this will take a while..."TDF_MULTIPLE_INSTANCES
What to do if the user tries to launch run.sh
while it's
already running.
Possible values:
deny
: do nothing, just exit without an error
messageerror
: show an error message and exitaskcmd
(default): don't launch the game but ask the
user if they want to launch a command prompt in the running
instancecmd
: same as askcmd
but without asking
firstallow
: allow multiple instances of the game to be
running at the same time (generally a bad idea)kill
: terminate previous instance and start a new
oneaskkill
: ask the user if they want to terminate the
previous instance and start a new one or exitTDF_IGNORE_EXIST_CHECKS
By default, TDF checks whether the executable specified in
game_exe
actually exists before trying to launch it, but
this is not always desirable and can be disabled, which can be useful to
run certain commands.
Possible values:
0
(default): check that the executable actually exists
and show an error if it doesn't1
: don't check and don't show an error if it doesn't
existTDF_HIDE_GAME_RUNNING_DIALOG
Whether to hide the TDF window that says "Game running". By default, TDF
shows it so you can know if the process has stalled.
Possible values:
0
(default): show the window1
: hide itTDF_SHOW_PLAY_TIME
Whether to show a message when you close the game that tells you how
long you've been playing.
Possible values:
0
(default): don't show it1
: show itTDF_DND
Enables Do Not Disturb mode (on supported DEs) while the game is
running.
Possible values:
1
(default): mute notifications while the game is
running0
: don't mute themNote: some games launch a separate process and terminate immediately. This setting won't work on these games.
TDF_UI_LANGUAGE
The language to use for the TDF user interface. Does not affect Wine or
games (see TDF_WINE_LANGUAGE
for that).
By default, TDF tries to obtain the language from the OS. If a translation is not available, it will fall back to English.
Currently implemented languages:
en
: Englishit
: ItalianTDF_WINE_PREFERRED_VERSION
TDF comes with 2 different versions of Wine and can also use the one on
your system (if installed). This variable lets you choose which one you
prefer.
Possible values:
games
(default): use the game-optimized build. This
version is based on Valve's version of Wine, with the GE and tkg patches
and is very similar to Wine-GE-Proton.
Some functionalities have been disabled: anticheat bridges (you can't
convince me they're not malware), dbus (automounting of external
drives), ISDN, printing, digital camera importing, LDAP and related
things, pcap support (network traffic sniffing), smart cart readers
support, scanners, low level access to USB devices (does not affect
input, that goes over HID), webcam support, Win16 support,
winemenubuilder, vkd3d-lib (Wine's own VKD3D implementation, not needed
since TDF uses VKD3D-Proton)mainline
: use a mostly regular version of Wine, useful
for applications and old games that don't work with the game-optimized
build. This version only contains a couple of hotfixes from tkg and the
only disabled features are dbus and winemenubuilder for better
isolationsystem
: use the version of Wine that's installed in the
system, if it's not installed mainline
will be used
insteadcustom
: use the version of Wine that you can put in a
folder called wine-custom
outside the system folder (next
to run.sh
). This is useful to keep TDF updates easy for the
occasional game that requires custom builds of Winesystem/wine-yourValue
. If not found, system Wine will be
used insteadTDF_WINE_HIDE_CRASHES
When a Wine application crashes, it normally shows a window similar to
the "Stopped working" dialog on Windows, but depending on the game and
configuration, it may be impossible to interact with that window,
leaving you stuck. By default, TDF disables this crash window, but it
can be enabled for debugging and troubleshooting purposes.
Possible values:
1
(default): hide the crash window0
: show the crash windowTDF_WINE_AUDIO_DRIVER
Sets the preferred audio driver for Wine. This can be useful if you have
crackling audio or if one of the drivers has a lower latency than the
others. Default is usually fine.
Possible values:
pulse
: use PulseAudio (you may also want to add
export PULSE_LATENCY_MSEC=20
for lower latency in music
games or export PULSE_LATENCY_MSEC=120
if you have
crackling/dropouts)alsa
: use ALSAjack
: use Jackdefault
(default): let Wine decideNote: Choosing a driver that doesn't exist in Wine or in your system will result in no sound being played.
Note: Wine doesn't natively support PipeWire yet, it uses PulseAudio by default for compatibility if you're using PipeWire.
TDF_WINE_GRAPHICS_DRIVER
Sets the preferred graphics driver for Wine (as in how it outputs, not
how it renders 3D graphics). This can be useful if you're messing around
with Wayland and X11 and Wine doesn't work properly.
Possible values:
default
(default): let Wine decide (defaults to X11 at
the moment, even on Wayland)x11
: use X11, does not support HDRwayland
: use Wayland, supports HDR. Not feature
complete yetauto
: let TDF decide based on what you're using. If
Wayland is available, Wayland will be used, otherwise X11Note: Choosing a driver that doesn't exist in Wine or in your system will result in no graphics being displayed.
Note: This setting is automatically forced to wayland
when TDF_HDR
is set to 1
.
TDF_WINE_DPI
DPI value for display scaling of Wine applications.
Possible values:
0
(default): let Wine handle scaling-1
: use DPI from the main displayTDF_WINE_KILL_BEFORE
Whether to kill wine before launching the game. Not recommended.
Possible values:
0
(default): don't kill wine before launching the
game1
: kill all wine instances before launching the
gameTDF_WINE_KILL_AFTER
Whether to kill wine after the game ends. Not recommended.
Possible values:
0
(default): don't kill wine after the game ends1
: kill all wine instances after the game endsTDF_START_ARGS
Optional arguments to pass to Wine's start command. More info. Mostly useful to
set CPU affinity for old games (in this regard, see also
TDF_WINE_MAXLOGICALCPUS
).
Example: TDF_START_ARGS='/AFFINITY 1'
TDF_WINE_LANGUAGE
By default, TDF will pass the system language to Wine, which may be
undesirable for some games and applications that just use the system
language instead of showing a language selector. Here's a complete list
of locales, obviously not all games will support them.
Example: TDF_WINE_LANGUAGE='it_IT.utf-8'
TDF_WINE_ARCH
The architecture of the Wine installation. Can only be set once, before
the initialization is performed, and can't be changed afterwards without
deleting the wineprefix.
Possible values:
win64
(default): create a 64-bit Windows
installationwin32
: create a 32-bit Windows installation (useful for
some old games)TDF_WINE_SYNC
The synchronization method to be used by Wine (game-optimized build
only).
Possible values:
fsync
(default): use fsync if supported by the kernel
(5.16+), otherwise use esync. This provides the best performance and
compatibilityesync
: use the older esync methoddefault
: let Wine decideTDF_WINE_WINVER
Sets the Windows version to emulate.
Possible values:
""
(empty string) (default): let Wine decide on prefix
creation (at the moment it's win10
). Can be changed through
winecfg
win10
, win11
,
win7
, win8
, win81
,
vista
, winxp
, winxp64
win2003
, win2008
,
win2008r2
, winme
, win2k
,
win98
, win95
, nt40
,
nt351
, win31
, win30
,
win20
Note: If using an older Windows version, TDF_WINE_ARCH
should also be set accordingly. It usually doesn't break anything, but
applications may not expect to see 64-bit versions of legacy
systems.
TDF_WINE_THEME
Sets the Wine theme.
Possible values:
""
(empty string) (default): let Wine decide on prefix
creation (at the moment it's light
). Can be changed through
winecfg
classic
: use the classic 9x style theme (can fix some
old apps that have drawing issues with modern themes)light
: use the modern 11-ish style themeNote: It's possible to install msstyles themes, in this case, leave
this empty and install them through winecfg
.
TDF_WINE_DEBUG_RELAY
Enables the Wine relay feature, which traces all interaction between the
application and the rest of the system to a file. Extremely slow but can
be useful to debug weird issues and crashes.
Possible values:
0
(default): disabled1
: when the game is launched, TDF will ask where you
want to save the trace, then launch the game with relay enabledTDF_WINE_DEBUG_GSTREAMER
Enables gstreamer debug output. This can be used to debug issues like
games not playing videos or crashing when a video is supposed to
play.
Possible values:
0
(default): disabled1
: enable gstreamer debug outputTDF_WINE_SMOKETEST
Whether or not to perform a "smoke test" to make sure that Wine actually
works before trying to run the game, that way we can tell if a crash is
a Wine problem or a game problem. TDF does this by default but you can
disable it if it takes too long at the "Starting Wine" screen.
Possible values:
1
(default): do the "smoke test"0
: skip the "smoke test" for faster startupTDF_WINEMONO
Whether to install Wine Mono in the prefix or not. Mostly useful for
launchers and applications based on .NET, games don't usually need
this.
Possible values:
0
(default): don't install Wine Mono1
: install Wine MonoTDF_WINEGECKO
Whether to install Wine Gecko in the prefix or not. This provides the
equivalent of a Webview, mostly useful for launchers and applications
based on IE, games don't usually need this.
Possible values:
0
(default): don't install Wine Gecko1
: install Wine Geckoexport WINEDLLOVERRIDES
Some game fixes and mods come in the form of DLLs that override one of
Windows' DLL, usually winmm
, dinput8
,
version
, d3d9
, etc.
Unlike Windows, which happily loads random DLLs from the game's folder,
Wine prefers to use its own DLLs and overrides need to be specified
manually.
This is not a TDF variable, but it's part of Wine. More about this here.
Example:
#load winmm.dll and dinput8 from the game's folder (if available)
export WINEDLLOVERRIDES="winmm,dinput8=n,b"
This can also be used to fix games that complain about outdated
drivers on AMD cards or that don't detect the correct amount of VRAM,
since they often obtain this information through a DLL called
amd_ags_x64.dll
:
Example:
#use wine's own fake amd_ags_x64 instead of the game's version
export WINEDLLOVERRIDES="amd_ags_x64=b"
Multiple overrides can be separated by a semicolon
;
.
export WINEDEBUG
Enables/disables some Wine debug
channels.
By default, TDF sets this to -all
to improve
performance, but you might want to enable one or more of these for
troubleshooting, or restore the default Wine settings using
unset WINEDEBUG
.
Don't add +relay
to this variable, as it's controlled by
the TDF_WINE_DEBUG_RELAY
variable.
Example:
#log loaded DLLs to the terminal and show the pid of the process that generated each message
export WINEDEBUG=+loaddll,+pid
As CPUs get more and more cores and threads, problems such as crashes, inconsistent performance and general instability can occur in older games. For this reason, TDF implements several ways to limit which cores can be used.
Note: these settings apply to the game-optimized build only
Before we get into the settings, some terminology:
If a game doesn't support a high number of cores, TDF can limit the number of logical CPUs assigned to it and choose the best ones to maximize performance.
Note: These limits affect the performance of everything running inside Wine, including DXVK and VKD3D. Use them only if absolutely necessary.
Note: if WINE_CPU_TOPOLOGY
is set, these settings will
have no effect.
TDF_WINE_MAXLOGICALCPUS
The maximum number of logical CPUs that can be assigned to this
game.
Possible values:
0
(default): unlimitedIf the number of logical CPUs exceeds this value, they are assigned intelligently in this way:
TDF_WINE_PREFER_SAMESOCKET
belowGenerally speaking, this is the only limit you should set. Let TDF do the rest for you.
Example 1: We're on an Intel Core i7 12900K (8 P-cores with 2 threads
each, 8 E-cores with 1 thread each, 24 threads in total), the CPU
topology is the following (obtained with
lscpu --all --extended
):
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ
0 0 0 0 0:0:0:0 yes 6700.0000 800.0000
1 0 0 0 0:0:0:0 yes 6700.0000 800.0000
2 0 0 1 1:1:1:0 yes 6700.0000 800.0000
3 0 0 1 1:1:1:0 yes 6700.0000 800.0000
4 0 0 2 2:2:2:0 yes 6500.0000 800.0000
5 0 0 2 2:2:2:0 yes 6500.0000 800.0000
6 0 0 3 3:3:3:0 yes 6500.0000 800.0000
7 0 0 3 3:3:3:0 yes 6500.0000 800.0000
8 0 0 4 4:4:4:0 yes 6500.0000 800.0000
9 0 0 4 4:4:4:0 yes 6500.0000 800.0000
10 0 0 5 5:5:5:0 yes 6500.0000 800.0000
11 0 0 5 5:5:5:0 yes 6500.0000 800.0000
12 0 0 6 6:6:6:0 yes 6500.0000 800.0000
13 0 0 6 6:6:6:0 yes 6500.0000 800.0000
14 0 0 7 7:7:7:0 yes 6500.0000 800.0000
15 0 0 7 7:7:7:0 yes 6500.0000 800.0000
16 0 0 8 8:8:8:0 yes 3900.0000 800.0000
17 0 0 9 9:9:8:0 yes 3900.0000 800.0000
18 0 0 10 10:10:8:0 yes 3900.0000 800.0000
19 0 0 11 11:11:8:0 yes 3900.0000 800.0000
20 0 0 12 12:12:9:0 yes 3900.0000 800.0000
21 0 0 13 13:13:9:0 yes 3900.0000 800.0000
22 0 0 14 14:14:9:0 yes 3900.0000 800.0000
23 0 0 15 15:15:9:0 yes 3900.0000 800.0000
If you want to play Colin McRae Dirt (2007), a game that supports 4
cores at most, you'll have to set
TDF_WINE_MAXLOGICALCPUS=4
, and with this CPU TDF will
select logical CPUs 0,2,4,6, because they are the fastest cores
available, one thread per core.
If you want to play Lara Croft and the Guardian of Light (2010), a
game that supports 12 cores at most, you'll have to set
TDF_WINE_MAXLOGICALCPUS=12
, and with this CPU TDF will
select logical CPUs 0,2,4,6,8,10,12,14,16,17,18,19. The first 8 are the
P-cores, one thread per core, the last 4 are E-cores, one thread per
core.
If you want to play The Witcher 2 (2010), a game that supports 31
cores at most, you'll have to set
TDF_WINE_MAXLOGICALCPUS=31
, and with this CPU TDF will not
apply any special restriction because it only has 24 logical CPUs.
Example 2: We're on an AMD Ryzen 7 5800X (8 cores with 2 threads each, 16 threads in total), the CPU topology is the following:
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE MAXMHZ MINMHZ
0 0 0 0 0:0:0:0 yes 4850.1948 2200.0000
1 0 0 1 1:1:1:0 yes 4850.1948 2200.0000
2 0 0 2 2:2:2:0 yes 4850.1948 2200.0000
3 0 0 3 3:3:3:0 yes 4850.1948 2200.0000
4 0 0 4 4:4:4:0 yes 4850.1948 2200.0000
5 0 0 5 5:5:5:0 yes 4850.1948 2200.0000
6 0 0 6 6:6:6:0 yes 4850.1948 2200.0000
7 0 0 7 7:7:7:0 yes 4850.1948 2200.0000
8 0 0 0 0:0:0:0 yes 4850.1948 2200.0000
9 0 0 1 1:1:1:0 yes 4850.1948 2200.0000
10 0 0 2 2:2:2:0 yes 4850.1948 2200.0000
11 0 0 3 3:3:3:0 yes 4850.1948 2200.0000
12 0 0 4 4:4:4:0 yes 4850.1948 2200.0000
13 0 0 5 5:5:5:0 yes 4850.1948 2200.0000
14 0 0 6 6:6:6:0 yes 4850.1948 2200.0000
15 0 0 7 7:7:7:0 yes 4850.1948 2200.0000
(Notice the different interleaving in the CORE column compared to the previous example).
If you want to play Colin McRae Dirt (2007), a game that supports 4
cores at most, you'll have to set
TDF_WINE_MAXLOGICALCPUS=4
, and with this CPU TDF will
select logical CPUs 0,1,2,3, which are simply the first 4 logical CPUs,
one per core.
If you want to play Lara Croft and the Guardian of Light (2010), a
game that supports 12 cores at most, you'll have to set
TDF_WINE_MAXLOGICALCPUS=12
, and with this CPU TDF will
select logical CPUs 0,1,2,3,4,5,6,7,8,9,10,11. The first 8 are the first
logical CPU of each core, one thread per core, the last 4 are the second
logical CPU of the first 4 cores.
If you want to play The Witcher 2 (2010), a game that supports 31
cores at most, you'll have to set
TDF_WINE_MAXLOGICALCPUS=31
, and with this CPU TDF will not
apply any special restriction because it only has 16 logical CPUs.
TDF_WINE_NOSMT
Whether to hide the additional logical CPUs on CPUs that support
HyperThreading/SMT.
Possible values:
0
(default): use SMT1
: do not use SMT. If this is set, only the first
logical CPU of each core will be used, the others will be ignored. This
can improve the performance of some older games.TDF_WINE_NOECORES
Whether to hide E-cores on CPUs like Intel Alder Lake.
Possible values:
0
(default): use E-cores1
: do not use E-coresNote: for compatibility reasons, these CPUs have no easy way to tell which cores are P-cores and each ones are E-cores, so TDF "guesses" that the E-cores are the ones with a maximum clock that's <75% of that of any other core. This may be improved in the future.
TDF_WINE_PREFER_SAMESOCKET
For systems with multiple CPUs only, how to use them.
Possible values:
1
(default): assign logical CPUs based on speed, but
prioritize cores on the same physical CPU (first assign all the logical
CPUs in the first socket, then the second, etc.). This is generally the
best for games.0
: logical CPUs are assigned based exclusively on
speed, regardless of which CPU they are physically on. This is generally
not recommended for games.2
: restrict to the first CPUexport WINE_CPU_TOPOLOGY
This is not a TDF variable, but it allows you to set Wine to use
specific CPU cores, similar to the /AFFINITY
option of the
start
command in Windows, but more fine grained. This
should be used as a last resort or if you want to do dumb things like
restrict a game to only use E-cores.
Example:
#limits wine to one CPU core
export WINE_CPU_TOPOLOGY="1:0"
Example:
#limits wine to use the first 4 CPU cores
export WINE_CPU_TOPOLOGY="4:0,1,2,3"
Note: if WINE_CPU_TOPOLOGY
is set, the settings above
will have no effect.
TDF_DXVK
Whether to install DXVK or not, which provides DirextX 9-11 emulation
through Vulkan. If this is disabled, WineD3D will be used instead, which
is better for some older games.
Settings for DXVK can be changed by editing the
dxvk.conf
file that will be created inside
zzprefix
.
Possible values:
1
(default): use DXVK0
: use WineD3DTDF_DXVK_ASYNC
If enabled, TDF will use the gplasync version of DXVK instead of the
regular version. This is only useful for systems that don't support the
Vulkan VK_EXT_graphics_pipeline_library
(GPL) extension
because either the GPU or the driver is too old.
Possible values:
2
(default): let TDF decide automatically, uses regular
DXVK if GPL is supported, gplasync otherwise0
: always use the regular version of DXVK. If the
system doesn't support GPL, the game will suffer from heavy shader
compilation stuttering1
: always use the gplasync version of DXVK. Not
recommended, can introduce minor graphical issues or stability
issuesTDF_DXVK_NVAPI
Whether to install DXVK-nvapi or not, which provides nvapi support for
nVidia GPUs. Requires TDF_DXVK
to be set to
1
.
Possible values:
0
(default): don't use DXVK-nvapi1
: use DXVK-nvapi on nVidia GPUsTDF_HDR
Whether to expose HDR support to the application or not. HDR must be
enabled in the system settings for this to work and an HDR compatible
display is required. This setting has no effect is HDR is disabled or
unsupported.
Possible values:
0
(default): don't expose HDR (this is the default
because HDR kinda sucks in most games)1
: expose HDR if availableNote: HDR is not supported by X11, you must be using Wayland for this to work.
TDF_VKD3D
Whether to install VKD3D-Proton, which provides DirectX 12 emulation
through Vulkan. If this is disabled, Wine's version of VKD3D is used
instead, which has very poor game compatibility compared to this
version.
Possible values:
1
(default): use VKD3D-Proton0
: use Wine's VKD3D implementationVKD3D's config can be changed by using its environment
variables. By default, doesn't set this variable, meaning that VKD3D
will automatically enable ray tracing on supported cards. Older versions
of TDF (before November 2023) set this to dxr11
to enable
ray tracing.
TDF_BLOCK_NETWORK
Whether to block network access to Wine. By default, TDF blocks network
access entirely to prevent undesirable data collection, but it can be
unblocked if you trust the game you're running or it needs to go
online.
Possible values:
1
(default): block network access using
unshare -nc
(creates a namespace without the network
stack)0
: allow network access2
: block network access using Firejail if it's
installed in the system, otherwise unshare -nc
will be
used. This can fix some games that take a long time to load when there
is no network stack, such as Death StrandingTDF_BLOCK_BROWSER
Whether to block Wine from opening the system's native web browser or
not. By default, TDF will block these requests to prevent undesirable
data collection, but it can be unblocked if you trust the game you're
running or it needs to open some web pages.
Possible values:
1
(default): block access to the system's native web
browser0
: allow Wine to launch the native web browserNote that allowing access to the native web browser can be abused to
bypass TDF_BLOCK_NETWORK
, this behavior has been noticed in
several game repack installers.
TDF_BLOCK_ZDRIVE
Wine normally exposes a Z drive to applications, with full access to the
Linux file system, which can be abused by games to collect data or by
malware to modify files outside the TDF instance, but it can also be
useful when installing games, since you can access mounted drives, your
Downloads folder, etc. or if you're running applications.
Possible values:
1
(default): allow access to the Z drive when in
"install mode" (i.e. game_exe
is not set yet), making it
easier to install the game, block afterwards2
: always block access to the Z drive0
: allow access to the Z driveNote that while this can help protect against Windows malware, malware designed to attack Wine or Linux can very easily bypass this restriction. Never run untrusted software inside TDF, use a VM instead.
TDF_BLOCK_EXTERNAL_DRIVES
Wine normally exposes external drives to applications, giving a letter
to each drive. This can be undesirable for the same reasons as exposing
the Z drive and TDF blocks this by default.
Possible values:
1
(default): remove all mappings to external drives
when TDF is started but don't disable the winedevice
service. If you're not using TDF's own Wine builds, drives connected
while Wine is running will be mapped automatically2
: remove all mappings to external drives when TDF is
started and also disable the winedevice
service so that
drives can never be mapped automatically even on other Wine builds (can
break some games and especially installers but improves security)0
: allow access to external drivesTDF_PROTECT_DOSDEVICES
Prevents Wine from automatically handling all drive mappings for better
security. Can cause the winedevice
service to hang when
external drives are connected.
Possible values:
0
(default): let Wine handle drive mappings1
: TDF handles drive mappings and denies Wine write
access to the zzprefix/dosdevices
directoryNote: this option is effectively useless when using TDF's own Wine builds, since dbus is disabled and no mappings will be automatically created.
TDF_BLOCK_SYMLINKS_IN_CDRIVE
When this option is enabled, TDF will scan the C drive on startup and
remove all symlinks. This can be useful in case Wine creats some
symlinks outside the TDF instance during an update, or if you created a
symlink during the installation and forgot to remove it, which can be
dangerous.
Possible values:
1
(default): scan and remove all symlinks in the C
drive on startup0
: allow symlinks in the C driveNote that Wine's symlinks to your home directory, My Documents, Desktop, etc. as well as the creation of shortcuts (.desktop files) on your desktop and start menu will always be blocked regardless of settings; TDF is not designed to let applications "integrate" with the system, quite the opposite.
TDF_FAKE_HOMEDIR
When this option is enabled, Wine will not see your home directory, but
a zzhome
folder will be created in the TDF instance. This
can be used to improve security, but it's mostly useful for games that
require special settings in ~/.driconf
, such as KOTOR.
Possible values:
0
(default): use the real home directory1
: use a fake home directory inside the TDF
instanceNote that the zzhome
folder and all data inside it will
be automatically deleted when this option is disabled.
TDF_GAMESCOPE
Whether to enable Gamescope when running the game or not. This is
generally not recommended when using the games
version of
Wine, since it integrates the fshack patches which makes it mostly
useless, but it can be useful when using the mainline
version for games that change the screen resolution often, require low
resolutions, integers scaling, etc. such as KOTOR or WinQuake. If
Gamescope is not installed in the system, it has no effect.
Possible values:
0
(default): don't use Gamescope1
: use Gamescope when running games if availableNote that Gamescope currently only works properly on AMD GPUs and getting it to work properly on Intel and nVidia cards requires additional configuration.
TDF_GL_MAXFPS
Enables an FPS limiter
for OpenGL applications, based on libstrangle.
Possible values:
0
(default): disabled, and don't load libstrangleTDF_GAMESCOPE_PARAMETERS
The command line arguments used to start Gamescope. You can see a
complete list here.
By default, TDF sets this variable to
-f -r 60 -w $XRES -h $YRES
, where XRES
and
YRES
are two read only variables provided by TDF for
conveninece that contain the horizontal and vertical resolution of the
main display. This default value emulates a virutal screen with the same
resolution as the real display, with a refresh rate of 60hz and sets
Gamescope to run in fullscreen without any special scaling.
TDF_GAMEMODE
Whether to launch the game using Feral Gamemode or not, which can
improve performance especially on weaker or mobile systems. If Gamemode
is not installed in the system, it has no effect.
Possible values:
1
(default): use Gamemode if available0
: don't use GamemodeTDF_MANGOHUD
Whether to launch the game with the MangoHud performance overlay or not.
If MangoHud is not installed in the system, it has no effect. Note that
some games will crash when launched with MangoHud.
Possible values:
0
(default): don't use MangoHud1
: use MangohudTDF_COREFONTS
Whether to install the Microsoft Corefonts or not. These are fonts like
Arial, Comic Sans, etc. that are required by some games such as PC
Building Simulator. This is generally harmless, but if some application
has font rendering issues, try disabling it.
Possible values:
1
(default): install the Corefonts0
: don't install the CorefontsTDF_VCREDIST
Whether to install the Microsoft Visual C++ Redistributable (2015+) or
not. This is useful for modern games but unnecessary for older ones.
Possible values:
1
(default): install VCRedist 2015+0
: don't install VCRedist 2015+TDF_REAPER
Whether to launch Wine using reaper or not. This will improve detection
of when a game is running or not, even if the main exe just launches a
separate process and terminates immediately.
Possible values:
1
(default): use reaper0
: don't use reaperexport DRI_PRIME
Sometimes on systems with multiple GPUs, a game might start using the
wrong GPU, such as the integrated graphics on your laptop instead of the
dedicated card.
By setting a value for DRI_PRIME
you can tell the game
which graphics card to use.
Example:
#use the second GPU
export DRI_PRIME=1
This is not a TDF variable and you can find more about it here.
export SteamGameId
The games-optimized build contains some game fixes from Proton that are
activated by setting this variable with the game's Steam appid.
Example:
#fix black screen in GOW:Ragnarok
export SteamGameId=2322010
You can find the appid for a specific game by searching for it on
Steam and copying it from the URL, for instance:
https://store.steampowered.com/app/2322010/God_of_War_Ragnark/
,
the appid is 2322010
.
Always copy the appid for the main game, not for a DLC.
You can optionally define the following functions inside
vars.conf
and they will be called at specific moments
during operation. This can be useful to fix games that have issues with
window positioning, focusing, etc. or that have some special
requirements. The language is just bash.
If you need to define some variables, do it inside the callback functions, as the configuration is loaded more than once during the initialization process.
customChecks
This function will be called immediately after the configuration is
loaded. It's useful to run some custom checks specific to the game or to
change some settings depending on hardware/software configuration. The
function returns 0 if the checks succeed, 1 to indicate that they failed
and stop TDF. If the function has no return, it will be treated as a
success.
Example:
customChecks(){
if [ "$XDG_SESSION_TYPE" == "x11" ]; then
return 0
else
zenity --error --text="Sorry, this game requires X11"
return 1
fi
}
Note that this function is blocking and TDF won't continue the initialization until it has finished running.
onGameStart
This function will be called right before the game is launched.
Example:
onGameStart(){
setGamma 1.2
}
Note that this function is blocking and the game won't be launched until it has finished running.
onGameEnd
This function will be called when the game's main process finishes
running.
Example:
onGameEnd(){
restoreGamma
}
Notes:
isProcessRunning
(mentioned later) to know
whether the game has actually finished running or notwhileGameRunning
This function will be called right before the game is running, and will
continue running in parallel to the game in a subshell.
Example:
whileGameRunning(){
#workaround for the little black bar at the top of the screen
waitForWindow "APlagueTaleRequiem_x64.exe"
sleep 3
focusWindow $WINDOW
pressKey alt+enter 2
}
Notes:
isProcessRunning
onArchiveStart
This function will be called right before the packaging process begins
when using ./run.sh archive
(mentioned later). It can be
used to remove or move some unnecessary files like DXVK/VKD3D caches,
saved games, etc.. The function receives the same arguments passed to
run.sh
and can return 1 to prevent the packaging process
from starting if something's wrong.
Example:
onArchiveStart(){
TEMPDIR="/tmp/requiem$RANDOM"
mkdir "$TEMPDIR"
mv zzprefix/drive_c/APTRequiem/vkd3d-proton.cache "$TEMPDIR"
mv zzprefix/drive_c/users/wine/AppData/Local/GOG.com "$TEMPDIR"
}
Note that this function is blocking and the packaging process won't start until it has finished running.
onArchiveEnd
This function will be called at the end of the packaging process when
using ./run.sh archive
(mentioned later). It can be used to
restore files modified or deleted by onArchiveStart
. This
function receives 0 in input if the packaging process has succeeded, 1
otherwise.
Example:
onArchiveEnd(){
mv "$TEMPDIR/vkd3d-proton.cache" zzprefix/drive_c/APTRequiem/
mv "$TEMPDIR/tmp/requiem/GOG.com" zzprefix/drive_c/users/wine/AppData/Local/
rm -rf "$TEMPDIR"
}
Note that this function is blocking and TDF won't quit until it has finished running.
For convenience, TDF comes with some functions that can be used inside the callback functions mentioned before, in addition to everything provided by bash such as sleep, grep, etc..
waitForWindow exe title [timeout]
Scans windows to find one that matches the specified exe
and contains title
in the name. If no matching window is
found, it will keep trying for timeout
seconds (30 if not
specified). If exe
is an empty string, it will match any
process with the specified title, if title
is an empty
string, it will match any window from the specified process.
The window IDs will be copied to a WINDOWS
array, with
the first matching window easily accessible with a WINDOW
variable.
The function returns 0 if a match was found, 1 if the timeout was reached.
Examples:
waitForWindow "APlagueTaleRequiem_x64.exe" "A Plague Tale: Requiem" 10
:
waits up to 10 seconds for the process "APlagueTaleRequiem_x64.exe" to
spawn a window that contains "A Plague Tale: Requiem" in the titlewaitForWindow "APlagueTaleRequiem_x64.exe"
: waits up to
30 seconds for the process "APlagueTaleRequiem_x64.exe" to spawn a
windowwaitForWindow "" "A Plague Tale: Requiem"
: waits up to
30 seconds for any process to spawn a window that contains "A Plague
Tale: Requiem" in the titlewaitForWindow "APlagueTaleRequiem_x64.exe" "" 10
: waits
up to 10 seconds for the process "APlagueTaleRequiem_x64.exe" to spawn a
windowNote: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
focusWindow id
Makes the specified window active and focused, useful to fix games where
the taskbar is visible and you have to alt-tab to get rid of it.
The id
of the window can be obtained with the
waitForWindow
function.
Returns 0 if the operation succeeded, 1 if there's no window with the specified id.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
maximizeWindow id
Makes the specified window maximized.
The id
of the window can be obtained with the
waitForWindow
function.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
restoreWindow id
Makes the specified window not maximized.
The id
of the window can be obtained with the
waitForWindow
function.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
minimizeWindow id
Makes the specified window minimized.
The id
of the window can be obtained with the
waitForWindow
function.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
activateWindow id
Makes a minimized window active again.
The id
of the window can be obtained with the
waitForWindow
function.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
moveWindow id x y
Moves the specified window to the requested position.
The id
of the window can be obtained with the
waitForWindow
function.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
resizeWindow id width height
Resizes the specified window to the requested width
and
height
.
The id
of the window can be obtained with the
waitForWindow
function.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
makeFullscreen id
Adds the fullscreen attribute to the specified window, essentially
making it borderless and maximized. Don't use this unless the game has
no other way to go to fullscreen.
The id
of the window can be obtained with the
waitForWindow
function.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
removeFullscreen id
Removes the fullscreen attribute to the specified window. Games react
differently to this, don't use this if the game has a better way to go
to windowed mode.
The id
of the window can be obtained with the
waitForWindow
function.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
keepWindowFocused exe title [timeout]
Keeps a game focused automatically, useful for games that have issues
when alt-tabbing or when the taskbar is still visible when the game is
in fullscreen.
The arguments are the same as the waitForWindow
function, since it works in much the same way.
This function is blocking until the window no longer exists.
Example:
whileGameRunning(){
keepWindowFocused "MassEffect.exe"
}
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
keepWindowFocusedById id
Keeps a game focused automatically, useful for games that have issues
when alt-tabbing or when the taskbar is still visible when the game is
in fullscreen.
This is essentially the same as the keepWindowFocused
except it takes a window id as input, which you can obtain with the
waitForWindow
function.
This function is blocking until the window no longer exists. Returns 1 if the specified window was not found in the first place, 0 if the window was found.
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
pressKey keys [repeats]
Simulates the pressing of the specified key or key combination, which is
sent to the currently active and focused window. Useful for games where
you have to press alt+enter to enter fullscreen or where you need to
press some keys to get rid of a problem.
If a number is added for the repeats
parameter, the
specified key or key combination will be repeated repeats
times, with a delay of 0.5s between each press.
Example:
#workaround for the lag spike when you first press a key in GTA V
whileGameRunning(){
waitForWindow "GTA5.exe" "Grand Theft Auto V"
sleep 3
focusWindow $WINDOW
sleep 1
pressKey w
}
Note: this function uses xdotool
internally and may not
work properly on Wayland, depending on how good the X11 emulation in
your display manager is (works on major ones).
setGamma gamma
Sets the gamma for the main screen. gamma
can either be a
single decimal number (1.0 is the default gamma), or it can be expressed
as 3 separate values r:g:b
. Useful for games that look too
dark on modern displays or when using gamescope since it doesn't support
hardware gamma yet.
Returns 0 if the operation succeeded, 1 if an error occurred.
The gamma level is not restored automatically when the game ends, so
restoreGamma
must be called later.
Note: this function only works on X11.
saveGamma
Stores the current gamma level so it can be restored later with
restoreGamma
.
Returns 0 if the operation succeeded, 1 if an error occurred.
Note: this function only works on X11.
restoreGamma
Restores the gamma level previously saved with saveGamma
.
If a gamma level was never saved, it restores the gamma level from when
TDF was started.
Returns 0 if the operation succeeded, 1 if an error occurred.
Example:
onGameStart(){
saveGamma
setGamma 1.2
}
onGameEnd(){
restoreGamma
}
Note: this function only works on X11.
defaultGamma
Sets the default 1.0 gamma.
Returns 0 if the operation succeeded, 1 if an error occurred.
Note: this function only works on X11.
resetResolution
Resets the main display to its default screen resolution an gamma. This
is useful for when you're not using the game-optimized wine build and an
old game crashes without restoring the screen resolution.
Returns 0 if the operation succeeded, 1 if an error occurred.
Note: this function only works on X11.
Example:
TDF_WINE_PREFERRED_VERSION='mainline'
onGameEnd(){
resetResolution
}
isProcessRunning exe
Determines whether there's a process with a name that contains the value
in exe
(case sensitive). Not limited to Wine
executables.
Returns 1 if a process was found, 0 otherwise.
Example:
if isProcessRunning "explorer.exe"; then
wineserver -k -w
fi
Ideally, you want to have one TDF instance for each game, which keeps
them nicely isolated, but some game series like Mass Effect need to
import the previous game's data or the game itself has expansions/mods
that need to be started with different commands, and therefore need to
be installed in the same TDF instance. This is where that
confs
folder comes in.
Inside the conf
folder, you can make as many
.conf
files as you need, one for each game/mod installed in
the TDF instance. These files follow the same syntax as the
vars.conf
file and each one contains the configuration
necessary to launch one game.
TDF will automatically detect the presence of files in the
conf
folder and show a menu with the list of games in
alphabetical order.
When using this mode, the vars.conf
file will always be
loaded first and its settings will apply to all games, then once the
user has chosen one of the games, the specific .conf
file
will be loaded. If a variable or a callback function is defined both in
vars.conf
and in one of the .conf
file, the
latter wins because it's more specific.
Example for Mass Effect Legendary Edition:
vars.conf
:
#all 3 games use the same arguments so we can put them here
game_args='-NoHomeDir -SeekFreeLoadingPCConsole -Subtitles 20 -OVERRIDELANGUAGE=INT'
confs/Mass Effect 1.conf
:
game_exe='C:\MELE\Game\ME1\Binaries\Win64\MassEffect1.exe'
whileGameRunning(){
keepWindowFocused "MassEffect1.exe"
}
confs/Mass Effect 2.conf
game_exe='C:\MELE\Game\ME2\Binaries\Win64\MassEffect2.exe'
whileGameRunning(){
keepWindowFocused "MassEffect2.exe"
}
confs/Mass Effect 3.conf
game_exe='C:\MELE\Game\ME3\Binaries\Win64\MassEffect3.exe'
whileGameRunning(){
keepWindowFocused "MassEffect3.exe"
}
Note: the TDF_UI_LANGUAGE
variable can only be set in
vars.conf
, since it's applied before TDF is started, all
other variables can be changed at any moment.
By default, when the list of games is displayed, they are shown in
alphabetical order. If you want them to appear in a specific order,
create a file called _list.txt
in the confs
folder, with the list of the configuration files in the order in which
you want them to appear (filenames only, no extension).
Example:
Mass Effect 1
Mass Effect 2
Mass Effect 3
Mass Effect 1 - Configuration Utility
Mass Effect 2 - Configuration Utility
Mass Effect 3 - Configuration Utility
Command Prompt (for modding)
Windows Explorer (for modding)
You installed your game(s) in a TDF instance and made sure it works perfectly? Did you test it on different hardware? Different distros? All good? Great! You're ready to package it.
To start the packaging process, open a terminal inside the TDF
instance and type ./run.sh archive
. This will create an
archive containing the whole TDF instance that you can easily
redistribute (assuming you have the rights to do it). Users will be able
to simply extract these archives and launch run.sh
to start
the game.
By default, TDF creates a highly compressed .tar.zst
archive, which takes a long time to create but can be extracted very
quickly.
During the compression process, TDF will show you a progress indicator. At the end of the process, it will tell you the compressed size and the compression ratio.
If you want to customize the way these archives are created, the
following short commands can be added after
./run.sh archive
:
nocompress
: creates a simple uncompressed
.tar
archive. Very fast but not ideal for
redistributionfastcompress
: creates a compressed .tar.xz
archive, compressed with multithread XZ. Compression is relatively fast,
decompression is also quite fast, but the compression ratio is not the
bestmaxcompress
: creates a compressed .tar.zst
archive, compressed with single thread ZStandard with the highest
settings. This is pretty slow but decompression is very fast and also
has good compression ratio. This is what Fitgirl would call a "monkey
repack"Generally speaking, the short commands above are the only ones you
should need but if you want to customize it further, you can specify the
following options after ./run.sh archive
instead of the
short commands above:
-o path
: path to output file (relative or absolute). If
the path contains an extension such as .tar.zst, TDF will automatically
select the appropriate compression method; otherwise an appropriate
extension will be added automatically. If not specified, it creates a
file with the same name as the folder containing the TDF instance.-m method
: compression method to use. Supported values
are zstd
(default), xz
, gzip
and
tar
(uncompressed). Not required if a file extension has
already been specified with -o
-p preset
: compression preset to use. TDF provides 3
presets for each method: max
(slow but smallest size),
normal
(balances speed and compression), fast
(favors speed over compression). By default, zstd
uses
max
, which is very slow, xz
uses
fast
and gzip
uses normal
,
tar
does not compress so this parameter will be
ignored-f
: overwrite the output file if it already exists,
otherwise it will just show an error-s size
: split the output file in a multipart archive
of the specified size. Supported values are any positive integer
followed by M
or G
, such as 100M
or 1G
. auto
can also be used to automatically
decide the split size based on input size, similar to scene releases
(<1G: 100M parts, 1G-10G: 1G parts, 10G-100G: 5G parts, 100G-250G:
10G parts, 250G-500G: 25G parts, >500G: 100G parts). A script to
extract the multipart archive will also be created, in case your archive
manager doesn't support it.Examples:
#compress using zstd maximum to a file called example.tar.zst in the upper directory
./run.sh archive -o ../example.tar.zst
#compress using xz normal to a file called example.tar.xz in the home directory
./run.sh archive -m xz -p normal -o ~/example.tar.xz
#compress using xz fast to a file with the same name as the current folder and put it in the upper directory
./run.sh archive -m xz -p fast
#compress using zstd maximum to a file called example.tar.zst in the upper directory, split in 5G parts
./run.sh archive -o ../example.tar.zst -s 5G
Note: this feature assumes that tar
, xz
,
gzip
and zstd
are installed on your system
(they probably are).
If you want to transfer a TDF instance from one PC to another using an external drive, it is strongly recommended to use the archive function so that it's just one big file. Never copy a TDF instance to an NTFS, exFAT or a FAT32 partition, it will become unusable.
TDF is designed to be easy to update. To update a TDF instance from an older version:
system
folder and run.sh
system
and run.sh
from the newer
version to the TDF instance, where the old ones used to beIt is also possible to downgrade to an older version of TDF in the same way, in case the newer version introduces some problems.
TDF will automatically detect and apply changes to the files in the
following folders inside the system
of a TDF instance:
dxvk
dxvk-async
dxvk-nvapi
localization
msi
reaper
strangle
tdfutils
vcredist
vkd3d
wine-games
wine-mainline
xutils
zenity
So for instance, if you need to test a custom version of DXVK, simply
replace the DLLs in system/dxvk
with your build (making
sure to keep the same folder structure), when you launch
run.sh
, TDF will detect that these DLLs don't match the
ones in the wineprefix and reinstall DXVK. The same goes for Wine and
other components in the list above.
Note: your custom files will only be used if that component is
actually being used. For instance, if your GPU supports the
VK_EXT_graphics_pipeline_library
, then DXVK-gplasync will
never be used unless you explicitly set TDF_DXVK_ASYNC=1
or
switch to an older driver.
The following folders are not monitored for changes as they are very rarely needed:
corefonts
Should you need to test changes to them, simply disable that
component, launch run.sh
, then reenable it and launch it
again.
TDF is built to be partially modular, meaning that if your game doesn't need certain components, such as Wine Mono, they can be removed to reduce overhead.
Do not do this unless you know what you're doing.
The following folders can be deleted from the system
folder of a TDF instance if they are not needed:
dxvk
dxvk-async
(Note: if this is removed, it is recommended
to set TDF_DXVK_ASYNC=0
, that way it won't try to use it on
GPUs that don't support the GPL extension)dxvk-nvapi
msi/winemono.msi
msi/winegecko32.msi
and
msi/winegecko64.msi
reaper
strangle
(Note: if this is removed, FPS limiting for
OpenGL will not be available)tdfutils
themes
(Note: if this is removed, leave
TDF_WINE_THEME
empty)vcredist
vkd3d
wine-games
(Note: if this is removed, it is recommended
to set either TDF_WINE_PREFERRED_VERSION="mainline"
or
TDF_WINE_PREFERRED_VERSION="system"
, otherwise TDF will try
to use the version of Wine provided by the system or
wine-mainline
as a last resort. If neither are available,
TDF will fail to start)wine-mainline
(Note: if this is removed, it is
recommended to set either
TDF_WINE_PREFERRED_VERSION="games"
or
TDF_WINE_PREFERRED_VERSION="system"
, otherwise TDF will try
to use the version of Wine provided by the system or
wine-games
as a last resort. If neither are available, TDF
will fail to start)zenity
(Note: if this is removed and Zenity is not
installed in the system, TDF will still work but it will not have a
GUI)Folders and files not mentioned in this list should not be removed to avoid breaking TDF.
If a component has been removed, TDF will not try to use or install
it even if explicitly requested in the config. If a component is removed
after it has been installed in the wineprefix, it will not be removed
even if explicitly requested in the config.
For these reasons, it's better to remove components before the first
time initialization of the wineprefix.
Never remove a component that is currently installed in the wineprefix, as this will leave it in an inconsistent state, especially during Wine updates. If that happens, simply restore the removed components and TDF should take care of the problem.
This section covers troubleshooting games on Wine in general, with a focus on how to do it with TDF. In general, some good knowledge of Windows and Linux will be very useful here.
If a game doesn't work out of the box, before you even start troubleshooting, check ProtonDB for known issues/fixes for this game. Solutions that work on Proton can easily be adapted to work in TDF.
Wine depends on a lot of libraries, TDF is built exclusively using
64-bit libraries, so multilib is not required. The easiest way to obtain
these is to simply install Wine on your system and then removing it. *
For Arch-based distros:
sudo pacman -S wine sudo pacman -R wine
* For Debian-based
distros:
sudo apt-get install wine sudo apt-get remove wine
./run.sh
, and looking at the errors
that appear while TDF tries to load. If this is your case, at the moment
the only solution is either building TDF yourself or using a more modern
distroTDF_WINE_PREFERRED_VERSION='mainline'
during
the installation, using a normal version of Wine instead of the
game-optimized one can get it to workexport WINE_HEAP_DELAY_FREE=1
during the
installation, this can workaround memory management bugs in the
installer (very useful for repacks)zzprefix/drive_c
WINEDLLOVERRIDES
) or it could be missing some DLL (see next
section)_CommonRedist
or
_Redists
in the game's folder, that will most likely
contain some installers for libraries required by the game. They're
usually not necessary with Wine but some older redists like PhysX will
need to be installed.
game_exe
and launch run.sh
game_exe
and try launching the game againexport WINEDEBUG=-all,+loaddll
to
vars.conf
./run.sh
xinput1_3.dll
or
d3dcompiler_43.dll
indicates that you need to install the
old
DirectX redistributablemscoree.dll
indicates that you're
trying to load a .net application, try adding
TDF_WINEMONO=1
to the configurationmsvcrt###.dll
or
vcruntime###.dll
indicates that you need a specific version
of the Microsoft Visual C++ Redistributablemshtml.dll
indicates that you're
trying to load an application that depends on Internet Explorer, try
adding TDF_WINEGECKO=1
to the configurationgame_exe
from the
configuration and launch run.sh
to enter "install mode",
install what you downloaded, then put back game_exe
and try
launching the game againunset WINEDEBUG
and
TDF_WINE_HIDE_CRASHES=0
to enable Wine's default debugging
messages and "stopped working" screen./run.sh
TDF_WINE_DEBUG_RELAY=1
and launch the game, it
will ask you where you want to save the trace and then try to launch the
game. Keep in mind that Wine runs extremely slow while this is enabled
and the generated trace could be several GB in sizeTDF_WINE_MAXLOGICALCPUS=4
to simulate a
quad-coregame_exe
to another file or adding some arguments
with game_args
TDF_WINEMONO=1
and
TDF_WINEGECKO=1
export DRI_PRIME=1
to the config, where 1 is the
number of the GPU that you want to use (starting from 0)dinput8.dll
, version.dll
,
winmm.dll
, dsound.dll
, etc., this is a common
technique used by mods to inject code, add
export WINEDLLOVERRIDES="filename1,filename2,...=n,b"
. Note
that the filenames must not have an extension, only the name. Example:
export WINEDLLOVERRIDES="winmm=n,b"
.TDF_WINE_LANGUAGE
variablesteam_api.ini
that will contain some
configuration, including the languagegame_args
variable)game_exe
from the configuration to get into "install mode",
run regedit and find the keyamd_ags_x64.dll
or
nvapi.dll
, you can force Wine to use its own fake version
to fix this problem by adding
export WINEDLLOVERRIDES="amd_ags_x64=b"
. If you need to add
multiple overrides, separate them with a semicolon. Example:
export WINEDLLOVERRIDES="winmm=n,b;amd_ags_x64=b"
VK_EXT_graphics_pipeline_library
extension by running this
command:
vulkaninfo | grep VK_EXT_graphics_pipeline_library
, if you
don't see anything, your GPU/driver doesn't support it and your
experience will be miserableTDF_MANGOHUD=1
, this provides a nice overlay for various
things, including VRAM usage. When it's above 90%, you'll start running
into problemsTDF_WINE_MAXLOGICALCPUS=4
to simulate a
quad-coreTDF_WINE_SYNC="esync"
TDF_WINE_MAXLOGICALCPUS=4
to simulate a
quad-coreTDF_WINE_PREFERRED_VERSION=mainline
TDF_DXVK=0
VK_EXT_depth_bias_control
extension yet (added in Mesa 23.3
for AMD/Intel)dxvk.conf
in the game's folder and tinker with DXVK's
settingsunset VKD3D_CONFIG
to disable ray tracing support that's normally enabled by default by
TDFexport RADV_DEBUG=nodcc
export RADV_DEBUG=llvm
export ACO_DEBUG=noopt
export RADV_PERFTEST=nosam
export AMD_DEBUG=nongg
export WINE_HEAP_DELAY_FREE=1
unset WINEDEBUG
to the
configuration, open a terminal and run ./run.sh
, if you see
errors about shader compilation, you probably need to install the old
DirectX redistributableexport WINEDLLOVERRIDES="msvcrt,msvcp=n,b"
unset WINEDEBUG
and
TDF_WINE_HIDE_CRASHES=0
to the config, open a terminal and
run ./run.sh
, most of the messages you'll see are
innocuous, but some may provide clues about what's going onIf you find a solution to a problem, always make sure to report it somewhere. If you can't find a solution, report the problem to one of the projects involved, at worst they'll tell you it's not their fault and where to report it. People are generally very friendly in the Linux gaming community.
export PULSE_LATENCY_MSEC=120
export WINEDLLOVERRIDES="dsound=n,b"
TDF_WINE_DEBUG_GSTREAMER=1
, it may provide
details about what's happeningTDF_WINE_DPI=96
TDF_WINE_KILL_AFTER=1
, this will terminate all Wine
processes when the game's main process terminatesgame-devices-udev
package on the AUR will take care of most
models, otherwise, this article will
help users of all distroszzprefix
and
start over with a new TDF instanceThe TDF build scripts are designed to download the latest version of
each component in TDF, build what needs to be compiled from source and
create a template-YYYYMMDD.tar.zst
ready to extract and
use.
It is strongly recommended to use an Arch-based distro to build TDF.
To build TDF:
git clone https://github.com/adolfintel/tdf
cd tdf
./makeTemplate.sh
The following dependencies must be installed on your system:
base-devel
package should provide everything you need)The following components will be downloaded:
The following components will be built from source:
The first build will take a good 30-60 minutes to download and compile everything, but subsequent builds will be quicker as the download phase will only download updates for the components and the TDF repo itself.
If the build fails (and let's be honest, the first times it probably
will), fix the problem and run ./makeTemplate.sh
again, the
script will automatically resume from where it left off.
If you don't want to use this caching and resuming system, you can
run a clean build using ./makeTemplate.sh clean
, this will
delete all saved data and redownload everything, then build TDF.
If you're going to build TDF regularly, you can enable automatic
updates for the TDF repo using
TDF_BUILD_AUTOUPDATE=1 ./makeTemplate.sh
(git only).
At the end of the build process, the package will be compressed using a slow but efficient zstd compression and the finished archive will be ~310MB.
While TDF provides some additional security compared to a standard installation of Wine or Proton, it is important to understand that Wine is simply not designed for security, quite the opposite, it's designed to seamlessly integrate Windows stuff into Linux.
Wine is an HLE (High Level Emulator) which means that, to put it simply, it doesn't emulate an entire system like dosbox does because it would be too slow, instead it provides a way to load Windows exe files, intercept Windows system calls and "convert" them to equivalent Linux system calls. It also provides a ton of libraries and other functionality but that's not relevant here.
What this means is that a process running inside Wine is, to all intents and purposes, a regular UNIX process that's running under your user, and therefore has access to everything you have access to, and malicious software can easily escape the restrictions put in place by Wine or TDF by using Linux system calls directly, it only requires some modest knowledge of assembly.
This is not really a problem if you're just running games, the chances of games containing such a sophisticated malware are virtually zero, but it's important to understand that TDF is not a safe way to run malware or other software downloaded from dubious sources, it can easily escape the sandboxing and damage the real system. Always use a well isolated VM to test or reverse engineer malware.
To put it short: if you're worried about telemetry and data collection in games, you just don't want games to put files all over your system or you just want to package games, TDF is good; if you're going to run GTAV_Installer.exe (2.9MB) downloaded from SkidEmpressReloadedLegitCracks69.ru it is very much not.
Important: some cracked copies of games that I have in my Steam/GOG/EGS library are used in these videos. These cracks have been used to circumvent DRM issues or incompatibilities with modern systems. TDF does not endorse piracy and I will not provide cracked copies of games.
This project started off in 2021 as a "template" that I could use to easily create these self-contained ready-made environments to easily and safely run Windows games, something that things like Lutris couldn't do really well despite having a nice GUI.
Eventually, my friends started calling it "Template Di Frederico", meaning Frederico's Template in Italian (Frederico being a common misspelling of my name, Federico); the temporary name eventually stuck, it got abbreviated to TDF or just "the template", and I couldn't come up with a better name so TDF became the official name in 2023 when I finally decided to write some documentation and release it.
All TDF code is distributed under the GNU GPL v3 license, but a built version of TDF will contain components with multiple licenses, including proprietary ones.
Copyright (C) 2021-2025 Federico Dossena
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/gpl-3.0.