#!/bin/sh . ../../common-script.sh for cmd in find 7z curl git grep; do if ! command_exists "$cmd"; then printf "%b\n" "${RED}$cmd is not installed.${RC}" exit 1 fi done printErr() { removeTempDir echo -e "\e[40m\e[31mError: $1\nExiting.\e[0m" [[ -z $2 ]] && exit 1 || exit "$2" } # Check user input # $1 is valid values to display to user # $2 is regex checkStdin() { while true; do read -rp "$1" userInput if [[ $userInput =~ $2 ]]; then break fi done echo "$userInput" } # Try to get game directory from user. getGamePath() { echo 'Supply the folder path where the main executable (exe file) for the game is.' echo '(Control+c to exit)' while true; do read -rp 'Game path: ' gamePath eval gamePath="$gamePath" &> /dev/null gamePath=$(realpath "$gamePath") [[ -f $gamePath ]] && gamePath=$(dirname "$gamePath") if ! ls "$gamePath" > /dev/null 2>&1 || [[ -z $gamePath ]]; then echo "Incorrect or empty path supplied. You supplied \"$gamePath\"." continue fi if ! ls "$gamePath/"*.exe > /dev/null 2>&1; then echo "No .exe file found in \"$gamePath\"." echo "Do you still want to use this directory?" [[ $(checkStdin "(y/n) " "^(y|n)$") != "y" ]] && continue fi echo "Is this path correct? \"$gamePath\"" [[ $(checkStdin "(y/n) " "^(y|n)$") == "y" ]] && break done } # Remove / create temporary directory. createTempDir() { tmpDir=$(mktemp -d) cd "$tmpDir" || printErr "Failed to create temp directory." } removeTempDir() { cd "$MAIN_PATH" || exit [[ -d $tmpDir ]] && rm -rf "$tmpDir" } # Downloads d3dcompiler_47.dll files. downloadD3dcompiler_47() { ! [[ $1 =~ ^(32|64)$ ]] && printErr "(downloadD3dcompiler_47): Wrong system architecture." [[ -f $MAIN_PATH/d3dcompiler_47.dll.$1 ]] && return echo "Downloading d3dcompiler_47.dll for $1 bits." createTempDir # Based on https://github.com/Winetricks/winetricks/commit/bc5c57d0d6d2c30642efaa7fee66b60f6af3e133 curl -sLO "https://download-installer.cdn.mozilla.net/pub/firefox/releases/62.0.3/win$1/ach/Firefox%20Setup%2062.0.3.exe" \ || echo "Could not download Firefox setup file (which contains d3dcompiler_47.dll)" [[ $1 -eq 32 ]] && hash="d6edb4ff0a713f417ebd19baedfe07527c6e45e84a6c73ed8c66a33377cc0aca" || hash="721977f36c008af2b637aedd3f1b529f3cfed6feb10f68ebe17469acb1934986" ffhash=$(sha256sum Firefox*.exe | cut -d\ -f1) [[ "$ffhash" != "$hash" ]] && printErr "(downloadD3dcompiler_47) Firefox integrity check failed. (Expected: $hash ; Calculated: $ffhash)" 7z -y e Firefox*.exe 1> /dev/null || printErr "(downloadD3dcompiler_47) Failed to extract Firefox using 7z." cp d3dcompiler_47.dll "$MAIN_PATH/d3dcompiler_47.dll.$1" || printErr "(downloadD3dcompiler_47): Unable to find d3dcompiler_47.dll" removeTempDir } # Download / extract ReShade from specified link. # $1 => Version of ReShade # $2 -> Full URL of ReShade exe, ex.: https://reshade.me/downloads/ReShade_Setup_5.0.2.exe downloadReshade() { createTempDir curl -sLO "$2" || printErr "Could not download version $1 of ReShade." exeFile="$(find . -name "*.exe")" ! [[ -f $exeFile ]] && printErr "Download of ReShade exe file failed." [[ $(file "$exeFile" | grep -o executable) == "" ]] && printErr "The ReShade exe file is not an executable file, does the ReShade version exist?" 7z -y e "$exeFile" 1> /dev/null || printErr "Failed to extract ReShade using 7z." rm -f "$exeFile" resCurPath="$RESHADE_PATH/$1" [[ -e $resCurPath ]] && rm -rf "$resCurPath" mkdir -p "$resCurPath" mv ./* "$resCurPath" removeTempDir } SEPARATOR="------------------------------------------------------------------------------------------------" COMMON_OVERRIDES="d3d8 d3d9 d3d11 ddraw dinput8 dxgi opengl32" REQUIRED_EXECUTABLES="7z curl git grep" XDG_DATA_HOME=${XDG_DATA_HOME:-"$HOME/.local/share"} MAIN_PATH=${MAIN_PATH:-"$XDG_DATA_HOME/reshade"} RESHADE_PATH="$MAIN_PATH/reshade" WINE_MAIN_PATH="$(echo "$MAIN_PATH" | sed "s#/home/$USER/##" | sed 's#/#\\\\#g')" UPDATE_RESHADE=${UPDATE_RESHADE:-1} MERGE_SHADERS=${MERGE_SHADERS:-1} VULKAN_SUPPORT=${VULKAN_SUPPORT:-0} GLOBAL_INI=${GLOBAL_INI:-"ReShade.ini"} SHADER_REPOS=${SHADER_REPOS:-"https://github.com/CeeJayDK/SweetFX|sweetfx-shaders;https://github.com/martymcmodding/iMMERSE|martymc-shaders;https://github.com/BlueSkyDefender/AstrayFX|astrayfx-shaders;https://github.com/prod80/prod80-ReShade-Repository|prod80-shaders;https://github.com/crosire/reshade-shaders|reshade-shaders|slim"} RESHADE_VERSION=${RESHADE_VERSION:-"latest"} RESHADE_ADDON_SUPPORT=${RESHADE_ADDON_SUPPORT:-0} FORCE_RESHADE_UPDATE_CHECK=${FORCE_RESHADE_UPDATE_CHECK:-0} RESHADE_URL="https://reshade.me" RESHADE_URL_ALT="http://static.reshade.me" for REQUIRED_EXECUTABLE in $REQUIRED_EXECUTABLES; do if ! which "$REQUIRED_EXECUTABLE" &> /dev/null; then echo -ne "Program '$REQUIRED_EXECUTABLE' is missing, but it is required.\nExiting.\n" exit 1 fi done # Z0000 Create MAIN_PATH # Z0005 Check if update enabled. # Z0010 Download / update shaders. # Z0015 Download / update latest ReShade version. # Z0016 Download version of ReShade specified by user. # Z0020 Process GLOBAL_INI. # Z0025 Vulkan install / uninstall. # Z0030 DirectX / OpenGL uninstall. # Z0035 DirectX / OpenGL find correct ReShade DLL. # Z0040 Download d3dcompiler_47.dll. # Z0045 DirectX / OpenGL link files to game directory. # Z0000 mkdir -p "$MAIN_PATH" || printErr "Unable to create directory '$MAIN_PATH'." cd "$MAIN_PATH" || exit # Z0000 mkdir -p "$RESHADE_PATH" mkdir -p "$MAIN_PATH/ReShade_shaders" mkdir -p "$MAIN_PATH/External_shaders" # Z0005 # Skip updating shaders / reshade if recently done (4 hours). [[ -f LASTUPDATED ]] && LASTUPDATED=$(cat LASTUPDATED) || LASTUPDATED=0 [[ ! $LASTUPDATED =~ ^[0-9]+$ ]] && LASTUPDATED=0 [[ $LASTUPDATED -gt 0 && $(($(date +%s)-LASTUPDATED)) -lt 14400 ]] && UPDATE_RESHADE=0 [[ $UPDATE_RESHADE == 1 ]] && date +%s > LASTUPDATED # Z0005 echo -e "$SEPARATOR\nReShade installer/updater for Linux games using wine or proton.\n$SEPARATOR\n" # Z0010 # Link Shader / Texture files from an input directory to an output directory if the link doesn't already exist. # $1 is the input directory (full path). # $2 is the output directory name (Textures / Shaders), with optional subdirectory. function linkShaderFiles() { [[ ! -d $1 ]] && return cd "$1" || return for file in *; do [[ ! -f $file ]] && continue [[ -L "$MAIN_PATH/ReShade_shaders/Merged/$2/$file" ]] && continue INFILE="$(realpath "$1/$file")" OUTDIR="$(realpath "$MAIN_PATH/ReShade_shaders/Merged/$2/")" [[ ! -d $OUTDIR ]] && mkdir -p "$OUTDIR" echo "Linking $INFILE to $OUTDIR" ln -s "$INFILE" "$OUTDIR" done } # Check ReShade_shaders or External_shaders directories for directories to link to the Merged folder. # $1 ReShade_shaders | External_shaders # $2 Optional: Repo name function mergeShaderDirs() { [[ $1 != ReShade_shaders && $1 != External_shaders ]] && return for dirName in Shaders Textures; do [[ $1 == "ReShade_shaders" ]] && dirPath=$(find "$MAIN_PATH/$1/$2" ! -path . -type d -name "$dirName") || dirPath="$MAIN_PATH/$1/$dirName" linkShaderFiles "$dirPath" "$dirName" # Check if there are any extra directories inside the Shaders or Texture folder, and link them. while IFS= read -rd '' anyDir; do linkShaderFiles "$dirPath/$anyDir" "$dirName/$anyDir" done < <(find . ! -path . -type d -print0) done } if [[ -n $SHADER_REPOS ]]; then echo "Checking for ReShade Shader updates." [[ $REBUILD_MERGE == 1 ]] && rm -rf "$MAIN_PATH/ReShade_shaders/Merged/" [[ $MERGE_SHADERS == 1 ]] && mkdir -p "$MAIN_PATH/ReShade_shaders/Merged/Shaders" && mkdir -p "$MAIN_PATH/ReShade_shaders/Merged/Textures" for URI in $(echo "$SHADER_REPOS" | tr ';' '\n'); do localRepoName=$(echo "$URI" | cut -d'|' -f2) branchName=$(echo "$URI" | cut -d'|' -f3) URI=$(echo "$URI" | cut -d'|' -f1) if [[ -d "$MAIN_PATH/ReShade_shaders/$localRepoName" ]]; then if [[ $UPDATE_RESHADE -eq 1 ]]; then cd "$MAIN_PATH/ReShade_shaders/$localRepoName" || continue echo "Updating ReShade shader repository $URI." git pull || echo "Could not update shader repo: $URI." fi else cd "$MAIN_PATH/ReShade_shaders" || exit [[ -n $branchName ]] && branchName="--branch $branchName" || branchName= eval git clone "$branchName" "$URI" "$localRepoName" || echo "Could not clone Shader repo: $URI." fi [[ $MERGE_SHADERS == 1 ]] && mergeShaderDirs "ReShade_shaders" "$localRepoName" done if [[ $MERGE_SHADERS == 1 ]] && [[ -d "$MAIN_PATH/External_shaders" ]]; then echo "Checking for External Shader updates." mergeShaderDirs "External_shaders" # Link loose files. cd "$MAIN_PATH/External_shaders" || exit 1 for file in *; do [[ ! -f $file || -L "$MAIN_PATH/ReShade_shaders/Merged/Shaders/$file" ]] && continue INFILE="$(realpath "$MAIN_PATH/External_shaders/$file")" OUTDIR="$MAIN_PATH/ReShade_shaders/Merged/Shaders/" echo "Linking $INFILE to $OUTDIR" ln -s "$INFILE" "$OUTDIR" done fi fi echo "$SEPARATOR" # Z0010 # Z0015 cd "$MAIN_PATH" || exit [[ -f LVERS ]] && LVERS=$(cat LVERS) || LVERS=0 if [[ $RESHADE_VERSION == latest ]]; then # Check if user wants reshade without addon support and we're currently using reshade with addon support. [[ $LVERS =~ Addon && $RESHADE_ADDON_SUPPORT -eq 0 ]] && UPDATE_RESHADE=1 # Check if user wants reshade with addon support and we're not currently using reshade with addon support. [[ ! $LVERS =~ Addon ]] && [[ $RESHADE_ADDON_SUPPORT -eq 1 ]] && UPDATE_RESHADE=1 fi if [[ $FORCE_RESHADE_UPDATE_CHECK -eq 1 ]] || [[ $UPDATE_RESHADE -eq 1 ]] || [[ ! -e reshade/latest/ReShade64.dll ]] || [[ ! -e reshade/latest/ReShade32.dll ]]; then echo -e "Checking for Reshade updates.\n$SEPARATOR" RHTML=$(curl --max-time 10 -sL "$RESHADE_URL") ALT_URL=0 if [[ $? != 0 || $RHTML =~ "