From 9ec6dd0f3eb50e5b2ebe55d1732521a27da86e4e Mon Sep 17 00:00:00 2001 From: Mikhail Tergoev Date: Fri, 31 Jan 2025 15:17:19 +0300 Subject: [PATCH] added main script: winehelper --- winehelper | 820 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 820 insertions(+) create mode 100755 winehelper diff --git a/winehelper b/winehelper new file mode 100755 index 0000000..0b81472 --- /dev/null +++ b/winehelper @@ -0,0 +1,820 @@ +#!/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 + +PP_VULKAN_LIBDIR="$USER_WORK_PATH/vulkan" +PP_PREFIXES_DIR="$USER_WORK_PATH/prefixes" +PP_DIST_DIR="$USER_WORK_PATH/dist" +PP_TMP_DIR="$USER_WORK_PATH/tmp" + +PP_IMAGE_PATH="$DATA_PATH/image" +PP_DB_DIR="$DATA_PATH/database" +PP_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 PP_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 PP_WINDOWS_VER "10" +# check_variables PP_USE_GSTREAMER "1" +# check_variables PP_USE_D3D_EXTRAS "1" +check_variables PP_USE_SHADER_CACHE "1" +check_variables PP_USE_WINE_DXGI "0" +check_variables PP_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" + +##### 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 1>/dev/null +then : # Зависимости установлены. Пропускаем... +else + if su_run "$DATA_PATH/dependencies.sh" + then print_info "Зависимости успешно установлены. Продолжаем работу $0" + else fatal "Не удалось установить зависимости. Работа $0 прервана." + 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 () { + 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 () { + local name_desktop="$1" + local exe_file="$2" + local icon_file="$PP_IMAGE_PATH/$3.png" + + if [[ -z "$name_desktop" ]] || [[ -z "$exe_file" ]] ; then + fatal "Used: $0 --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 + grep -e "#!" -e "export" -e "var_" "$PP_AUTOINSTALL_DIR/$AI_SCRIPT" \ + | grep -vE "LAUNCH_PARAMETERS|AUTOINSTALL|WIN_FILE_EXEC|echo" \ + | awk '{$1=$1;print}' > "$exe_file".ppdb + print_info "Создан файл настроек для $exe_file" + 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 "$DXVK_STABLE_VER" + + get_dxvk () { + DXVK_URL="$1" + DXVK_PACKAGE="${PP_VULKAN_LIBDIR}/dxvk-${DXVK_VAR_VER}.tar.$(echo ${DXVK_URL#*.tar.})" + if try_download "$DXVK_URL" "$DXVK_PACKAGE" check256sum \ + && unpack "$DXVK_PACKAGE" "$PP_VULKAN_LIBDIR" + then + try_remove_file "$DXVK_PACKAGE" + return 0 + fi + return 1 + } + + for DXVK_VAR_VER in "$USE_DXVK_VER" $@ ; do + if [[ ! -d "${PP_VULKAN_LIBDIR}/dxvk-$DXVK_VAR_VER" ]] ; then + get_dxvk "$CLOUD_URL/dxvk-${DXVK_VAR_VER}.tar.gz" + fi + done + + if [[ "${PP_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 "${PP_VULKAN_LIBDIR}/dxvk-$USE_DXVK_VER/x64/$dxvkfiles.dll" + if try_copy_other_dll_to_pfx_32 "${PP_VULKAN_LIBDIR}/dxvk-$USE_DXVK_VER/x32/$dxvkfiles.dll" + then var_winedlloverride_update "$dxvkfiles=n" + fi + done +} + +init_vkd3d () { + check_variables USE_VKD3D_VER "$VKD3D_STABLE_VER" + + get_vkd3d () { + VKD3D_URL="$1" + VKD3D_PACKAGE="${PP_VULKAN_LIBDIR}/vkd3d-proton-${VKD3D_VAR_VER}.tar.$(echo ${VKD3D_URL#*.tar.})" + if try_download "$VKD3D_URL" "$VKD3D_PACKAGE" check256sum \ + && unpack "$VKD3D_PACKAGE" "$PP_VULKAN_LIBDIR" + then + try_remove_file "$VKD3D_PACKAGE" + return 0 + fi + return 1 + } + + for VKD3D_VAR_VER in "$USE_VKD3D_VER" $@ ; do + if [[ ! -d "${PP_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 "${PP_VULKAN_LIBDIR}/vkd3d-proton-$USE_VKD3D_VER/x64/$vkd3dfiles.dll" + if try_copy_other_dll_to_pfx_32 "${PP_VULKAN_LIBDIR}/vkd3d-proton-$USE_VKD3D_VER/x86/$vkd3dfiles.dll" + then var_winedlloverride_update "$vkd3dfiles=n" + fi + done +} + +##### DOWNLOAD WINE ##### +download_wine () { + if [[ ! -d "$PP_DIST_DIR/$PP_WINE_USE" ]] ; then + WINE_URL="$CLOUD_URL/$PP_WINE_USE.tar.xz" + local WINE_PACKAGE="$PP_TMP_DIR/${PP_WINE_USE}.tar.xz" + if try_download "$WINE_URL" "$WINE_PACKAGE" check256sum ; then + if unpack "$WINE_PACKAGE" "$PP_DIST_DIR/" ; then + echo "$PP_WINE_USE" > "$PP_DIST_DIR/$PP_WINE_USE/version" + try_remove_file "$WINE_PACKAGE" + fi + fi + fi +} + +##### INITIAL WINE SETTINGS ##### +init_wine_ver () { + if [[ "$PP_WINE_USE" != system* ]] ; then + export WINEDIR="$PP_DIST_DIR/$PP_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 "${PP_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 PP_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 PP_WDBG="" + fi + + print_info "Используется версия wine: $PP_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="$PP_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="$PP_PREFIXES_DIR/default" + else + if echo "$WINEPREFIX" | grep -v '/' ; then + export WINEPREFIX="$PP_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 $PP_WINDOWS_VER" "$WINEPREFIX/system.reg") ]] + then + if [[ $(echo "$PP_WINDOWS_VER" | sed 's/.*/\L&/') == "xp" ]] \ + && [[ "$WINEARCH" != "win32" ]] + then export PP_WINDOWS_VER="xp64" + fi + env WINEDLLOVERRIDES="winegstreamer=" "$WINELOADER" winecfg -v $(echo "win${PP_WINDOWS_VER}" | sed 's/.*/\L&/') + wait_wineserver + print_info "Windows версия изменена на win${PP_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 +} + + +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 "$PP_TMP_DIR/winetricks" ]] ; then + W_TRX_INT_VER="$(cat "$PP_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" "$PP_TMP_DIR/winetricks_new" ; then + mv -f "$PP_TMP_DIR/winetricks_new" "$PP_TMP_DIR/winetricks" + W_TRX_INT_VER="$(cat "$PP_TMP_DIR/winetricks" | grep -i 'WINETRICKS_VERSION=' | sed 's/_VERSION=//')" + print_info "Портативная версия winetricks обновлена до (${W_TRX_INT_VER})" + chmod u+x "$PP_TMP_DIR/winetricks" + fi + fi + export WINETRICKS="$PP_TMP_DIR/winetricks" +} + +use_winetricks () { + if [[ -n "$INSTALL_DLL" ]] ; then + PP_DLL_INSTALL="$(echo "$INSTALL_DLL $PP_DLL_INSTALL" | awk '{ for(i=1;i<=NF;i++){a[$i]++} }END{ for(i in a){printf("%s ",i)} }' )" + fi + if [[ -n "$PP_DLL_INSTALL" ]] ; then + PP_DLL_NEED_INSTALL="" + USE_WT_FROM_DB=0 + [[ ! -f "$WINEPREFIX/winetricks.log" ]] && touch "$WINEPREFIX/winetricks.log" + for need_install_dll_to_pfx in $PP_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 "$PP_DLL_NEED_INSTALL" ]] + then PP_DLL_NEED_INSTALL="$need_install_dll_to_pfx" + else PP_DLL_NEED_INSTALL="$need_install_dll_to_pfx $PP_DLL_NEED_INSTALL" + fi + USE_WT_FROM_DB=1 + fi + done + if [[ "$USE_WT_FROM_DB" == "1" ]] ; then + if update_winetricks ; then + print_info "Пробуем установить библиотеки: ${PP_DLL_NEED_INSTALL}" + print_info "Запускаем WINETRICKS..." + export WINETRICKS_DOWNLOADER="curl" + env WINEDLLOVERRIDES="winegstreamer=" "$PP_TMP_DIR/winetricks" -q ${PP_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 + PPDB="$(basename "$WIN_FILE_EXEC" .exe)" + if [[ -f "$WIN_FILE_EXEC".ppdb ]] ; then + PPDB_FILE="$WIN_FILE_EXEC".ppdb + else + orig_IFS="$IFS" + IFS=$'\n' + PP_FIND_DB_FILE="$(grep -ilw "#$PPDB.exe" "$PP_DB_DIR"/* )" + if [[ $(echo "$PP_FIND_DB_FILE" | wc -l) -gt 1 ]] ; then + print_error "Найдено более одного файла настроек: $PPDB.exe" + PPDB_FILE="$(echo "$PP_FIND_DB_FILE" | head -n1)" + else + PPDB_FILE="$PP_FIND_DB_FILE" + fi + IFS="$orig_IFS" + fi + if [[ "$PPDB_FILE" ]] ; then + print_info "Используется файл настроек: $PPDB_FILE" + . "$PPDB_FILE" + else + print_warning "Файл настроек не найден. Пропускаем." + fi + fi +} + +prepair_wine () { + var_winedlloverride_update "winemenubuilder.exe=" + + 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 + init_vkd3d + [[ "$MANGOHUD" == 1 ]] && MANGOHUD_RUN="mangohud" + fi +} + +wine_run () { + print_var WINEPREFIX WINEDLLOVERRIDES PP_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 () { + case "${1,,}" in + *.exe) wine_run $WINE_WIN_START "$@" ;; + *.msi) wine_run msiexec /i "$@" ;; + *.bat|*.cmd) wine_run "$@" ;; + *) fatal "Unknown file extension." ;; + esac + wait_wineserver +} + +run_autoinstall () { + AI_SCRIPT="${1,,}" + if [[ $AI_SCRIPT == "list" ]] || [[ -z "$AI_SCRIPT" ]] ; then + print_info "Список программ с возможностью автоматической установки:" + for list in $(ls "$PP_AUTOINSTALL_DIR") ; do + AI_INFO="$(grep "info_ru:" "$PP_AUTOINSTALL_DIR/$list" | awk -F"info_ru: " '{print $2}')" + AI_PROGNAME="$(grep "PROG_NAME=" "$PP_AUTOINSTALL_DIR/$list" | awk -F"PROG_NAME=" '{print $2}')" + printf "\E[36m%s $SCRIPT_NAME install $list - $AI_PROGNAME %s\e[0m\n" + echo -e "$AI_INFO\n" + done + echo + elif [[ -f "$PP_AUTOINSTALL_DIR/$AI_SCRIPT" ]] ; then + export USE_AI_SCRIPTS="1" + source "$PP_AUTOINSTALL_DIR/$AI_SCRIPT" + print_info "Завершена установка $AI_SCRIPT" + else + fatal "Скрипт автоматической установки для $AI_SCRIPT не найден!" + fi +} + +##### MAIN ##### +create_new_dir "$PP_TMP_DIR" +create_new_dir "$PP_DIST_DIR" +create_new_dir "$PP_PREFIXES_DIR" +create_new_dir "$PP_VULKAN_LIBDIR" + +case "${1,,}" in + 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|autoinstall|-ai) shift ; run_autoinstall "$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 + print_info "Делать нечего... Выходим." + exit 0 + fi + ;; +esac