#!/bin/bash if ! which 7z &> /dev/null; then echo "7z is not installed. Installing 7z..." if [[ -f /etc/debian_version ]]; then sudo apt update sudo apt install -y p7zip-full elif [[ -f /etc/redhat-release ]]; then sudo yum install -y p7zip elif [[ -f /etc/arch-release ]]; then sudo pacman -S --noconfirm p7zip else echo "Unsupported OS. Please install 7zip manually." exit 1 fi fi function printErr() { removeTempDir echo -e "\e[40m\e[31mError: $1\nExiting.\e[0m" [[ -z $2 ]] && exit 1 || exit "$2" } function checkStdin() { while true; do read -rp "$1" userInput if [[ $userInput =~ $2 ]]; then break fi done echo "$userInput" } function 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 } function createTempDir() { tmpDir=$(mktemp -d) cd "$tmpDir" || printErr "Failed to create temp directory." } function removeTempDir() { cd "$MAIN_PATH" || exit [[ -d $tmpDir ]] && rm -rf "$tmpDir" } function 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 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 } function 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 mkdir -p "$MAIN_PATH" || printErr "Unable to create directory '$MAIN_PATH'." cd "$MAIN_PATH" || exit mkdir -p "$RESHADE_PATH" mkdir -p "$MAIN_PATH/ReShade_shaders" mkdir -p "$MAIN_PATH/External_shaders" [[ -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 echo -e "$SEPARATOR\nReShade installer/updater for Linux games using wine or proton.\n$SEPARATOR\n" 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 } 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" 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" cd "$MAIN_PATH" || exit [[ -f LVERS ]] && LVERS=$(cat LVERS) || LVERS=0 if [[ $RESHADE_VERSION == latest ]]; then [[ $LVERS =~ Addon && $RESHADE_ADDON_SUPPORT -eq 0 ]] && UPDATE_RESHADE=1 [[ ! $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 =~ '