SIL: System Interface Library for games
=======================================
Platform notes for Windows
Build environment
-----------------
The Makefile-based SIL build system is designed to be platform-agnostic,
but it does require GNU Make and a
POSIX-compliant shell such as Bash
along with the standard set of POSIX command line tools; Microsoft's
NMAKE tool and the CMD.EXE command-line interpreter will not suffice,
though the initial "make" command can be run from CMD.EXE if the other
prerequisites are satisfied.
If using Windows 10 (2017 Creators Update) or later, the Windows
Subsystem for Linux provides a convenient POSIX-compliant environment
for building SIL programs. Install "make" with "sudo apt install make"
and the GCC compiler with "sudo apt install g++ g++-mingw-w64", then
just run "make" in the project build directory to build the program.
The tool programs included in SIL require some auxiliary libraries (see
the notes under "Tool programs" in README.txt); these can be installed
with "sudo apt install zlib1g-dev libpng-dev". You may first need to
update the environment by running "sudo apt update && sudo apt upgrade".
See for more
information.
On a multi-core system, adding the "-jN" option (where "N" is the number
of cores) will let the build proceed in parallel, which can considerably
reduce the total build time. For example, on a quad-core system with
2-thread-per-core hyperthreading, use the command "make -j8" instead of
just "make". Depending on the speed of your storage device, it may even
help to increase N by 1 or 2 so that a process waiting for disk I/O
doesn't leave a core idle.
The very first time you compile in a Windows Subsystem for Linux
environment, the SIL build system may issue a warning saying "Can't
determine compiler type, assuming GCC". This can be safely ignored.
The Microsoft Visual Studio compiler _cannot_ be used to build SIL
programs (at least as of Visual Studio 2017) because it does not support
enough of the C99 standard.
Build products and required DLLs
--------------------------------
On Windows 8.1 and later, the only file (other than resource data files
loaded using the resource_*() functions) needed to run the program is
the executable file ".exe" created in the build directory.
However, to support game controllers which use the XInput interface,
Windows 7 and earlier require xinput1_3.dll from the DirectX
redistributable (see "Joystick (game controller) device support" below).
Typically, this is installed via the June 2010 DirectX end-user runtime
installer from Microsoft, which can be bundled with the application.
As part of the build process, an application manifest file is created
under the name ".exe.manifest". This is only a temporary file
and can be safely removed after a build completes ("make clean" will
remove it along with other temporary and intermediate files), but if the
file is present, Windows XP will refuse to start the executable. If
testing on Windows XP, be sure to remove the manifest file or move the
executable to a different directory before running the program.
Fullscreen mode and window focus
--------------------------------
When running in fullscreen mode, SIL will by default minimize the window
if it loses focus (because the user pressed Alt-Tab to switch windows,
for example). This is necessary in single-monitor environments to
ensure that the user can actually see other windows, but it may be
undesirable in multi-monitor setups in which the user has the SIL
program running fullscreen on one monitor and other applications running
on another monitor.
To control whether SIL auto-minimizes the window on loss of focus, set
the display attribute "fullscreen_minimize_on_focus_loss". This
attribute takes a single argument of type int; a false (zero) value
prevents the window from being minimized on loss of focus, while a true
(nonzero) value restores the default behavior of auto-minimizing. (If
not in fullscreen mode, the window never auto-minimizes regardless of
this setting.)
For compatibility with programs using SDL 2.x, SIL also recognizes the
environment variable SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS. If the SIL
display attribute has not yet been set, the default behavior will be
taken from the value of this variable if it is present and non-empty:
a value of "0" or "false" (case-insensitive) will disable
auto-minimization, while any other value will enable it.
Graphics rendering
------------------
By default, SIL uses OpenGL for graphics rendering. SIL also supports
rendering with Direct3D 11, which can be enabled by setting the Windows-
specific "backend_name" display attribute to the string "direct3d":
graphics_set_display_attr("backend_name", "direct3d");
Similarly, if Direct3D is already in use, SIL can be switched back to
OpenGL by selecting the "opengl" backend:
graphics_set_display_attr("backend_name", "opengl");
The new backend will be enabled on the next display mode change. Note
that all graphics resources will be invalidated when the backend is
changed, so they must be reloaded as needed.
The Direct3D backend does not currently implement either the shader
generator API (graphics_set_shader_generator()) or custom shader objects
(shader_*()).
Note that the Direct3D operations corresponding to graphics primitive
creation in SIL (graphics_create_primitive(), graphics_draw_vertices(),
etc.) are expensive compared to OpenGL. SIL tries to hide this overhead
as well as it can, but programs which make heavy use of immediate-mode
rendering may get better performance with OpenGL.
The Direct3D backend supports these additional display attributes:
- d3d_shader_opt_level: Accepts 1 int, a value from 0 through 3 giving
the desired optimization level for shader compilation. This is used
for both autogenerated shaders and custom shader objects. The default
is 1. Changes to this attribute take effect immediately.
- d3d_shader_debug_info: Accepts 1 int; a true (nonzero) value enables
inclusion of debug information in compiled shaders, while false (0)
disables debug information. This can be useful in debugging shaders
using the Microsoft Visual Studio debugging tools. The default is
false. Changes to this attribute take effect immediately.
When using OpenGL, if graphics_set_display_mode() fails with a
BACKEND_TOO_OLD error, it usually indicates that Windows is attempting
to use the software renderer, which identifies itself as OpenGL 1.1.
This usually indicates that the graphics driver is too old for the
current version of Windows; updating the driver will often solve the
problem, but in some cases, the user's GPU or the associated OpenGL
driver may simply not be supported on the version of Windows in use.
(This has been observed, for example, with Intel HD Graphics 3000 and
4000 integrated GPUs on Windows 10 version 1709.) In some cases,
DirectX may work even when OpenGL does not.
Some Windows graphics drivers deliberately deviate from the OpenGL or
Direct3D specification, ostensibly to improve graphics performance or
quality. These deviations are generally intended for specific 3D
rendering patterns, and they can cause 2D rendering in particular to
break spectacularly. Users should be advised to check their driver
settings and make sure that any "graphics quality" or similar options
are turned off, or set to "Use application settings" if such a choice is
present.
SIL normally spawns a separate thread to process window messages, which
improves Windows UI responsiveness (such as when moving the window); in
particular, when window resizing is enabled, this allows the program to
continue rendering while the window is being resized. The multithreaded
logic is written to conform to the Windows API; however, some older
graphics drivers and third-party software have been reported to have
trouble with multithreaded programs. In case a workaround is needed,
SIL supports a Windows-specific display attribute to control whether
multithreading is used for window management:
- window_thread: Accepts 1 int; a true (nonzero) value enables
multithreading for window operations, while false (0) disables
multithreading. The default is true.
Note that disabling window multithreading will reduce Windows UI
responsiveness and prevent the program from updating the window while
it is being resized.
Joystick (game controller) device support
-----------------------------------------
SIL supports joystick devices through both the XInput interface, for
Xbox game controllers, and the WM_INPUT interface, for other USB or
Bluetooth controllers compatible with the HID standard. XInput requires
either xinput1_3.dll from the DirectX redistributable or xinput1_4.dll
which is distributed with Windows 8 and later; xinput9_1_0.dll, included
with Windows Vista and 7, is not accepted due to deficiencies in the
library. WM_INPUT requires the hid.dll library, which is standard in
all Windows distributions. In either case, if the required library
cannot be loaded at runtime, the associated input interface will be
disabled.
If desired, the user can disable either joystick interface by setting
environment variables as follows (the quotes are not part of the value):
- SIL_WINDOWS_USE_XINPUT="0": Disables the XInput interface.
- SIL_WINDOWS_USE_RAWINPUT="0": Disables the WM_INPUT interface.
Setting either environment variable to "1" will cause SIL to display an
error message when the required library is unavailable (if the
SIL_UTILITY_NOISY_ERRORS build option is enabled), which can be used to
determine if a missing DLL is causing a joystick device to not be
recognized.
Typically, XInput devices are also exposed as HID devices. If both
XInput and HID interfaces are enabled, SIL will use the XInput interface
for devices which report themselves as XInput-compatible.
The following devices are known to work "out of the box":
- Microsoft Xbox 360 wired controller (using the XInput interface).
Note that Microsoft deliberately cripples the Xbox 360 controller when
used with the WM_INPUT interface, so if a user reports that they can't
use the LT and RT trigger buttons or rumble effects, that may be due
to XInput not being available.
- Sony DualShock 4 (using the WM_INPUT interface).
The following devices are known to have problems:
- Sony SIXAXIS and DualShock 3: These controllers require a "secret
handshake" from the host before they will start reporting events (see
the Linux driver, linux/drivers/hid/hid-sony.c, for details). This
handshake is in the form of a feature request for a report not listed
in the device's report descriptors, and the standard Windows HID
driver rejects attempts to call HidD_GetFeature() for unlisted
reports, so there is no way to activate the controller from userspace
on Windows. There are third-party drivers, albeit of unknown safety
and stability, which support these controllers as XInput devices.
Note that at least as of January 2018, Valve Software's Steam client
injects a DLL which wraps the system function GetRawInputDeviceList() with
a buggy function that prevents SIL from scanning WM_INPUT devices. SIL
will log a message to this effect if it detects the bug. (Steam itself
appears to expose game controllers via the XInput interface, so this may
not cause any actual problems.)
Long pathname support
---------------------
The Windows API has traditionally limited pathnames to a maximum of 260
characters. Generally speaking, this should not be a problem for SIL
programs; however, if a user installs the program in a location with a
particularly long pathname, or if you use userdata_override_file_path()
with a long pathname, you may encounter unexpected errors.
In Windows 10 version 1607 and later, applications can opt in to a
longer pathname limit (32,767 characters) with an application manifest
setting. SIL does not enable this by default, to ensure that the
program does not unintentionally create files which other programs might
not be able to access. However, if you need this behavior, you can copy
and modify the default application manifest template
(build/windows/manifest.xml.in) to include the tag
in the block (make sure to also add the "xmlns:ws2"
attribute to ):
true
Set the "make" variable MANIFEST_TEMPLATE to the pathname of your
modified template file to apply it to the final executable.
Note that users can also enable long pathnames globally by setting a
registry key. For more information, see the section "Maximum Path
Length Limitation" of the MSDN document "Naming Files, Paths, and
Namespaces (Windows)", which can (as of this writing) be found at:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#maxpath
Synchronization primitives
--------------------------
SIL implements mutexes using Windows CRITICAL_SECTION objects. These
provide significantly better performance than full-fledged Mutex
objects; the latter are only needed if mutexes must be shared between
processes (as opposed to threads), which is typically not the case for
SIL-based programs. The one caveat to CRITICAL_SECTION objects is that
Windows does not include a "timed wait" operation on them, so timed
waits are implemented as a loop which polls the mutex and calls Sleep(1)
if acquisition fails. Depending on system load and timer resolution,
this can have a fairly coarse resolution, so do not rely on
mutex_lock_timeout() for precise timing.
Windows will abort (with EXCEPTION_POSSIBLE_DEADLOCK) a program which
waits on a mutex for longer than the timeout given by the
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\
CriticalSectionTimeout" registry value. The default value is 2592000
seconds (30 days), so this should not be a problem in practice, but it
may occur on systems in which CriticalSectionTimeout is set to an
abnormally low value. (Notably, the WINE libraries for non-Windows
platforms use a timeout of just 65 seconds.)
Windows XP lacks native support for condition variables. SIL includes a
substitute implementation, but it is fairly slow, so be aware that heavy
use of condition variables in code hotspots may impair performance on XP
systems.
Touch input
-----------
SIL uses the WM_POINTER* event interface, introduced in Windows 8, for
touch input. Windows 7 also includes support for touch events, but this
support uses a completely different, more kludgey interface (WM_TOUCH),
and there are currently no plans to support this interface in SIL.
Accordingly, touch input is only supported for Windows 8 or later.
User data location
------------------
The userdata_*() family of functions reads and writes files in the
directory "\". is the
%APPDATA% folder for the current user; this is usually:
- On Windows Vista and later, C:\Users\\AppData\Roaming
- On Windows XP, C:\Documents and Settings\\Application Data
(The folder can also be opened by typing "%APPDATA%" in the Explorer
location bar.) is the string passed as the first
parameter to userdata_set_program_name().
Known quirks
------------
- The Windows OpenGL driver for Intel GPUs has two significant bugs
affecting at least the HD Graphics 4000 and 4400, present through at
least version 15.33.46.4885:
* When a fullscreen window is minimized, the driver fails to stop
drawing the window, so it hides all other windows even though
some other window is in fact receiving input.
* Specific to the HD Graphics 4000: Under unknown conditions,
glFinish() (and thus graphics_sync()) can block for several
seconds even though GPU rendering has completed. In particular,
enabling sync-on-frame-start with graphics_enable_debug_sync()
appears to trigger this behavior fairly frequently.
There are no known workarounds for either of these bugs, so it is
recommended to use DirectX with this GPU.