Created
September 20, 2018 01:07
-
-
Save grepwood/ddc9e41779fa5414b9946fe4b212c84d to your computer and use it in GitHub Desktop.
Setup Fallout 4 on Wine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
SCRIPT_NAME="$(basename "${0}")" | |
FALLOUT4_EXECUTABLE="Fallout4.exe" | |
WINE_REGISTRY_KEY="HKEY_CURRENT_USER\\Software\\Wine" | |
FALLOUT4_APPDEFAULTS_REGISTRY_KEY="HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\${FALLOUT4_EXECUTABLE}" | |
FALLOUT4_INSTALL_REGISTRY_KEY='HKEY_LOCAL_MACHINE\Software\Bethesda Softworks\Fallout4' | |
USER_SHELL_FOLDERS_REGISTRY_KEY='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders' | |
function die() { | |
printf "%s : %s() : %s\\n" "${SCRIPT_NAME}" "${FUNCNAME[1]}" "${1}" >&2 | |
exit 1 | |
} | |
# get_registry_value() | |
# Returns "data" from a specified Registry key and value, where "value"="data". | |
# Note: the Wine reg query result will use \r\n CR linefeeds - strip these! | |
function get_registry_value() { | |
local registry_key="${1}" registry_value="${2}" | |
declare -n data="${3}" | |
data="$(wine reg query "${registry_key}" /v "${registry_value}" 2>/dev/null \ | |
| awk -F 'REG_[A-Z]*' \ | |
-vregistry_value="${registry_value}" \ | |
'{ | |
for (i=1;i<=NF;++i) | |
gsub("(^[[:blank:]]*|[[:blank:]]*$)","",$i) | |
if ($1 == registry_value) | |
print $2 | |
}' 2>/dev/null \ | |
| sed 's/\r//g' | |
)" | |
[[ -z "${data}" ]] && die "Registry key data lookup [${registry_key}] \"${registry_value}\"=... failed" | |
} | |
# add_registry_value() | |
# Adds a Wine Registry key or a key plus "value"="data". | |
function add_registry_value() { | |
local registry_key="${1}" registry_value="${2}" data="${3}" type="${4}" | |
if [[ -z "${registry_value}" ]]; then | |
wine reg add "${registry_key}" /f 2>/dev/null \ | |
|| die "Failed to add Registry key [${registry_key}]" | |
else | |
wine reg add "${registry_key}" /v "${registry_value}" /t "${type}" /d "${data}" /f 2>/dev/null \ | |
|| die "Failed to add Registry key+value: [${registry_key}] \"${registry_value}\"=\"${data}\" (${type})" | |
fi | |
} | |
# delete_registry_value() | |
# Deletes a Wine Registry key or key plus value pair. | |
function delete_registry_value() { | |
local registry_key="${1}" registry_value="${2}" | |
if [[ -z "${registry_value}" ]]; then | |
wine reg delete "${registry_key}" /va /f &>/dev/null | |
else | |
wine reg delete "${registry_key}" /v "${registry_value}" /f &>/dev/null | |
fi | |
} | |
# convert_windows_to_unix_path() | |
# Convert a Windows path to a canonical Unix path - follows all symbolic links. | |
# Note: winepath outputs \r\n CR linefeeds - so we must strip these! | |
function convert_windows_to_unix_path() { | |
local windows_path="${1}" unix_path | |
declare -n canonical_unix_path="${2}" | |
unix_path="$(winepath -u ''"${windows_path}"'' 2>/dev/null | sed 's/\r//g')" | |
canonical_unix_path="$(readlink -f "${unix_path}")" | |
if [[ ! -d "${canonical_unix_path}" ]]; then | |
die "Unable to convert Windows directory: \"${windows_path}\"; to a Unix directory." | |
fi | |
} | |
# find_file() | |
# Finds a specified file, using a specified base directory+relative path offset. | |
# Note: must use a case-insensitive search! | |
function find_file() { | |
local search_path="${1}" relative_path="${2}" depth relative_path_regex | |
declare -n target="${3}" | |
[[ -d "${search_path}" ]] || die "File search directory does not exist \"${search_path}\"" | |
depth="$(echo "${relative_path}" | awk -F'/' '{ print NF }')" | |
relative_path_regex=".*$(echo "${relative_path}" | sed 's/[-.()\/]/\\&/g' 2>/dev/null)" | |
# Without this last grep you will end up finding multiple directories | |
target="$(find "${search_path}" -mindepth "$((depth-1))" -maxdepth "$((depth))" -iregex "${relative_path_regex}" 2>/dev/null | grep "${2}")" | |
[[ -f "${target}" ]] || die "File search failed: \"${search_path}${relative_path}\"" | |
} | |
# ini_file_overwrite_value() | |
# Add/Overwrite name=value pair in a specified .ini file section. | |
# Note: Windows .ini files will use \r\n CR linefeeds - don't break this! | |
function ini_file_overwrite_value() { | |
local ini_file="${1}" name="${2}" value="${3}" section="${4}" | |
[[ -f "${ini_file}" ]] || die ".ini file path not valid: \"${ini_file}\"" | |
# shellcheck disable=SC1004 | |
sed -i -e '\|^'"${name}"'=|d' -e '\|^\['"${section}"'\]|a\ | |
'"${name}=${value}\\r" "${ini_file}" 2>/dev/null \ | |
|| die "sed operation failed on: \"${ini_file}\"" | |
} | |
# I don't like it when scripts are messy and dirty like they lack a main function. | |
# Makes it so much harder to read them. | |
function main { | |
[[ -z "${WINEPREFIX}" ]] && die "WINEPREFIX env variable not set" | |
[[ -d "${WINEPREFIX}" ]] || die "WINEPREFIX env variable is set to an invalid path: \"${WINEPREFIX}\"" | |
((EUID==0)) && die "Do not run this script as the root user!" | |
# Get Wine user 'My Documents' folder from Wine Registry. | |
get_registry_value "${USER_SHELL_FOLDERS_REGISTRY_KEY}" \ | |
'Personal' "WINDOWS_USER_DOCUMENTS_PATH" | |
convert_windows_to_unix_path "${WINDOWS_USER_DOCUMENTS_PATH}" "UNIX_USER_DOCUMENTS_PATH" | |
# Get install directory of Fallout 4 from Wine Registry. | |
get_registry_value "${FALLOUT4_INSTALL_REGISTRY_KEY}" \ | |
'installed path' "WINDOWS_FALLOUT4_INSTALL_PATH" | |
convert_windows_to_unix_path "${WINDOWS_FALLOUT4_INSTALL_PATH}" "UNIX_FALLOUT4_INSTALL_PATH" | |
# Find 2 main Fallout 4 configuration files. | |
find_file "${UNIX_USER_DOCUMENTS_PATH}" '/My Games/Fallout4/Fallout4.ini' "USER_FALLOUT4_INI_FILE" | |
find_file "${UNIX_FALLOUT4_INSTALL_PATH}" 'Fallout4_Default.ini' "GAME_FALLOUT4DEFAULT_INI_FILE" | |
# Set bBackgroundMouse=1 : Switches between the game controlling the mouse position (0) or the operating system (1). | |
ini_file_overwrite_value "${USER_FALLOUT4_INI_FILE}" "bBackgroundMouse" "1" "Controls" | |
ini_file_overwrite_value "${GAME_FALLOUT4DEFAULT_INI_FILE}" "bBackgroundMouse" "1" "Controls" | |
# GrabFullscreen=Y | |
add_registry_value "${WINE_REGISTRY_KEY}\\X11 Driver" 'GrabFullscreen' 'Y' 'REG_SZ' | |
# Version=win7 | |
add_registry_value "${FALLOUT4_APPDEFAULTS_REGISTRY_KEY}" 'Version' 'win7' 'REG_SZ' | |
# Setup winetricks xact | |
winetricks -q --force xact &>/dev/null || die "winetricks xact failed" | |
# Move xact audio Dll Overrides to Fallout 4 AppDefaults. So this set of DLL Overrides | |
# doesn't affect other games/applications in the same Wineprefix. | |
for dll in "xaudio2_0" "xaudio2_1" "xaudio2_2" "xaudio2_3" "xaudio2_4" "xaudio2_5" "xaudio2_6" "xaudio2_7" "x3daudio1_0" "x3daudio1_1" "x3daudio1_2" "x3daudio1_3" "x3daudio1_4" "x3daudio1_5" "x3daudio1_6" "x3daudio1_7"; do | |
delete_registry_value "${WINE_REGISTRY_KEY}\\DllOverrides" "*${dll}" | |
delete_registry_value "${WINE_REGISTRY_KEY}\\DllOverrides" "*${dll}" | |
delete_registry_value "${FALLOUT4_APPDEFAULTS_REGISTRY_KEY}\\DllOverrides" "*${dll}" | |
add_registry_value "${FALLOUT4_APPDEFAULTS_REGISTRY_KEY}\\DllOverrides" "${dll}" 'native,builtin' 'REG_SZ' | |
done | |
# Delete all xact DLL Overrides we don't required (2D audio as well?) | |
for dll in "xapofx1_1" "xapofx1_2" "xapofx1_3" "xapofx1_4" "xapofx1_5"; do | |
delete_registry_value "${WINE_REGISTRY_KEY}\\DllOverrides" "${dll}" | |
delete_registry_value "${WINE_REGISTRY_KEY}\\DllOverrides" "*${dll}" | |
done | |
} | |
main $@ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment