#!/usr/bin/env bash ##### CHECK ROOT ##### if [[ $(id -u) -eq 0 ]] ; then echo "Перезапустите скрипт $0 от обычного пользователя!" exit 1 fi ##### MESSAGES FUNCTIONS ##### print_error () { printf "\E[31m%s Ошибка: $@ %s\e[0m\n" ;} print_warning () { printf "\E[33m%s Предупреждение: $@ %s\e[0m\n" ;} print_info () { printf "\E[36m%s Информация: \"$@\" %s\e[0m\n" ;} print_ok () { printf "\E[35m%s Успех: $@ %s\e[0m\n" ;} print_var () { for vp in $@ ; do print_info "${vp}=${!vp}" ; done ;} fatal () { print_error "$@" ; exit 1 ;} ##### CHECK VARIABLES ##### check_variables () { [[ -z ${!1} ]] && export $1="$2" ;} ##### DEFAULT VARIABLES ##### SCRIPT_NAME="$(basename "$0")" if [[ "$(realpath "$0")" == "/usr/bin/$SCRIPT_NAME" ]] ; then USER_WORK_PATH="$HOME/.local/share/$SCRIPT_NAME" RUN_SCRIPT="/usr/bin/$SCRIPT_NAME" DATA_PATH="/usr/share/$SCRIPT_NAME" else USER_WORK_PATH="$HOME/test-$SCRIPT_NAME" RUN_SCRIPT="$(realpath "$0")" DATA_PATH="$(dirname "$RUN_SCRIPT")" fi WH_VULKAN_LIBDIR="$USER_WORK_PATH/vulkan" WH_PREFIXES_DIR="$USER_WORK_PATH/prefixes" WH_DIST_DIR="$USER_WORK_PATH/dist" WH_TMP_DIR="$USER_WORK_PATH/tmp" WH_IMAGE_PATH="$DATA_PATH/image" WH_DB_DIR="$DATA_PATH/database" WH_AUTOINSTALL_DIR="$DATA_PATH/autoinstall" # export WINEDLLOVERRIDES=mshtml,mscoree=" check_variables WINEESYNC "0" check_variables WINEFSYNC "0" check_variables WINEARCH "win64" # or "win32" check_variables WH_WINE_USE "wine_x_tkg_10-0_amd64" # or system check_variables STAGING_SHARED_MEMORY "1" check_variables WINE_LARGE_ADDRESS_AWARE "1" check_variables WINE_FULLSCREEN_FSR "1" check_variables WINE_DO_NOT_CREATE_DXGI_DEVICE_MANAGER "0" check_variables WINE_HEAP_DELAY_FREE "0" check_variables WINE_ALLOW_XIM "0" check_variables DEBUG 0 check_variables WH_WINDOWS_VER "10" # check_variables WH_USE_GSTREAMER "1" # check_variables WH_USE_D3D_EXTRAS "1" check_variables WH_USE_SHADER_CACHE "1" check_variables WH_USE_WINE_DXGI "0" check_variables WH_DLL_INSTALL "" check_variables WINE_WIN_START "start /wait /high /unix" check_variables WINE_CPU_TOPOLOGY "4" check_variables USE_OPENGL "1" check_variables DXVK_STABLE_VER "1.10.3-28" check_variables DXVK_GIT_VER "2.2-164" # check_variables DXVK_CONFIG_FILE "path/to/dxvk.conf" check_variables VKD3D_STABLE_VER "1.1-2602" check_variables VKD3D_GIT_VER "1.1-3556" # check_variables VKD3D_LIMIT_TESS_FACTORS 64 # check_variables VKD3D_FEATURE_LEVEL "12_0" if [[ "$WINEARCH" == "win32" ]] ;then check_variables BASE_PFX "defpfx_x86_v01" check_variables WINEPREFIX "default_x86" else check_variables BASE_PFX "defpfx_x64_v01" check_variables WINEPREFIX "default_x64" fi export CLOUD_URL="https://cloud.linux-gaming.ru/portproton" export WH_AUTOINSTALL="0" ##### CHECK NOEXEC FOR /HOME ##### if grep "/home" /etc/fstab | grep -q "noexec" ; then fatal "/home примонтирован в /etc/fstab с аргументом noexec.\nЗапуск портативной версии wine не возможен из домашнего каталога." fi ##### ROOT ##### su_run () { print_info "Для продолжения установки зависимостей введите root пароль..." su - -c "$@" } ##### CHECK DEPENDENCIES ##### # yad zenity cups-pdf if rpm -q {i586-,}{wine,glibc-core,libstdc++6,glibc-pthread,glibc-nss,libOSMesa,\ libnss-mdns,libunixODBC2,ocl-icd,libfreetype,libfontconfig1,libgnutls30,libGL,\ libEGL,xorg-dri-swrast,xorg-dri-intel,xorg-dri-radeon,libvulkan1,libcups} \ winetricks ca-certificates cups-pdf 1>/dev/null then : # Зависимости установлены. Пропускаем... else if su_run "$DATA_PATH/dependencies.sh" then print_info "Зависимости успешно установлены. Продолжаем работу $SCRIPT_NAME" else fatal "Не удалось установить зависимости. Работа $SCRIPT_NAME прервана." fi fi ##### HELPER FUNCTIONS ##### check_command () { if command -v "$1" &>/dev/null ; then return 0 else print_warning "command: $1 - not found!" return 1 fi } add_to_var () { if ! echo ${!1} | grep "$2" &>/dev/null then export $1="${!1} $2" fi } rm_from_var () { if echo ${!1} | grep "$2" &>/dev/null then export $1="$(echo "${!1//$2/}" | tr -s " ")" fi } try_remove_file () { if [[ -f "$1" ]] || [[ ! -e "$1" ]] ; then rm -f "$1" [[ "$?" == 0 ]] && return 0 || return 1 fi } try_remove_dir () { if [[ -d "$1" ]] ; then rm -fr "$1" [[ "$?" == 0 ]] && return 0 || return 1 fi } try_copy_file () { if [[ ! -f "$1" ]] ; then print_info "file $1 not found for copy" && return 1 elif [[ -z "$2" ]] ; then print_error "no way to copy file $1" && return 1 elif [[ -L "$2" ]] ; then print_warning "$2 is a file with a symbolic link" try_remove_file "$2" cp -f "$1" "$2" && return 0 || return 1 else [[ -e "$2/$(basename "$1")" ]] && rm -f "$2/$(basename "$1")" cp -f "$1" "$2" && return 0 || return 1 fi } try_copy_dir () { if [[ ! -d "$1" ]] ; then print_info "directory $1 not found for copy" elif [[ -z "$2" ]] ; then print_error "no way to copy directory $1" else cp -fr "$1" "$2" [[ "$?" != 0 ]] && print_error "failed to copy directory $1 to $2" || return 0 fi return 1 } try_force_link_file () { if [[ ! -f "$1" ]] ; then print_warning "file not found for link: $1" if [[ -f "$2" ]] ; then try_remove_file "$2" print_warning "removed old link: $2" fi return 1 elif [[ -z "$2" ]] ; then print_error "no way to link file $1" && return 1 else try_remove_file "$2" ln -s -f -r "$1" "$2" return 0 fi return 1 } check_symlink () { local CHK_SYMLINK_FILE="$(file "$1")" if [[ -n "$(echo "$CHK_SYMLINK_FILE" | grep -v "broken" | grep "symbolic link to" | awk '{print $1}')" ]] ; then return 0 elif [[ -n "$(echo "$CHK_SYMLINK_FILE" | grep "broken symbolic link to" | awk '{print $1}')" ]] ; then print_error "remove broken symlink: $CHK_SYMLINK_FILE" rm -fr "$CHK_SYMLINK_FILE" return 1 else return 1 fi } try_force_link_dir () { if [[ ! -d "$1" ]] ; then print_info "directory $1 not found for link" elif [[ -z "$2" ]] ; then print_error "no way to link directory $1" else ln -s -f -r "$1" "$2" [[ "$?" != 0 ]] && print_error "failed to link directory $1 to $2" || return 0 fi return 1 } create_new_dir () { if [[ ! -d "$1" ]] ; then mkdir -p "$1" fi return 0 } unpack () { print_info "Запуск распаковки архива $1" case $1 in *.tar.xz) local command="tar -Jxhf";; *.tar.gz) local command="tar -xhzf" ;; *.tar.zst) local command="tar -I zstd -xhf" ;; *.tar) local command="tar -xhf" ;; esac if $command "$1" -C "$2" ; then print_ok "Архив $1 распакован." return 0 else print_error "Распаковать архив $1 не удалось!" return 1 fi } try_download () { local DOWNLOAD_FILE_URL="$1" local OUTPUT_FILE="$2" local OUTPUT_FILE_NAME="$(basename "$OUTPUT_FILE")" print_info "Скачивание файла $OUTPUT_FILE_NAME..." if curl -f --progress-bar -A "Mozilla/5.0 (compatible; Konqueror/2.1.1; X11)" \ -L "$DOWNLOAD_FILE_URL" -o "$OUTPUT_FILE" then print_ok "Скачивание файла $OUTPUT_FILE_NAME прошло успешно." if [[ "$3" == check256sum ]] ; then SHA256SUM_EXT=$(sha256sum "$OUTPUT_FILE" | awk '{print $1}') SHA256SUM_INT="$(grep "$OUTPUT_FILE_NAME" "$DATA_PATH/sha256sum.list" | awk '{print $1}')" if [[ "$SHA256SUM_EXT" == "$SHA256SUM_INT" ]] ; then print_ok "Хэш-сумма файла $OUTPUT_FILE_NAME успешно проверена." return 0 else fatal "Хэш-сумма файла $OUTPUT_FILE_NAME не совподает!" return 1 fi fi return 0 else fatal "Скачивание файла: $OUTPUT_FILE_NAME завершилось с ошибкой!" return 1 fi } try_copy_other_dll_to_pfx_64 () { if [[ "$WINEARCH" == "win64" ]] ; then cmp -s "$1" "${WINEPREFIX}/drive_c/windows/system32/$(basename $1)" && return 0 try_copy_file "$1" "${WINEPREFIX}/drive_c/windows/system32/" && return 0 || return 1 fi } try_copy_other_dll_to_pfx_32() { if [[ "$WINEARCH" == "win64" ]] ; then cmp -s "$1" "${WINEPREFIX}/drive_c/windows/syswow64/$(basename $1)" && return 0 try_copy_file "$1" "${WINEPREFIX}/drive_c/windows/syswow64/" && return 0 || return 1 else cmp -s "$1" "${WINEPREFIX}/drive_c/windows/system32/$(basename $1)" && return 0 try_copy_file "$1" "${WINEPREFIX}/drive_c/windows/system32/" && return 0 || return 1 fi } try_copy_wine_dll_to_pfx_64 () { if [[ "$WINEARCH" == "win64" ]] ; then if [[ -d "${WINEDIR}/lib64/wine/x86_64-windows" ]] then WINE_BUILD_DLL_64="${WINEDIR}/lib64/wine/x86_64-windows" else WINE_BUILD_DLL_64="${WINEDIR}/lib64/wine" fi cmp -s "$WINE_BUILD_DLL_64/$1" "${WINEPREFIX}/drive_c/windows/system32/$(basename $1)" && return 0 try_copy_file "$WINE_BUILD_DLL_64/$1" "${WINEPREFIX}/drive_c/windows/system32/" && return 0 || return 1 fi } try_copy_wine_dll_to_pfx_32() { if [[ -d "${WINEDIR}/lib/wine/i386-windows" ]] then WINE_BUILD_DLL_32="${WINEDIR}/lib/wine/i386-windows" else WINE_BUILD_DLL_32="${WINEDIR}/lib/wine" fi if [[ "$WINEARCH" == "win64" ]] ; then cmp -s "$WINE_BUILD_DLL_32/$1" "${WINEPREFIX}/drive_c/windows/syswow64/$1" && return 0 try_copy_file "$WINE_BUILD_DLL_32/$1" "${WINEPREFIX}/drive_c/windows/syswow64/" && return 0 || return 1 else cmp -s "$WINE_BUILD_DLL_32/$1" "${WINEPREFIX}/drive_c/windows/system32/$1" && return 0 try_copy_file "$WINE_BUILD_DLL_32/$1" "${WINEPREFIX}/drive_c/windows/system32/" && return 0 || return 1 fi } ##### OVERRIDE VARIABLES FUNCTIONS ##### var_winedlloverride_update () { if [[ -n "${WINEDLLOVERRIDES}" ]] then export WINEDLLOVERRIDES="${1};${WINEDLLOVERRIDES}" else export WINEDLLOVERRIDES="${1}" fi } var_vkd3d_config_update () { if [[ -n "${DXVK_CONFIG}" ]] then export DXVK_CONFIG="${1}; ${DXVK_CONFIG}" else export DXVK_CONFIG="${1}" fi } var_vkd3d_config_update () { if [[ -n "${VKD3D_CONFIG}" ]] then export VKD3D_CONFIG="${1};${VKD3D_CONFIG}" else export VKD3D_CONFIG="${1}" fi } var_radv_perftest_config_update () { if [[ -n "${RADV_PERFTEST}" ]] then export RADV_PERFTEST="${1};${RADV_PERFTEST}" else export RADV_PERFTEST="${1}" fi } var_vk_istance_layers_config_update () { if [[ -n "${VK_INSTANCE_LAYERS}" ]] then export VK_INSTANCE_LAYERS="${1}:${VK_INSTANCE_LAYERS}" else export VK_INSTANCE_LAYERS="${1}" fi } var_ld_library_path_update () { if echo "$LD_LIBRARY_PATH" | grep "$1" then return 0 elif [[ -n "$LD_LIBRARY_PATH" ]] then export LD_LIBRARY_PATH="$1:$LD_LIBRARY_PATH" else export LD_LIBRARY_PATH="$1" fi return 0 } ##### CREATE DESKTOP FILE ##### create_desktop () { local name_desktop="$1" local exe_file="$2" local icon_file="$WH_IMAGE_PATH/$3.png" if [[ -z "$name_desktop" ]] || [[ -z "$exe_file" ]] ; then fatal "Used: $SCRIPT_NAME --desktop \"desktop_name\" \"path_to_exe\" \"name_png_from_image\"" fi [[ ! -f "$exe_file" ]] && fatal "Для создания ярлыка не найден исполняемый файл: $exe_file" [[ ! -f "$icon_file" ]] && icon_file=wine { echo "[Desktop Entry]" echo "Name=$name_desktop" echo "Exec=env \"$RUN_SCRIPT\" \"$exe_file\" %F" echo "Type=Application" echo "Categories=Other;" echo "StartupNotify=true" echo "Path=$DATA_PATH" echo "Icon=$icon_file" } > "$USER_WORK_PATH/$name_desktop.desktop" chmod +x "$USER_WORK_PATH/$name_desktop.desktop" create_new_dir "$HOME/.local/share/applications/" # cp -f "$USER_WORK_PATH/$name_desktop.desktop" "$HOME/.local/share/applications/" cp -f "$USER_WORK_PATH/$name_desktop.desktop" "$(xdg-user-dir DESKTOP)" print_info "На рабочем столе создан $name_desktop.desktop" if [[ "$USE_AI_SCRIPTS" == "1" ]] \ && [[ -f "$exe_file" ]] then { echo '#!/usr/bin/env bash' echo "# cmd_name: $AI_SCRIPT" } > "$exe_file".whdb grep -e "info_" -e "#####" -e "export" -e "var_" "$WH_AUTOINSTALL_DIR/$AI_SCRIPT" \ | grep -vE "LAUNCH_PARAMETERS|AUTOINSTALL|WIN_FILE_EXEC|echo" \ | awk '{$1=$1;print}' >> "$exe_file".whdb print_info "Создан файл настроек для $exe_file" fi } ##### REMOVE DESKTOP FILE ##### remove_desktop () { if [[ -n "$1" ]] ; then try_remove_file "$USER_WORK_PATH/$1.desktop" try_remove_file "$HOME/.local/share/applications/$1.desktop" try_remove_file "$(xdg-user-dir DESKTOP)/$1.desktop" fi } ##### INSTALLED PROGRAMS ##### check_installed_programs () { for desktop_file in "$USER_WORK_PATH"/*.desktop ; do if [[ ! -f "$desktop_file" ]] ; then print_info "Установленные программы не найдены." return 1 fi EXE_PATH="$(grep "Exec" "$desktop_file" | awk -F'"' '{print $4}')" case "$1" in check_only) if [[ -z $2 ]] ; then print_error "Нет аргумента для проверки файла запуска!" print_info "Список установленных программ:" check_installed_programs exit 1 elif [[ "$EXE_PATH" =~ ${2}$ ]] ; then export EXE_PATH return 0 else fatal "Не найден файл запуска для $2" fi ;; *) if [[ -f "$EXE_PATH.whdb" ]] ; then WH_INFO_RU="$(grep "info_ru:" "$EXE_PATH.whdb" | awk -F"info_ru: " '{print $2}')" printf "\E[36m%s $SCRIPT_NAME run $(basename "$EXE_PATH") - $(basename "$desktop_file") %s\e[0m\n" echo -e "$WH_INFO_RU\n" fi ;; esac done } run_installed_programs () { if check_installed_programs check_only "$1" ; then /usr/bin/env bash -c "\"$RUN_SCRIPT\" \"$EXE_PATH\"" & exit 0 fi } ##### USED WINED3D LIBRARY ##### init_opengl () { if [[ "$USE_OPENGL" == 1 ]] ; then WINED3D_FILES="d3d8 d3d9 d3d10_1 d3d10 d3d10core d3d11 dxgi d3d12" # d3d12core for wined3dfiles in $WINED3D_FILES ; do try_copy_wine_dll_to_pfx_64 "$wined3dfiles.dll" try_copy_wine_dll_to_pfx_32 "$wined3dfiles.dll" done # check_variables WINE_D3D_CONFIG "renderer=" return 0 else return 1 fi } ##### CHECK VULKAN LIBRARY ##### init_dxvk () { check_variables USE_DXVK_VER "$1" get_dxvk () { DXVK_URL="$1" DXVK_PACKAGE="${WH_VULKAN_LIBDIR}/dxvk-${DXVK_VAR_VER}.tar.$(echo ${DXVK_URL#*.tar.})" if try_download "$DXVK_URL" "$DXVK_PACKAGE" check256sum \ && unpack "$DXVK_PACKAGE" "$WH_VULKAN_LIBDIR" then try_remove_file "$DXVK_PACKAGE" return 0 fi return 1 } for DXVK_VAR_VER in "$USE_DXVK_VER" $@ ; do if [[ ! -d "${WH_VULKAN_LIBDIR}/dxvk-$DXVK_VAR_VER" ]] ; then get_dxvk "$CLOUD_URL/dxvk-${DXVK_VAR_VER}.tar.gz" fi done if [[ "${WH_USE_WINE_DXGI}" == 1 ]] ; then DXVK_FILES="d3d9 d3d10_1 d3d10 d3d11" # dxvk_config openvr_api_dxvk" try_copy_wine_dll_to_pfx_64 "dxgi.dll" try_copy_wine_dll_to_pfx_32 "dxgi.dll" else DXVK_FILES="d3d9 d3d10_1 d3d10 d3d11 dxgi" # dxvk_config openvr_api_dxvk" fi for dxvkfiles in $DXVK_FILES ; do try_copy_other_dll_to_pfx_64 "${WH_VULKAN_LIBDIR}/dxvk-$USE_DXVK_VER/x64/$dxvkfiles.dll" if try_copy_other_dll_to_pfx_32 "${WH_VULKAN_LIBDIR}/dxvk-$USE_DXVK_VER/x32/$dxvkfiles.dll" then var_winedlloverride_update "$dxvkfiles=n" fi done } init_vkd3d () { check_variables USE_VKD3D_VER "$1" get_vkd3d () { VKD3D_URL="$1" VKD3D_PACKAGE="${WH_VULKAN_LIBDIR}/vkd3d-proton-${VKD3D_VAR_VER}.tar.$(echo ${VKD3D_URL#*.tar.})" if try_download "$VKD3D_URL" "$VKD3D_PACKAGE" check256sum \ && unpack "$VKD3D_PACKAGE" "$WH_VULKAN_LIBDIR" then try_remove_file "$VKD3D_PACKAGE" return 0 fi return 1 } for VKD3D_VAR_VER in "$USE_VKD3D_VER" $@ ; do if [[ ! -d "${WH_VULKAN_LIBDIR}/vkd3d-proton-$VKD3D_VAR_VER" ]] ; then get_vkd3d "$CLOUD_URL/vkd3d-proton-${VKD3D_VAR_VER}.tar.xz" fi done VKD3D_FILES="d3d12 d3d12core libvkd3d-shader-1 libvkd3d-1" # libvkd3d-proton-utils-3 for vkd3dfiles in $VKD3D_FILES ; do try_copy_other_dll_to_pfx_64 "${WH_VULKAN_LIBDIR}/vkd3d-proton-$USE_VKD3D_VER/x64/$vkd3dfiles.dll" if try_copy_other_dll_to_pfx_32 "${WH_VULKAN_LIBDIR}/vkd3d-proton-$USE_VKD3D_VER/x86/$vkd3dfiles.dll" then var_winedlloverride_update "$vkd3dfiles=n" fi done } ##### DOWNLOAD WINE ##### download_wine () { if [[ ! -d "$WH_DIST_DIR/$WH_WINE_USE" ]] ; then WINE_URL="$CLOUD_URL/$WH_WINE_USE.tar.xz" local WINE_PACKAGE="$WH_TMP_DIR/${WH_WINE_USE}.tar.xz" if try_download "$WINE_URL" "$WINE_PACKAGE" check256sum ; then if unpack "$WINE_PACKAGE" "$WH_DIST_DIR/" ; then echo "$WH_WINE_USE" > "$WH_DIST_DIR/$WH_WINE_USE/version" try_remove_file "$WINE_PACKAGE" fi fi fi } ##### INITIAL WINE SETTINGS ##### init_wine_ver () { if [[ "$WH_WINE_USE" != system* ]] ; then export WINEDIR="$WH_DIST_DIR/$WH_WINE_USE" if [[ ! -d "$WINEDIR" ]] ; then download_wine fi export WINE="${WINEDIR}/bin/wine" export WINELOADER="${WINEDIR}/bin/wine" export WINESERVER="${WINEDIR}/bin/wineserver" if [[ -n "${PATH}" ]] then export PATH="${WINEDIR}/bin:${PATH}" else export PATH="${WINEDIR}/bin" fi if [[ -n "${LD_LIBRARY_PATH}" ]] then export LD_LIBRARY_PATH="${WINEDIR}/lib:${LD_LIBRARY_PATH}" else export LD_LIBRARY_PATH="${WINEDIR}/lib" fi export WINEDLLPATH="${WINEDIR}/lib/wine" if [[ -d "${WINEDIR}/lib/gstreamer-1.0" ]] ; then export GST_PLUGIN_SYSTEM_PATH_1_0="${WINEDIR}/lib/gstreamer-1.0" fi if [[ "${WINEARCH}" == "win64" ]] ; then export LD_LIBRARY_PATH+=":${WINEDIR}/lib64" export WINEDLLPATH+=":${WINEDIR}/lib64/wine" if [[ -d "${WINEDIR}/lib64/gstreamer-1.0" ]] ; then export GST_PLUGIN_SYSTEM_PATH_1_0+=":${WINEDIR}/lib64/gstreamer-1.0" fi fi [[ ! -f "${WINEDIR}/version" ]] && echo "${WH_WINE_USE}" > "${WINEDIR}/version" if [[ ! -d "${WINEDIR}/lib64/" ]] && [[ -d "${WINEDIR}/lib/wine/x86_64-unix" ]] ; then create_new_dir "${WINEDIR}/lib64/wine" mv -f "${WINEDIR}/lib/wine/x86_64-unix" "${WINEDIR}/lib64/wine/" mv -f "${WINEDIR}/lib/wine/x86_64-windows" "${WINEDIR}/lib64/wine/" fi else # use system WINE if ! command -v "wine" &>/dev/null ; then fatal "system WINE - not found." fi export WINEDIR="/usr" export WINELOADER="wine" export WINESERVER="wineserver" fi if [[ $DEBUG != 1 ]] ; then check_variables WINEDEBUG "-all" check_variables DXVK_LOG_LEVEL "none" check_variables VKD3D_SHADER_DEBUG "none" check_variables VKD3D_DEBUG "none" check_variables DXVK_LOG_PATH "none" check_variables VKBASALT_LOG_LEVEL "none" check_variables DXVK_NVAPI_LOG_LEVEL "none" export WH_WDBG='2>/dev/null' else # check_variables WINEDEBUG "fixme-all,err+loaddll,err+dll,err+file,err+reg,warn+file" check_variables WINEDEBUG "+loaddll,+seh" check_variables DXVK_LOG_LEVEL "error" check_variables VKD3D_DEBUG "error" check_variables WINE_MONO_TRACE "E:System.NotImplementedException" check_variables VK_LOADER_DEBUG "error" check_variables VKBASALT_LOG_LEVEL "error" check_variables DXVK_NVAPI_LOG_LEVEL "error" export WH_WDBG="" fi print_info "Используется версия wine: $WH_WINE_USE" } ##### INITIAL WINEPREFIX SETTINGS ##### wait_wineserver () { # while [[ -n "$(ls -l /proc/*/exe 2>/dev/null | grep -ie portproton | grep -E 'wine(64)?-preloader|wineserver' | awk -F/ '{print $3}')" ]] ; do # sleep 1 # done "$WINESERVER" -w } get_base_pfx () { local FILE_NAME_PFX="$1" local PFX_URL="$CLOUD_URL/${FILE_NAME_PFX}.tar.xz" local PFX_TMP="$WH_TMP_DIR/pfx" create_new_dir "$PFX_TMP" if [[ ! -f "$PFX_TMP/$FILE_NAME_PFX.tar.xz" ]] ; then print_info "Загрузка базового префикса: ${FILE_NAME_PFX}" if try_download "$PFX_URL" "$PFX_TMP/$FILE_NAME_PFX.tar.xz" check256sum then unpack "$PFX_TMP/$FILE_NAME_PFX.tar.xz" "$WINEPREFIX/" else try_remove_file "$PFX_TMP/$FILE_NAME_PFX.tar.xz" fi else if ! unpack "$PFX_TMP/$FILE_NAME_PFX.tar.xz" "$WINEPREFIX/" ; then try_remove_file "${PFX_TMP}/${FILE_NAME_PFX}.tar.xz" get_base_pfx "$FILE_NAME_PFX" fi fi } init_wineprefix () { if [[ -z "$WINEPREFIX" ]] ; then export WINEPREFIX="$WH_PREFIXES_DIR/default" else if echo "$WINEPREFIX" | grep -v '/' ; then export WINEPREFIX="$WH_PREFIXES_DIR/$WINEPREFIX" fi fi export DRIVE_C="$WINEPREFIX/drive_c" # export WINEDLLPATH+=":$DRIVE_C/widows/system32:$DRIVE_C/windows/syswow64" if [[ ! -f "$WINEPREFIX/.firstboot" ]] ; then create_new_dir "$WINEPREFIX" if [[ "$CLEAR_PREFIX" == "1" ]] then print_warning "Используется переменная \"CLEAR_PREFIX=1\" что принудительно создает чистый префикс с установкой компонентов с помощью winetricks." elif [[ "$BASE_PFX" != "none" ]] then get_base_pfx "$BASE_PFX" fi print_info "Обновление префикса $WINEPREFIX." if [[ -d "$WINEPREFIX/drive_c/windows" ]] then env WINEDLLOVERRIDES="winegstreamer=" "$WINELOADER" wineboot -u else env WINEDLLOVERRIDES="winegstreamer=" "$WINELOADER" wineboot -i fi touch "$WINEPREFIX/.firstboot" wait_wineserver fi if [[ -f "$WINEPREFIX/system.reg" ]] \ && [[ -z $(grep "Windows $WH_WINDOWS_VER" "$WINEPREFIX/system.reg") ]] then if [[ $(echo "$WH_WINDOWS_VER" | sed 's/.*/\L&/') == "xp" ]] \ && [[ "$WINEARCH" != "win32" ]] then export WH_WINDOWS_VER="xp64" fi env WINEDLLOVERRIDES="winegstreamer=" "$WINELOADER" winecfg -v $(echo "win${WH_WINDOWS_VER}" | sed 's/.*/\L&/') wait_wineserver print_info "Windows версия изменена на win${WH_WINDOWS_VER}" fi if [[ -d "$DRIVE_C/users/xuser" ]] && [[ ! -d "$DRIVE_C/users/$USER" ]] then try_force_link_dir "$DRIVE_C/users/xuser" "$DRIVE_C/users/$USER" elif [[ ! -d "$DRIVE_C/users/xuser" ]] && [[ -d "$DRIVE_C/users/$USER" ]] then try_force_link_dir "$DRIVE_C/users/$USER" "$DRIVE_C/users/xuser" fi try_remove_file "$DRIVE_C/windows/system32/winemenubuilder.exe" } update_winetricks () { W_TRX_URL="https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks" W_TRX_EXT_VER="$(curl -s --list-only "$W_TRX_URL" | grep -i 'WINETRICKS_VERSION=' | sed 's/WINETRICKS_VERSION=//')" print_info "Актуальная версия winetricks: $W_TRX_EXT_VER" if [[ -f "$WH_TMP_DIR/winetricks" ]] ; then W_TRX_INT_VER="$(cat "$WH_TMP_DIR/winetricks" | grep -i 'WINETRICKS_VERSION=' | sed 's/WINETRICKS_VERSION=//')" print_info "Установленная портативная версия winetricks: $W_TRX_INT_VER" fi if [[ -n "$W_TRX_EXT_VER" ]] && [[ "$W_TRX_INT_VER" != "$W_TRX_EXT_VER" ]] ; then if try_download "$W_TRX_URL" "$WH_TMP_DIR/winetricks_new" ; then mv -f "$WH_TMP_DIR/winetricks_new" "$WH_TMP_DIR/winetricks" W_TRX_INT_VER="$(cat "$WH_TMP_DIR/winetricks" | grep -i 'WINETRICKS_VERSION=' | sed 's/_VERSION=//')" print_info "Портативная версия winetricks обновлена до (${W_TRX_INT_VER})" chmod u+x "$WH_TMP_DIR/winetricks" fi fi export WINETRICKS="$WH_TMP_DIR/winetricks" } use_winetricks () { if [[ -n "$INSTALL_DLL" ]] ; then WH_DLL_INSTALL="$(echo "$INSTALL_DLL $WH_DLL_INSTALL" | awk '{ for(i=1;i<=NF;i++){a[$i]++} }END{ for(i in a){printf("%s ",i)} }' )" fi if [[ -n "$WH_DLL_INSTALL" ]] ; then WH_DLL_NEED_INSTALL="" USE_WT_FROM_DB=0 [[ ! -f "$WINEPREFIX/winetricks.log" ]] && touch "$WINEPREFIX/winetricks.log" for need_install_dll_to_pfx in $WH_DLL_INSTALL "isolate_home" ; do if [[ "$need_install_dll_to_pfx" == vcrun201[5-9] ]] ; then sed -i "/${need_install_dll_to_pfx}/d" "$WINEPREFIX/winetricks.log" need_install_dll_to_pfx="vcrun2022" fi if ! grep "$need_install_dll_to_pfx" "$WINEPREFIX/winetricks.log" &>/dev/null ; then if [[ -z "$WH_DLL_NEED_INSTALL" ]] then WH_DLL_NEED_INSTALL="$need_install_dll_to_pfx" else WH_DLL_NEED_INSTALL="$need_install_dll_to_pfx $WH_DLL_NEED_INSTALL" fi USE_WT_FROM_DB=1 fi done if [[ "$USE_WT_FROM_DB" == "1" ]] ; then if update_winetricks ; then print_info "Пробуем установить библиотеки: ${WH_DLL_NEED_INSTALL}" print_info "Запускаем WINETRICKS..." export WINETRICKS_DOWNLOADER="curl" env WINEDLLOVERRIDES="winegstreamer=" "$WH_TMP_DIR/winetricks" -q ${WH_DLL_NEED_INSTALL} wait_wineserver fi fi fi } kill_wine () { wine_pids=$(ls -l /proc/*/exe 2>/dev/null | grep -E 'wine(64)?-preloader|wineserver' | awk -F/ '{print $3}') for pw_kill_pids in ${wine_pids}; do if ps cax | grep "${pw_kill_pids}" ; then kill -n 9 "${pw_kill_pids}" &>/dev/null fi done } init_database () { if [[ -f "$WIN_FILE_EXEC" ]] ; then WHDB="$(basename "$WIN_FILE_EXEC" .exe)" if [[ -f "$WIN_FILE_EXEC".whdb ]] ; then WHDB_FILE="$WIN_FILE_EXEC".whdb else orig_IFS="$IFS" IFS=$'\n' WH_FIND_DB_FILE="$(grep -ilw "#$WHDB.exe" "$WH_DB_DIR"/* )" if [[ $(echo "$WH_FIND_DB_FILE" | wc -l) -gt 1 ]] ; then print_error "Найдено более одного файла настроек: $WHDB.exe" WHDB_FILE="$(echo "$WH_FIND_DB_FILE" | head -n1)" else WHDB_FILE="$WH_FIND_DB_FILE" fi IFS="$orig_IFS" fi if [[ "$WHDB_FILE" ]] ; then print_info "Используется файл настроек: $WHDB_FILE" . "$WHDB_FILE" else print_warning "Файл настроек не найден. Пропускаем." fi fi } prepair_wine () { if [[ "$WH_AUTOINSTALL" == 1 ]] ; then print_warning "Лицензионные соглашения использования сторонних компонентов: Некоторые компоненты, установленные в префикс и необходимые для запуска приложений, могут быть защищены авторским правом или лицензионными соглашениями. Вы обязаны самостоятельно убедиться в законности использования этих компонентов в вашей юрисдикции. Мы не несём ответственности за нарушение лицензионных соглашений, связанное с использованием подготовленного префикса. Продолжая использовать данное ПО вы подтверждаете, что ознакомились с данным отказом от ответственности и принимаете все риски, связанные с его использованием. " sleep 5 fi var_winedlloverride_update "winemenubuilder.exe=d" init_database init_wine_ver init_wineprefix use_winetricks unset MANGOHUD_RUN if init_opengl ; then [[ "$MANGOHUD" == 1 ]] && MANGOHUD_RUN="mangohud --dlsym" else init_dxvk "$DXVK_STABLE_VER" init_vkd3d "$VKD3D_STABLE_VER" [[ "$MANGOHUD" == 1 ]] && MANGOHUD_RUN="mangohud" fi } wine_run () { print_var WINEPREFIX WINEDLLOVERRIDES WH_WINDOWS_VER WIN_FILE_PATH="$(dirname "$WIN_FILE_EXEC")" [[ -d "$WIN_FILE_PATH" ]] && cd "$WIN_FILE_PATH" $MANGOHUD_RUN "$WINELOADER" "$@" $LAUNCH_PARAMETERS wait_wineserver } wine_run_install () { print_info "Запускаем установку приложения $PROG_NAME." case "${1,,}" in *.exe) wine_run $WINE_WIN_START "$@" ;; *.msi) wine_run msiexec /i "$@" ;; *.bat|*.cmd) wine_run "$@" ;; *) fatal "Не удалось запустить файл $1. Проверьте расширение файла." ;; esac wait_wineserver } run_autoinstall () { if [[ $1 == "--clear-pfx" ]] ; then export CLEAR_PREFIX="1" shift elif [[ $2 == "--clear-pfx" ]] ; then export CLEAR_PREFIX="1" fi AI_SCRIPT="${1,,}" if [[ $AI_SCRIPT == "list" ]] || [[ -z "$AI_SCRIPT" ]] ; then echo "Список программ с возможностью автоматической установки:" for list in $(ls "$WH_AUTOINSTALL_DIR") ; do AI_INFO="$(grep "info_ru:" "$WH_AUTOINSTALL_DIR/$list" | awk -F"info_ru: " '{print $2}')" AI_PROGNAME="$(grep "PROG_NAME=" "$WH_AUTOINSTALL_DIR/$list" | awk -F"PROG_NAME=" '{print $2}')" echo -e "\n$list - $AI_PROGNAME" echo "$AI_INFO" done echo elif [[ -f "$WH_AUTOINSTALL_DIR/$AI_SCRIPT" ]] ; then export USE_AI_SCRIPTS="1" source "$WH_AUTOINSTALL_DIR/$AI_SCRIPT" print_info "Завершена установка $AI_SCRIPT" else fatal "Скрипт автоматической установки для $AI_SCRIPT не найден!" fi } wh_info () { echo "Использование: $SCRIPT_NAME [команда] Команды: install|-i list список возможных установочных скриптов install|-i [скрипт] запустить скрипт установки программы install|-i [скрипт] --clear-pfx не использовать подготовленный префикс для установки ПО installed|run список установленных программ run [программа.exe] запуск программы (отладка) Параметры: --help показать эту справку и выйти --version показать информацию о пакете и его версии " } ##### MAIN ##### create_new_dir "$WH_TMP_DIR" create_new_dir "$WH_DIST_DIR" create_new_dir "$WH_PREFIXES_DIR" create_new_dir "$WH_VULKAN_LIBDIR" case "${1,,}" in --version) rpm -qi "$SCRIPT_NAME" ; exit 0 ;; --help) wh_info ; exit 0 ;; killall) kill_wine ;; winecfg) prepair_wine ; wine_run "winecfg" ;; winereg|regedit) prepair_wine ; wine_run "regedit" ;; winefile|explorer) prepair_wine ; wine_run "winefile" ;; wineconsole|cmd) prepair_wine ; wine_run "wineconsole" ;; winetricks) shift ; update_winetricks ; prepair_wine ; "$WINETRICKS" -q "$@" ;; desktop) shift ; create_desktop "$@" ; exit 0 ;; install|-i) shift ; run_autoinstall "$@" ;; installed) shift ; check_installed_programs "$1" ;; run|-r) shift ; run_installed_programs "$1" ;; *) if [[ -f "$1" ]] ; then WIN_FILE_EXEC="$(readlink -f "$1")" WIN_FILE_NAME="$(basename "$WIN_FILE_EXEC")" shift case "${WIN_FILE_NAME,,}" in *.exe) prepair_wine ; wine_run $WINE_WIN_START "$WIN_FILE_EXEC" "$@" ;; *.msi) prepair_wine ; wine_run msiexec /i "$WIN_FILE_EXEC" "$@" ;; *.bat|*.cmd) prepair_wine ; wine_run start "$WIN_FILE_EXEC" "$@" ;; *) fatal "Тип файла не поддерживается." ;; esac else wh_info exit 1 fi ;; esac