#!/usr/bin/bash
# -- winedxvkcfg --
# Sets wine DXVK dlls.
#
# Script by Phantom X <megaphantomx at hotmail dot com>
# Suggested usage: $ winedxvkcfg --help
#
# Copyright 2018-2025 Phantom X, Goiania, Brazil.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

set -e

ver=20270107

name="DXVK"
pkgname="wine-dxvk"
datadir="/usr/share/wine/dxvk"
dllsuffix=""
dlls="dxgi d3d8 d3d9 d3d11 d3d10core"
nodlls="d3d10 d3d10_1"

unset winebits
bits="64 32"
enabled=0
enabledlnk=0
disabled=0
disabledlnk=0
dllmissing=0
retval=0
archdir="x86_64-windows"
archdirwow64="i386-windows"
overrideskey="HKCU\\Software\\Wine\\DllOverrides"
overrideskeywow64="HKCU\\Software\\WoW6432Node\\Wine\\DllOverrides"
sysdir="system32"
sysdirwow64="syswow64"
if [ -d "/usr/lib64/wine-wow64/wine" ] ;then
  wine_path="/usr/lib64/wine-wow64/wine"
else
  wine_path="/usr/lib64/wine"
fi
wine32_path="${wine_path}"

txt() {
cat <<EOF
$(basename "$0")
Uso : $0 <option>
-c|--check        Check ${name} dlls settings.
-s|1|--set        Enable ${name} dlls.
-u|0|--unset      Disable ${name} dlls.
-V|--version      Show version.
-h|--help         Show this message.
EOF
}

if [ -d "/usr/lib64/wine" ] && [ -d "/usr/lib/wine" ] ;then
  wine32_path="/usr/lib/wine"
fi

checkprefix(){
  native_path="$(wine winepath -u "C:\windows\\${sysdirwow64}" 2>/dev/null)"
  if ! [ -d "${native_path}" ] ;then
    return 1
  fi
}

checkcfg(){
  if ! checkprefix ;then
    bits="o32"
  fi
  for winebits in ${bits} ;do
    if [ "${winebits}" == "64" ] ;then
      lib=64
      regkey="${overrideskey}"
      winesysdir="${sysdir}"
    elif [ "${winebits}" == "32" ] ;then
      lib=32
      regkey="${overrideskeywow64}"
      winesysdir="${sysdirwow64}"
    else
      lib=32
      regkey="${overrideskey}"
      winesysdir="${sysdir}"
    fi
    native_path="$(wine winepath -u "C:\windows\\${winesysdir}" 2>/dev/null)"
    if [ -z "${native_path}" ] ;then
      echo 'Error while getting native winepath!'
      exit 5
    fi
    lib_path="${datadir}/${lib}"
    for dll in ${dlls} ;do
      if wine reg query "${regkey}" /v "${dll}" 2>/dev/null | grep -q -F "native" ;then
        enabled=1
      else
        disabled=1
      fi
      if [ -f "${native_path}/${dll}.dll" ] && [ "$(readlink -f "${lib_path}/${dll}${dllsuffix}.dll")" == "$(readlink -f "${native_path}/${dll}.dll")" ] ;then
        enabledlnk=1
      else
        disabledlnk=1
      fi
    done
  done

  if [ "${enabled}" -eq 1 ] && [ "${disabled}" -eq 0 ] && [ "${enabledlnk}" -eq 1 ] && [ "${disabledlnk}" -eq 0 ] ;then
    echo "${name} is enabled!"
  elif [ "${enabled}" -eq 1 ] && [ "${disabled}" -eq 1 ] || [ "${enabledlnk}" -eq 1 ] && [ "${disabledlnk}" -eq 1 ] ;then
    echo "${name} settings are corrupted!"
    echo "Rerun with --set or --unset to fix!"
  else
    echo "${name} is not enabled!"
  fi
  exit 0
}

setcfg(){
  enabled=1
  if ! checkprefix ;then
    bits="o32"
  fi
  for winebits in ${bits} ;do
    if [ "${winebits}" == "64" ] ;then
      lib=64
      regkey="${overrideskey}"
      winearchdir="${archdir}"
      winesysdir="${sysdir}"
    elif [ "${winebits}" == "32" ] ;then
      lib=32
      regkey="${overrideskeywow64}"
      winearchdir="${archdirwow64}"
      wine_path="${wine32_path}"
      winesysdir="${sysdirwow64}"
    else
      lib=32
      regkey="${overrideskey}"
      winearchdir="${archdirwow64}"
      wine_path="${wine32_path}"
      winesysdir="${sysdir}"
    fi
    native_path="$(wine winepath -u "C:\windows\\${winesysdir}" 2>/dev/null)"
    if [ -z "${native_path}" ] ;then
      echo 'Error while getting native winepath!'
      exit 5
    fi
    lib_path="${datadir}/${lib}"
    arch_path="${wine_path}/${winearchdir}"
    for dll in ${dlls} ;do
      if ! [ -f "${lib_path}/${dll}${dllsuffix}.dll" ];then
        echo "Missing ${dll}${dllsuffix}.dll in ${datadir}/${lib}/."
        dllmissing=1
      fi
    done
    if [ "${dllmissing}" -eq 1 ] ;then
      continue
    fi
    if [ -n "${nodlls}" ] ;then
      for nodll in ${nodlls} ;do
        if wine reg query "${regkey}" /v "${nodll}" &>/dev/null ;then
          wine reg delete "${regkey}" /v "${nodll}" /f &>/dev/null
          retval=$?
        fi
        if [ -f "${arch_path}/${nodll}.dll" ] && ! cmp -s "${arch_path}/${nodll}.dll" "$(readlink -f "${native_path}/${nodll}.dll")" ;then
          rm -f "${native_path}/${nodll}.dll" 2>/dev/null
          cp -pf "${arch_path}/${nodll}.dll" "${native_path}/${nodll}.dll" 2>/dev/null
        fi
      done
    fi
    for dll in ${dlls} ;do
      if wine reg query "${regkey}" /v "${dll}" 2>/dev/null | grep -q -v -F "native" &>/dev/null ;then
        wine reg add "${regkey}" /v "${dll}" -t REG_SZ /d native /f &>/dev/null
        retval=$?
        if [ "${retval}" -eq 0 ] ;then
          enabled=1
        else
          disabled=1
        fi
      else
        enabled=1
      fi
      if [ "$(readlink -f "${lib_path}/${dll}${dllsuffix}.dll")" != "$(readlink -f "${native_path}/${dll}.dll")" ] ;then
        rm -f "${native_path}/${dll}.dll" && ln -sf "${lib_path}/${dll}${dllsuffix}.dll" "${native_path}/${dll}.dll"
        retval=$?
        if [ "${retval}" -eq 0 ] ;then
          enabledlnk=1
        else
          enabledlnk=0
        fi
      else
        enabledlnk=1
      fi
    done
  done
  if [ "${dllmissing}" -eq 1 ] ;then
    echo "Reinstall ${pkgname}."
    exit 1
  fi
  if [ "${enabled}" -eq 1 ] && [ "${disabled}" -eq 0 ] && [ "${enabledlnk}" -eq 1 ] ;then
    echo "${name} is enabled!"
    exit 0
  else
    echo "${name} configuration fail!"
    echo "Check wine prefix or permissions."
    exit 1
  fi
}

unsetcfg(){
  disabled=1
  disabledlnk=1
  if ! checkprefix ;then
    bits="o32"
  fi
  for winebits in ${bits} ;do
    if [ "${winebits}" == "64" ] ;then
      lib=64
      regkey="${overrideskey}"
      winearchdir="${archdir}"
      winesysdir="${sysdir}"
    elif [ "${winebits}" == "32" ] ;then
      lib=32
      regkey="${overrideskeywow64}"
      winearchdir="${archdirwow64}"
      wine_path="${wine32_path}"
      winesysdir="${sysdirwow64}"
    else
      lib=32
      regkey="${overrideskey}"
      winearchdir="${archdirwow64}"
      wine_path="${wine32_path}"
      winesysdir="${sysdir}"
    fi
    native_path="$(wine winepath -u "C:\windows\\${winesysdir}" 2>/dev/null)"
    if [ -z "${native_path}" ] ;then
      echo 'Error while getting native winepath!'
      exit 5
    fi
    lib_path="${datadir}/${lib}"
    arch_path="${wine_path}/${winearchdir}"
    for dll in ${dlls} ;do
      if wine reg query "${regkey}" /v "${dll}" 2>/dev/null | grep -q -F "native" &>/dev/null ;then
        wine reg delete "${regkey}" /v "${dll}" /f &>/dev/null
        retval=$?
        if [ "${retval}" -eq 0 ] ;then
          disabled=1
        else
          disabled=0
        fi
      fi
      if [ -f "${native_path}/${dll}.dll" ] && [ "$(readlink -f "${lib_path}/${dll}${dllsuffix}.dll")" == "$(readlink -f "${native_path}/${dll}.dll")" ] ;then
        rm -f "${native_path}/${dll}.dll"
      fi
      if ! cmp -s "${arch_path}/${dll}.dll" "$(readlink -f "${native_path}/${dll}.dll")" ;then
        cp -pf "${arch_path}/${dll}.dll" "${native_path}/${dll}.dll" 2>/dev/null
        retval=$?
        if [ "${retval}" -eq 0 ] ;then
          disabledlnk=1
        else
          disabledlnk=0
        fi
      else
        disabledlnk=1
      fi
    done
  done
  if [ "${disabled}" -eq 1 ] && [ "${disabledlnk}" -eq 1 ] ;then
    echo "${name} is disabled!"
    exit 0
  else
    echo "${name} configuration fail!"
    echo "Check wine prefix or permissions."
    exit 1
  fi
}

if [ -z "$1" ] ;then
  txt
  exit 0
fi

while [ -n "$1" ] ;do
  case "$1" in
    -h|--help)
      txt
      exit 0
      ;;
    -V|--version)
      echo "${ver}"
      exit 0
      ;;
    -c|--check)
      checkcfg
      ;;
    -s|1|--set|--enable|--on)
      setcfg
      ;;
    -u|0|--unset|--disable|--off)
      unsetcfg
      ;;
    -*)
      echo "$0: unrecognized option '$1'"
      echo "Try '$0 --help' for more information."
      exit 2
      ;;
  esac
  shift
done
