From 19ad4191ecc3cb2b26eac03085ddc71df458e32b Mon Sep 17 00:00:00 2001 From: MaxWaldorf Date: Tue, 9 Jun 2026 10:35:19 +0200 Subject: [PATCH 1/6] first steam iteration --- bms-helper.sh | 174 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 167 insertions(+), 7 deletions(-) diff --git a/bms-helper.sh b/bms-helper.sh index 85a200e..d1d2374 100755 --- a/bms-helper.sh +++ b/bms-helper.sh @@ -338,6 +338,8 @@ fi # Falcon 4.0 Installer on GoG gog_url="https://www.gog.com/downloads/falcon_gold/61603" gog_installer="setup_falcon_4_2.0.0.1.exe" +falcon4_source="gog" +steam_falcon4_dir="" if [ -z "$bms_installer" ]; then bms_installer="Falcon BMS_4.38.0_Full_Setup.exe" fi @@ -4470,7 +4472,21 @@ install_game() { return 1 fi - download_gog_installer + choose_falcon4_source + if [ "$?" -eq 1 ]; then + cleanup_conf_if_only_firstrun + return 1 + fi + + if [ "$falcon4_source" = "gog" ]; then + download_gog_installer + if [ "$?" -eq 1 ]; then + message error "Unable to prepare Falcon 4.0 from GOG. Aborting." + cleanup_conf_if_only_firstrun + return 1 + fi + fi + download_bms_installer # Abort if the download failed if [ "$?" -eq 1 ]; then @@ -4557,13 +4573,41 @@ install_game() { wine reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v LogPixels /t REG_DWORD /d 96 /f >>"$tmp_install_log" 2>&1 - # Run the Falcon 4.0 GoG installer - debug_print continue "Installing Falcon 4.0. Please wait; this will take a moment..." - progress_update "Running Falcon 4.0 GoG installer..." - if [ -n "$selected_gog_installer" ]; then - wine "$selected_gog_installer" /VERYSILENT /NOICONS >>"$tmp_install_log" 2>&1 + if [ "$falcon4_source" = "steam" ]; then + # Create Falcon 4.0 target directory in the Proton/Wine C: drive, + # then mirror files from the Steam installation. + steam_target_dir="$install_dir/drive_c/Falcon 4.0" + progress_update "Copying Steam Falcon 4.0 files into the Wine prefix..." + debug_print continue "Copying Steam Falcon 4.0 files from $steam_falcon4_dir to $steam_target_dir" + mkdir -p "$steam_target_dir" >>"$tmp_install_log" 2>&1 + cp -a "$steam_falcon4_dir"/. "$steam_target_dir"/ >>"$tmp_install_log" 2>&1 + copy_exit_code="$?" + if [ "$copy_exit_code" -ne 0 ] || [ ! -f "$steam_target_dir/falcon4.exe" ]; then + wineserver -k + progress_bar stop + message error "Failed to copy Steam Falcon 4.0 files into the Wine prefix.\nThe install log was written to\n$tmp_install_log" + cleanup_conf_if_only_firstrun + return 1 + fi + + progress_update "Applying Falcon 4.0 registry keys..." + apply_falcon4_registry_key >>"$tmp_install_log" 2>&1 + if [ "$?" -ne 0 ]; then + wineserver -k + progress_bar stop + message error "Falcon 4.0 registry initialization failed.\nThe install log was written to\n$tmp_install_log" + cleanup_conf_if_only_firstrun + return 1 + fi else - wine "$SCRIPT_DIR/$gog_installer" /VERYSILENT /NOICONS >>"$tmp_install_log" 2>&1 + # Run the Falcon 4.0 GoG installer + debug_print continue "Installing Falcon 4.0. Please wait; this will take a moment..." + progress_update "Running Falcon 4.0 GoG installer..." + if [ -n "$selected_gog_installer" ]; then + wine "$selected_gog_installer" /VERYSILENT /NOICONS >>"$tmp_install_log" 2>&1 + else + wine "$SCRIPT_DIR/$gog_installer" /VERYSILENT /NOICONS >>"$tmp_install_log" 2>&1 + fi fi # Run the Falcon BMS installer @@ -4957,6 +5001,122 @@ download_protontricks() { return 0 } +# MARK: detect_steam_falcon4_install() +# Detect Falcon 4.0 in known Steam default locations +detect_steam_falcon4_install() { + steam_falcon4_dir="" + local candidates=( + "$HOME/.steam/steam/steamapps/common/Falcon 4.0" + "$HOME/.steam/root/steamapps/common/Falcon 4.0" + "$HOME/.local/share/Steam/steamapps/common/Falcon 4.0" + "$HOME/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/common/Falcon 4.0" + ) + local candidate + for candidate in "${candidates[@]}"; do + if [ -d "$candidate" ] && [ -f "$candidate/falcon4.exe" ]; then + steam_falcon4_dir="$candidate" + return 0 + fi + done + return 1 +} + +# MARK: select_steam_falcon4_install() +# Ask the user to select their Steam Falcon 4.0 folder and validate falcon4.exe +select_steam_falcon4_install() { + local default_dir="$HOME/.steam/steam/steamapps/common/Falcon 4.0" + local selected_dir="" + + if [ "$use_zenity" -eq 1 ]; then + selected_dir="$(zenity --file-selection --directory --title="Select Steam Falcon 4.0 directory" --filename="$default_dir/" 2>/dev/null)" + if [ -z "$selected_dir" ]; then + message error "No Steam Falcon 4.0 directory selected. Aborting installation." + return 1 + fi + else + printf "Enter your Steam Falcon 4.0 directory\nExample: %s\n\n" "$default_dir" + read -rp "Directory path: " selected_dir + if [ -z "$selected_dir" ]; then + message error "No Steam Falcon 4.0 directory provided. Aborting installation." + return 1 + fi + fi + + if [ ! -d "$selected_dir" ] || [ ! -f "$selected_dir/falcon4.exe" ]; then + message error "Invalid Steam Falcon 4.0 directory. Expected to find falcon4.exe in:\n$selected_dir\n\nInstallation cancelled." + return 1 + fi + + steam_falcon4_dir="$selected_dir" + return 0 +} + +# MARK: choose_falcon4_source() +# Ask user whether Falcon 4.0 should come from Steam; fallback to GOG by default +choose_falcon4_source() { + falcon4_source="gog" + steam_falcon4_dir="" + + if message question "Do you have Falcon 4.0 installed from Steam?\n\nSelect 'No' to use the default GOG installer flow."; then + falcon4_source="steam" + if detect_steam_falcon4_install; then + message info "Steam Falcon 4.0 detected at:\n$steam_falcon4_dir" + return 0 + fi + + message warning "Steam Falcon 4.0 was not found in default locations.\nPlease select your Falcon 4.0 folder manually." + if ! select_steam_falcon4_install; then + return 1 + fi + else + falcon4_source="gog" + fi + + return 0 +} + +# MARK: apply_falcon4_registry_key() +# Import Falcon 4.0 registry keys into the current prefix without external files +apply_falcon4_registry_key() { + if [ -z "$WINEPREFIX" ] || [ ! -d "$WINEPREFIX/drive_c" ]; then + message error "Unable to apply Falcon 4.0 registry key: Wine prefix is not ready." + return 1 + fi + + local falcon4_reg_file="$WINEPREFIX/drive_c/falcon_4.reg" + cat > "$falcon4_reg_file" << 'EOF' +Windows Registry Editor Version 5.00 + +[HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse] + +[HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse\\Falcon] + +[HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse\\Falcon\\4.0] +"baseDir"="C:\\Falcon 4.0" +"misctexDir"="C:\\Falcon 4.0\\terrdata\\misctex" +"movieDir"="C:\\Falcon 4.0" +"objectDir"="C:\\Falcon 4.0\\terrdata\\objects" +"theaterDir"="C:\\Falcon 4.0\\terrdata\\korea" + +[HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse\\Falcon\\4.0\\MPR] +"MPRDetect3Dx"=dword:00000001 +"MPRDetectCPU"=dword:00000001 +"MPRDetectMMX"=dword:00000001 +"MPRDetectXMM"=dword:00000001 +EOF + + wine regedit /S "C:\\falcon_4.reg" + local reg_exit_code="$?" + rm -f "$falcon4_reg_file" 2>/dev/null || true + + if [ "$reg_exit_code" -ne 0 ]; then + message error "Failed to apply Falcon 4.0 registry keys." + return 1 + fi + + return 0 +} + # MARK: download_gog_installer() # Opens browser for GOG download, waits for the installer to appear in Downloads, then runs it download_gog_installer() { From b0a756cb850c510c2d20e247ff6db625c5cda139 Mon Sep 17 00:00:00 2001 From: MaxWaldorf Date: Sun, 5 Jul 2026 15:22:32 +0200 Subject: [PATCH 2/6] - better steam support - Fixes to some internal functions - Falcon 4.0 support changed for internal functions --- README.md | 5 +- bms-helper.sh | 320 +++++++++++++++++++++++++++++++++---------- bms-launcher-256.png | Bin 0 -> 29763 bytes 3 files changed, 249 insertions(+), 76 deletions(-) create mode 100644 bms-launcher-256.png diff --git a/README.md b/README.md index 4483e56..31fb8ce 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Configuration is saved in *$XDG_CONFIG_HOME/bms-helper/* - This limits the maximum number of open files on your system. On some Linux distributions, the default is set too low for Falcon BMS `Install Falcon BMS` -- Installs Falcon BMS and Falcon 4.0 (GoG installer) +- Installs Falcon BMS (public installs also require Falcon 4.0 from GoG or Steam; internal installs do not) `Maintenance and Troubleshooting` - `Target a different Falcon BMS installation` @@ -50,7 +50,8 @@ Configuration is saved in *$XDG_CONFIG_HOME/bms-helper/* **From Source:** 1. Download it! https://github.com/benchmarksims/bms-helper/releases 2. Extract it! -3. Place `Falcon BMS_4.38.1_Full_Setup.exe`, `Falcon BMS_4.38.1_Full_Setup.nsisbin` and `setup_falcon_4_2.0.0.1.exe` (from GoG) in the bms-helper extracted folder +3. Public install: place `Falcon BMS_4.38.1_Full_Setup.exe`, `Falcon BMS_4.38.1_Full_Setup.nsisbin` and `setup_falcon_4_2.0.0.1.exe` (from GoG) in the bms-helper extracted folder +4. Internal install: place the internal Falcon BMS installer package in the helper folder (Falcon 4.0 media is not required) 4. Run the `bms-helper.sh`! _Dependencies: **bash**, **coreutils**, **curl**, **polkit**, **wine**, **protontricks**_ diff --git a/bms-helper.sh b/bms-helper.sh index d1d2374..955d24f 100755 --- a/bms-helper.sh +++ b/bms-helper.sh @@ -194,8 +194,9 @@ set_bms_mode "$bms_mode" PROTON_DEFAULT_VERSION="GE-Proton10-32" SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) -# Path to bundled icon +# Paths to bundled icons bms_icon="$SCRIPT_DIR/bms-launcher.png" +bms_icon_256="$SCRIPT_DIR/bms-launcher-256.png" # Use XDG base directories if defined if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" ]; then @@ -1216,9 +1217,6 @@ if [ -d "\$WINEPREFIX/drive_c" ]; then fi fi -# Keep desktop entries stable and favor native .NET runtime components. -# mscoree=n prevents accidental fallback to Wine Mono for .NET Framework apps. -export WINEDLLOVERRIDES="winemenubuilder.exe=d;mscoree=n,b" export WINEDEBUG="\${WINEDEBUG:--all}" unset SDL_VIDEODRIVER @@ -1238,7 +1236,7 @@ export BMS_USE_MANGOHUD="\${BMS_USE_MANGOHUD:-0}" export BMS_PROTON_LOG="\${BMS_PROTON_LOG:-0}" export BMS_USE_FSYNC="\${BMS_USE_FSYNC:-1}" export BMS_USE_ESYNC="\${BMS_USE_ESYNC:-1}" -export BMS_AUTO_LAUNCH_OPENTRACK="\${BMS_AUTO_LAUNCH_OPENTRACK:-1}" +export BMS_AUTO_LAUNCH_OPENTRACK="\${BMS_AUTO_LAUNCH_OPENTRACK:-0}" export BMS_OPENTRACK_DELAY="\${BMS_OPENTRACK_DELAY:-3}" if [ "\$BMS_USE_FSYNC" != "1" ]; then @@ -1914,6 +1912,73 @@ EOF return 0 } +# MARK: ensure_bms_icon_installed() +# Install/refresh the bundled icon in the user's local hicolor icon directory. +ensure_bms_icon_installed() { + icon_target_dir_256="${data_dir}/icons/hicolor/256x256/apps" + icon_target_dir_512="${data_dir}/icons/hicolor/512x512/apps" + icon_target_dir_pixmaps="${data_dir}/pixmaps" + icon_target_path_256="${icon_target_dir_256}/bms-launcher.png" + icon_target_path_512="${icon_target_dir_512}/bms-launcher.png" + icon_target_path_pixmaps="${icon_target_dir_pixmaps}/bms-launcher.png" + icon_prefix_path="" + icon_source_512="$bms_icon" + icon_source_256="$bms_icon_256" + + if [ ! -f "$icon_source_512" ]; then + debug_print continue "Bundled icon was not found at $icon_source_512" + return 1 + fi + + if [ ! -s "$icon_source_512" ]; then + debug_print continue "Bundled icon is empty and cannot be installed: $icon_source_512" + return 1 + fi + + # Prefer the bundled 256 icon for 256x256 installs, fallback to 512 if missing. + if [ ! -f "$icon_source_256" ] || [ ! -s "$icon_source_256" ]; then + icon_source_256="$icon_source_512" + fi + + mkdir -p "$icon_target_dir_256" "$icon_target_dir_512" "$icon_target_dir_pixmaps" || return 1 + + # Force overwrite so repair/recreate always refreshes stale or corrupted icons. + if ! cp -f -- "$icon_source_256" "$icon_target_path_256"; then + debug_print continue "Failed to copy icon to $icon_target_path_256" + return 1 + fi + if ! cp -f -- "$icon_source_512" "$icon_target_path_512"; then + debug_print continue "Failed to copy icon to $icon_target_path_512" + return 1 + fi + if ! cp -f -- "$icon_source_512" "$icon_target_path_pixmaps"; then + debug_print continue "Failed to copy icon to $icon_target_path_pixmaps" + return 1 + fi + + if [ ! -s "$icon_target_path_256" ] || [ ! -s "$icon_target_path_512" ] || [ ! -s "$icon_target_path_pixmaps" ]; then + debug_print continue "Installed icon appears empty in one or more target locations" + return 1 + fi + + # Also place the icon beside the generated launcher in the prefix root. + # This allows desktop files to use an absolute icon path that does not depend on icon themes. + if [ -n "$install_dir" ] && [ -d "$install_dir" ]; then + icon_prefix_path="$install_dir/bms-launcher.png" + if ! cp -f -- "$icon_source_512" "$icon_prefix_path"; then + debug_print continue "Failed to copy icon beside launcher: $icon_prefix_path" + fi + fi + + # Refresh icon cache when available so desktop environments pick the new icon. + if [ -x "$(command -v gtk-update-icon-cache)" ]; then + gtk-update-icon-cache -q -t "${data_dir}/icons/hicolor" >/dev/null 2>&1 || true + fi + + debug_print continue "Installed icon to $icon_target_path_256" + return 0 +} + ############################################################################ ######## begin preflight check functions ################################### @@ -1941,7 +2006,10 @@ preflight_check() { unset preflight_followup unset preflight_fail_string unset preflight_pass_string + unset preflight_manual_string unset preflight_fix_results_string + unset preflight_root_actions_string + unset preflight_user_actions_string unset install_mode retval=0 @@ -2137,7 +2205,13 @@ mapcount_check() { if [ "$mapcount" -ge 16777216 ]; then # All good preflight_pass+=("vm.max_map_count is set to $mapcount.") - elif grep -E -x -q "vm.max_map_count" /etc/sysctl.conf /etc/sysctl.d/* 2>/dev/null; then + elif awk ' + /^[[:space:]]*#/ { next } + match($0, /^[[:space:]]*vm\.max_map_count[[:space:]]*=[[:space:]]*([0-9]+)/, m) { + if (m[1] >= 16777216) found=1 + } + END { exit(found ? 0 : 1) } + ' /etc/sysctl.conf /etc/sysctl.d/* 2>/dev/null; then # Was it supposed to have been set by sysctl? preflight_fail+=("vm.max_map_count is configured to at least 16777216 but the setting has not been loaded by your system.") # Add the function that will be called to change the configuration @@ -3929,6 +4003,30 @@ install_powershell() { # MARK: reinstall_bms_launcher() # Download and re-install the latest Falcon BMS into the wine prefix +# MARK: build_bms_installer_args() +# Build installer argument array for public/internal variants. +build_bms_installer_args() { + installer_args=("/S") + + # Keep installer behavior consistent across public/internal builds. + installer_args+=("/noshort") + + if [ "${use_16k_tiles:-}" = "1" ]; then + installer_args+=("/16k") + fi + + if [ "$bms_mode" = "internal" ]; then + bms_key="$(echo "${bms_key:-}" | tr -d '\r' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + if [ -z "$bms_key" ]; then + message error "Internal installer key is required for internal Falcon BMS installs.\n\nPlease run install again and enter a valid key." + return 1 + fi + installer_args+=("/key=$bms_key") + fi + + return 0 +} + reinstall_bms_launcher() { # Update directories getdirs @@ -3939,7 +4037,7 @@ reinstall_bms_launcher() { return 1 fi - download_gog_installer + download_bms_installer # Abort if the download failed if [ "$?" -eq 1 ]; then message error "Unable to install or update the Falcon BMS." @@ -3959,22 +4057,44 @@ reinstall_bms_launcher() { # Set the correct wine prefix export WINEPREFIX="$wine_prefix" - export WINEDLLOVERRIDES="" # Show a zenity pulsating progress bar progress_bar start "Installing Falcon BMS. Please wait..." progress_update "Running Falcon BMS installer..." + # Guard against a stalled installer process. + launcher_timeout_seconds="${BMS_INSTALLER_TIMEOUT_SECONDS:-7200}" + # Run the installer debug_print continue "Installing Falcon BMS. Please wait; this will take a moment..." - "$launcher_winepath"/wine "$tmp_dir/$gog_installer" /S + reinstall_installer_path="" + if [ -n "$selected_bms_installer" ]; then + reinstall_installer_path="$selected_bms_installer" + else + reinstall_installer_path="$SCRIPT_DIR/$bms_installer" + fi + + if ! build_bms_installer_args; then + progress_bar stop + return 1 + fi + + if [ -x "$(command -v timeout)" ] && [ -n "$launcher_timeout_seconds" ]; then + timeout --foreground "$launcher_timeout_seconds" "$launcher_winepath"/wine "$reinstall_installer_path" "${installer_args[@]}" + else + "$launcher_winepath"/wine "$reinstall_installer_path" "${installer_args[@]}" + fi exit_code="$?" - if [ "$exit_code" -eq 1 ] || [ "$exit_code" -eq 58 ]; then + if [ "$exit_code" -eq 1 ] || [ "$exit_code" -eq 58 ] || [ "$exit_code" -eq 124 ]; then # User cancelled or there was an error "$launcher_winepath"/wineserver -k # Kill all wine processes progress_bar stop # Stop the zenity progress window - message error "Installation aborted. See terminal output for details." + if [ "$exit_code" -eq 124 ]; then + message error "Installation timed out after ${launcher_timeout_seconds} seconds.\n\nThis usually means the installer is waiting on a hidden dialog or got stuck.\nCheck terminal output for details." + else + message error "Installation aborted. See terminal output for details." + fi return 1 fi @@ -4099,8 +4219,11 @@ uninstall_bms() { # Remove desktop files and icon rm -f -- "$prefix_desktop_file" "$localshare_desktop_file" "$home_desktop_file" - # Also remove legacy shortcut names used before mode-specific desktop files. - rm -f -- "$legacy_prefix_desktop_file" "$legacy_localshare_desktop_file" "$legacy_home_desktop_file" + # Also remove legacy shortcut names used before mode-specific desktop files, + # but only if we're in public mode (legacy files use public mode name "Falcon BMS.desktop") + if [ "$bms_mode" = "public" ]; then + rm -f -- "$legacy_prefix_desktop_file" "$legacy_localshare_desktop_file" "$legacy_home_desktop_file" + fi rm -f -- "$icon_file" # Update desktop database @@ -4472,19 +4595,25 @@ install_game() { return 1 fi - choose_falcon4_source - if [ "$?" -eq 1 ]; then - cleanup_conf_if_only_firstrun - return 1 - fi - - if [ "$falcon4_source" = "gog" ]; then - download_gog_installer + if [ "$bms_mode" != "internal" ]; then + choose_falcon4_source if [ "$?" -eq 1 ]; then - message error "Unable to prepare Falcon 4.0 from GOG. Aborting." cleanup_conf_if_only_firstrun return 1 fi + + if [ "$falcon4_source" = "gog" ]; then + download_gog_installer + if [ "$?" -eq 1 ]; then + message error "Unable to prepare Falcon 4.0 from GOG. Aborting." + cleanup_conf_if_only_firstrun + return 1 + fi + fi + else + # Internal installs do not require Falcon 4.0 media. + falcon4_source="none" + steam_falcon4_dir="" fi download_bms_installer @@ -4537,22 +4666,40 @@ install_game() { #export WINE="$wine_path/wine" #export WINESERVER="$wine_path/wineserver" export WINEPREFIX="$install_dir" - export WINEDLLOVERRIDES="" + + # Timeouts for long-running install stages (override via environment if needed). + prefix_setup_timeout_seconds="${BMS_PREFIX_SETUP_TIMEOUT_SECONDS:-5400}" + installer_timeout_seconds="${BMS_INSTALLER_TIMEOUT_SECONDS:-7200}" # Show a zenity pulsating progress bar progress_bar start "Preparing Wine prefix and installing Falcon BMS. Please wait..." progress_update "Preparing Wine prefix..." - # Create the new prefix and install powershell + # Create the new prefix and install required runtime components. progress_update "Installing required components into the Wine prefix..." debug_print continue "Installing required components into the Wine prefix. Please wait; this will take a moment..." - "$protontricks_bin" -q corefonts tahoma lucida verdana dxvk powershell dotnet48 win11 >"$tmp_install_log" 2>&1 + + # Let the game installer handle .NET 4.8.1 by default. + # Set BMS_PREINSTALL_DOTNET48=1 only if you explicitly want helper-side dotnet48 preinstall. + prefix_components=(corefonts tahoma lucida verdana dxvk powershell win11) + if [ "${BMS_PREINSTALL_DOTNET48:-0}" = "1" ]; then + prefix_components+=(dotnet48) + fi + + if [ -x "$(command -v timeout)" ] && [ -n "$prefix_setup_timeout_seconds" ]; then + timeout --foreground "$prefix_setup_timeout_seconds" "$protontricks_bin" -q "${prefix_components[@]}" >"$tmp_install_log" 2>&1 + else + "$protontricks_bin" -q "${prefix_components[@]}" >"$tmp_install_log" 2>&1 + fi exit_code="$?" - if [ "$exit_code" -eq 1 ] || [ "$exit_code" -eq 130 ] || [ "$exit_code" -eq 126 ]; then + if [ "$exit_code" -eq 1 ] || [ "$exit_code" -eq 130 ] || [ "$exit_code" -eq 126 ] || [ "$exit_code" -eq 124 ]; then # 126 = permission denied (ie. noexec on /tmp) wineserver -k # Kill all wine processes progress_bar stop # Stop the zenity progress window + if [ "$exit_code" -eq 124 ]; then + message warning "Wine prefix preparation timed out after ${prefix_setup_timeout_seconds} seconds.\n\nThe install log was written to\n$tmp_install_log\n\nThis usually means a hidden installer dialog blocked automation." + fi if message question "Wine prefix creation failed. Aborting installation.\nThe install log was written to\n$tmp_install_log\n\nDo you want to delete\n${install_dir}?"; then debug_print continue "Deleting $install_dir..." rm -r --interactive=never "$install_dir" @@ -4599,7 +4746,7 @@ install_game() { cleanup_conf_if_only_firstrun return 1 fi - else + elif [ "$falcon4_source" = "gog" ]; then # Run the Falcon 4.0 GoG installer debug_print continue "Installing Falcon 4.0. Please wait; this will take a moment..." progress_update "Running Falcon 4.0 GoG installer..." @@ -4608,46 +4755,45 @@ install_game() { else wine "$SCRIPT_DIR/$gog_installer" /VERYSILENT /NOICONS >>"$tmp_install_log" 2>&1 fi + else + debug_print continue "Internal mode selected: skipping Falcon 4.0 install/source requirements." fi # Run the Falcon BMS installer debug_print continue "Installing Falcon BMS. Please wait; this will take a moment..." progress_update "Running Falcon BMS installer..." - # Determine tiles argument (default: opt-out unless user explicitly chose) - if [ "${use_16k_tiles:-}" = "1" ]; then - tiles_arg="/16k" - else - tiles_arg="" - fi - # Determine key argument (for internal installers) - if [ -n "${bms_key:-}" ]; then - key_arg="/key=${bms_key}" - else - key_arg="" - fi - # Build installer argument array to avoid passing empty/split parameters - installer_args=("/S") - installer_args+=("/noshort") - if [ -n "$tiles_arg" ]; then - installer_args+=("$tiles_arg") - fi - if [ -n "$key_arg" ]; then - installer_args+=("$key_arg") + # Build installer arguments suitable for the selected release type. + if ! build_bms_installer_args; then + wineserver -k + progress_bar stop + cleanup_conf_if_only_firstrun + return 1 fi debug_print continue "Falcon BMS selected arguments: ${installer_args[*]}" if [ -n "$selected_bms_installer" ]; then - wine "$selected_bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 + if [ -x "$(command -v timeout)" ] && [ -n "$installer_timeout_seconds" ]; then + timeout --foreground "$installer_timeout_seconds" wine "$selected_bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 + else + wine "$selected_bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 + fi else - wine "$SCRIPT_DIR/$bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 + if [ -x "$(command -v timeout)" ] && [ -n "$installer_timeout_seconds" ]; then + timeout --foreground "$installer_timeout_seconds" wine "$SCRIPT_DIR/$bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 + else + wine "$SCRIPT_DIR/$bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 + fi fi exit_code="$?" - if [ "$exit_code" -eq 1 ] || [ "$exit_code" -eq 58 ]; then + if [ "$exit_code" -eq 1 ] || [ "$exit_code" -eq 58 ] || [ "$exit_code" -eq 124 ]; then # User cancelled or there was an error wineserver -k # Kill all wine processes progress_bar stop # Stop the zenity progress window + if [ "$exit_code" -eq 124 ]; then + message warning "Falcon BMS installer timed out after ${installer_timeout_seconds} seconds.\n\nThe install log was written to\n$tmp_install_log" + fi if message question "Installation aborted. The install log was written to\n$tmp_install_log\n\nDo you want to delete\n${install_dir}?"; then debug_print continue "Deleting $install_dir..." rm -r --interactive=never "$install_dir" @@ -4685,15 +4831,9 @@ install_game() { fi installed_launch_script="$install_dir/$wine_launch_script_name" - # Copy the bundled Falcon BMS icon to the .local icons directory - if [ -f "$bms_icon" ]; then - mkdir -p "${data_dir}/icons/hicolor/256x256/apps" && - cp "$bms_icon" "${data_dir}/icons/hicolor/256x256/apps" - # also copy to standard name to ensure icon matches desktop file - icon_installed_path="${data_dir}/icons/hicolor/256x256/apps/$(basename "$bms_icon")" - if [ -f "$icon_installed_path" ]; then - debug_print continue "Installed icon to $icon_installed_path" - fi + # Copy/refresh the bundled Falcon BMS icon in the local icon theme. + if ! ensure_bms_icon_installed; then + debug_print continue "Warning: unable to install or refresh desktop icon from $bms_icon" fi # Create .desktop files @@ -4725,12 +4865,15 @@ create_desktop_files() { # $HOME/Desktop/ home_desktop_file="${XDG_DESKTOP_DIR:-$HOME/Desktop}/$bms_desktop_basename" - create_desktop_files="true" - # If the "needed" argument is passed, determine if we need to create system desktop files + create_localshare_file="true" + create_home_file="true" + # If the "needed" argument is passed, only create missing desktop files. if [ "$1" = "needed" ]; then - if [ -f "$localshare_desktop_file" ] || [ -f "$home_desktop_file" ]; then - # If either desktop file already exists, don't overwrite/replace them - create_desktop_files="false" + if [ -f "$localshare_desktop_file" ]; then + create_localshare_file="false" + fi + if [ -f "$home_desktop_file" ]; then + create_home_file="false" fi fi @@ -4738,11 +4881,19 @@ create_desktop_files() { # The backup .desktop file in the prefix directory will always be created so it's up to date # Use the configured base dir (public vs internal) when building Exec/Path escaped_base_dir="$(echo "$bms_base_dir" | sed "s/\\\\/\\\\\\\\/g; s/'/\\'"/g)" - icon_installed_path="${data_dir}/icons/hicolor/256x256/apps/$(basename "$bms_icon")" # Ensure install_dir is set (fallback to wine_prefix) install_dir="${install_dir:-$wine_prefix}" + if ! ensure_bms_icon_installed; then + debug_print continue "Warning: unable to install or refresh desktop icon from $bms_icon" + fi + + desktop_icon_value="bms-launcher" + if [ -n "$install_dir" ] && [ -s "$install_dir/bms-launcher.png" ]; then + desktop_icon_value="$install_dir/bms-launcher.png" + fi + # Ensure launch script exists and is up to date create_or_update_launch_script || true @@ -4802,17 +4953,22 @@ Categories=Game; StartupWMClass=FalconBMS_Alternative_Launcher.exe $exec_line Path=$install_dir/drive_c/$bms_base_dir/Launcher/ -Icon=bms-launcher" > "$prefix_desktop_file" +Icon=$desktop_icon_value" > "$prefix_desktop_file" - if [ "$create_desktop_files" = "true" ]; then - debug_print continue "Creating system .desktop files...\n${localshare_desktop_file}\n${home_desktop_file}" + if [ "$create_localshare_file" = "true" ] || [ "$create_home_file" = "true" ]; then + debug_print continue "Creating missing system .desktop files (if needed)..." # Copy the new desktop file to ~/.local/share/applications - mkdir -p "${data_dir}/applications" - cp "$prefix_desktop_file" "$localshare_desktop_file" + if [ "$create_localshare_file" = "true" ]; then + mkdir -p "${data_dir}/applications" + cp "$prefix_desktop_file" "$localshare_desktop_file" + fi + # Copy the new desktop file to the user's desktop directory - if [ -d "$(dirname "$home_desktop_file")" ]; then - cp "$prefix_desktop_file" "$home_desktop_file" + if [ "$create_home_file" = "true" ]; then + if [ -d "$(dirname "$home_desktop_file")" ]; then + cp "$prefix_desktop_file" "$home_desktop_file" + fi fi # Update the .desktop file database if the command is available @@ -4822,11 +4978,11 @@ Icon=bms-launcher" > "$prefix_desktop_file" fi # Check if the desktop files were created successfully - if [ ! -f "$home_desktop_file" ]; then + if [ "$create_home_file" = "true" ] && [ ! -f "$home_desktop_file" ]; then # Desktop file couldn't be created message warning "Warning: The .desktop file could not be created!\n\n${home_desktop_file}" fi - if [ ! -f "$localshare_desktop_file" ]; then + if [ "$create_localshare_file" = "true" ] && [ ! -f "$localshare_desktop_file" ]; then # Desktop file couldn't be created message warning "Warning: The .desktop file could not be created!\n\n${localshare_desktop_file}" fi @@ -5054,6 +5210,12 @@ select_steam_falcon4_install() { # MARK: choose_falcon4_source() # Ask user whether Falcon 4.0 should come from Steam; fallback to GOG by default choose_falcon4_source() { + if [ "$bms_mode" = "internal" ]; then + falcon4_source="none" + steam_falcon4_dir="" + return 0 + fi + falcon4_source="gog" steam_falcon4_dir="" @@ -5218,6 +5380,11 @@ download_bms_installer() { fi # Trim whitespace bms_key="$(echo "$bms_key" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + if [ -z "$bms_key" ]; then + message error "Internal installer key is required for internal Falcon BMS installs." + cleanup_conf_if_only_firstrun + return 1 + fi fi return 0 else @@ -5304,6 +5471,11 @@ download_bms_installer() { read -r bms_key fi bms_key="$(echo "$bms_key" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + if [ -z "$bms_key" ]; then + message error "Internal installer key is required for internal Falcon BMS installs." + cleanup_conf_if_only_firstrun + return 1 + fi fi # Don't show a popup on successful selection to reduce interruptions debug_print continue "Falcon BMS installer selected: $selected_bms_installer (use_16k_tiles=$use_16k_tiles bms_key=$bms_key)" diff --git a/bms-launcher-256.png b/bms-launcher-256.png new file mode 100644 index 0000000000000000000000000000000000000000..95a8a9620b59a6b3adcdfa11449cdd23b4015999 GIT binary patch literal 29763 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�iD*R)#Hs_rCw)UoFwb$AB!?>YqHLk9ikB2 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 Date: Sun, 5 Jul 2026 16:28:08 +0200 Subject: [PATCH 3/6] internal falcon 4.0 change --- bms-helper.sh | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/bms-helper.sh b/bms-helper.sh index 955d24f..35c3c76 100755 --- a/bms-helper.sh +++ b/bms-helper.sh @@ -4027,6 +4027,22 @@ build_bms_installer_args() { return 0 } +run_bms_installer_command() { + local runner_binary="$1" + local timeout_seconds="$2" + local installer_path="$3" + shift 3 + + local -a installer_cmd=("$runner_binary" "$installer_path" "$@") + debug_print continue "Falcon BMS installer command: $(printf '%q ' "${installer_cmd[@]}")" + + if [ -x "$(command -v timeout)" ] && [ -n "$timeout_seconds" ]; then + timeout --foreground "$timeout_seconds" "${installer_cmd[@]}" + else + "${installer_cmd[@]}" + fi +} + reinstall_bms_launcher() { # Update directories getdirs @@ -4079,11 +4095,7 @@ reinstall_bms_launcher() { return 1 fi - if [ -x "$(command -v timeout)" ] && [ -n "$launcher_timeout_seconds" ]; then - timeout --foreground "$launcher_timeout_seconds" "$launcher_winepath"/wine "$reinstall_installer_path" "${installer_args[@]}" - else - "$launcher_winepath"/wine "$reinstall_installer_path" "${installer_args[@]}" - fi + run_bms_installer_command "$launcher_winepath/wine" "$launcher_timeout_seconds" "$reinstall_installer_path" "${installer_args[@]}" exit_code="$?" if [ "$exit_code" -eq 1 ] || [ "$exit_code" -eq 58 ] || [ "$exit_code" -eq 124 ]; then @@ -4773,17 +4785,9 @@ install_game() { debug_print continue "Falcon BMS selected arguments: ${installer_args[*]}" if [ -n "$selected_bms_installer" ]; then - if [ -x "$(command -v timeout)" ] && [ -n "$installer_timeout_seconds" ]; then - timeout --foreground "$installer_timeout_seconds" wine "$selected_bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 - else - wine "$selected_bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 - fi + run_bms_installer_command "wine" "$installer_timeout_seconds" "$selected_bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 else - if [ -x "$(command -v timeout)" ] && [ -n "$installer_timeout_seconds" ]; then - timeout --foreground "$installer_timeout_seconds" wine "$SCRIPT_DIR/$bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 - else - wine "$SCRIPT_DIR/$bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 - fi + run_bms_installer_command "wine" "$installer_timeout_seconds" "$SCRIPT_DIR/$bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 fi exit_code="$?" From cc35255e7219215c3729a062079d9e28880aa23c Mon Sep 17 00:00:00 2001 From: MaxWaldorf Date: Mon, 13 Jul 2026 10:41:29 +0200 Subject: [PATCH 4/6] add prompt if Falcon 4.0 not detected for standard steam install --- bms-helper.sh | 51 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/bms-helper.sh b/bms-helper.sh index 35c3c76..78e44e1 100755 --- a/bms-helper.sh +++ b/bms-helper.sh @@ -5183,32 +5183,45 @@ detect_steam_falcon4_install() { # MARK: select_steam_falcon4_install() # Ask the user to select their Steam Falcon 4.0 folder and validate falcon4.exe +# Allows retrying so non-standard Steam library locations can be selected. select_steam_falcon4_install() { local default_dir="$HOME/.steam/steam/steamapps/common/Falcon 4.0" local selected_dir="" - if [ "$use_zenity" -eq 1 ]; then - selected_dir="$(zenity --file-selection --directory --title="Select Steam Falcon 4.0 directory" --filename="$default_dir/" 2>/dev/null)" - if [ -z "$selected_dir" ]; then - message error "No Steam Falcon 4.0 directory selected. Aborting installation." - return 1 - fi - else - printf "Enter your Steam Falcon 4.0 directory\nExample: %s\n\n" "$default_dir" - read -rp "Directory path: " selected_dir - if [ -z "$selected_dir" ]; then - message error "No Steam Falcon 4.0 directory provided. Aborting installation." - return 1 + while true; do + selected_dir="" + + if [ "$use_zenity" -eq 1 ]; then + selected_dir="$(zenity --file-selection --directory --title="Select Steam Falcon 4.0 directory" --filename="$default_dir/" 2>/dev/null)" + if [ -z "$selected_dir" ]; then + if message question "No directory was selected. Would you like to try again?"; then + continue + fi + message error "No Steam Falcon 4.0 directory selected. Aborting installation." + return 1 + fi + else + printf "Enter your Steam Falcon 4.0 directory\nExample: %s\n\n" "$default_dir" + read -rp "Directory path: " selected_dir + if [ -z "$selected_dir" ]; then + if message question "No directory was provided. Would you like to try again?"; then + continue + fi + message error "No Steam Falcon 4.0 directory provided. Aborting installation." + return 1 + fi fi - fi - if [ ! -d "$selected_dir" ] || [ ! -f "$selected_dir/falcon4.exe" ]; then - message error "Invalid Steam Falcon 4.0 directory. Expected to find falcon4.exe in:\n$selected_dir\n\nInstallation cancelled." - return 1 - fi + if [ -d "$selected_dir" ] && [ -f "$selected_dir/falcon4.exe" ]; then + steam_falcon4_dir="$selected_dir" + return 0 + fi - steam_falcon4_dir="$selected_dir" - return 0 + if ! message question "Invalid Steam Falcon 4.0 directory. Expected to find falcon4.exe in:\n$selected_dir\n\nWould you like to choose another folder?"; then + message error "Invalid Steam Falcon 4.0 directory. Installation cancelled." + return 1 + fi + done } # MARK: choose_falcon4_source() From e7ff882515f5cca3402be084495dd96af541821a Mon Sep 17 00:00:00 2001 From: MaxWaldorf Date: Tue, 14 Jul 2026 22:52:19 +0200 Subject: [PATCH 5/6] add normal reg path on top of wow6432node --- bms-helper.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/bms-helper.sh b/bms-helper.sh index 78e44e1..1a8dc9c 100755 --- a/bms-helper.sh +++ b/bms-helper.sh @@ -5266,6 +5266,23 @@ apply_falcon4_registry_key() { cat > "$falcon4_reg_file" << 'EOF' Windows Registry Editor Version 5.00 +[HKEY_LOCAL_MACHINE\\Software\\MicroProse] + +[HKEY_LOCAL_MACHINE\\Software\\MicroProse\\Falcon] + +[HKEY_LOCAL_MACHINE\\Software\\MicroProse\\Falcon\\4.0] +"baseDir"="C:\\Falcon 4.0" +"misctexDir"="C:\\Falcon 4.0\\terrdata\\misctex" +"movieDir"="C:\\Falcon 4.0" +"objectDir"="C:\\Falcon 4.0\\terrdata\\objects" +"theaterDir"="C:\\Falcon 4.0\\terrdata\\korea" + +[HKEY_LOCAL_MACHINE\\Software\\MicroProse\\Falcon\\4.0\\MPR] +"MPRDetect3Dx"=dword:00000001 +"MPRDetectCPU"=dword:00000001 +"MPRDetectMMX"=dword:00000001 +"MPRDetectXMM"=dword:00000001 + [HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse] [HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse\\Falcon] From 1941e084c3df1607d89e745c4f5bc303dd83b023 Mon Sep 17 00:00:00 2001 From: MaxWaldorf Date: Sun, 19 Jul 2026 14:00:58 +0200 Subject: [PATCH 6/6] fix reg entries --- bms-helper.sh | 90 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 22 deletions(-) diff --git a/bms-helper.sh b/bms-helper.sh index 1a8dc9c..ce59a8e 100755 --- a/bms-helper.sh +++ b/bms-helper.sh @@ -4679,6 +4679,32 @@ install_game() { #export WINESERVER="$wine_path/wineserver" export WINEPREFIX="$install_dir" + install_wine_bin="$(command -v wine 2>/dev/null || true)" + install_wineserver_bin="$(command -v wineserver 2>/dev/null || true)" + if [ -f "$install_dir/current_runner" ]; then + install_runner_dir="$(sed -n '1p' "$install_dir/current_runner" | tr -d '\r')" + if [ -n "$install_runner_dir" ] && [ -x "$install_runner_dir/files/bin/wine" ]; then + install_wine_bin="$install_runner_dir/files/bin/wine" + install_wineserver_bin="$install_runner_dir/files/bin/wineserver" + elif [ -n "$install_runner_dir" ] && [ -x "$install_runner_dir/bin/wine" ]; then + install_wine_bin="$install_runner_dir/bin/wine" + install_wineserver_bin="$install_runner_dir/bin/wineserver" + elif [ -n "$install_runner_dir" ] && [ -x "$install_runner_dir/wine" ]; then + install_wine_bin="$install_runner_dir/wine" + install_wineserver_bin="$install_runner_dir/wineserver" + fi + fi + + if [ -z "$install_wine_bin" ] || [ ! -x "$install_wine_bin" ]; then + message error "No usable Wine binary was found for installation." + cleanup_conf_if_only_firstrun + return 1 + fi + + if [ -z "$install_wineserver_bin" ] || [ ! -x "$install_wineserver_bin" ]; then + install_wineserver_bin="" + fi + # Timeouts for long-running install stages (override via environment if needed). prefix_setup_timeout_seconds="${BMS_PREFIX_SETUP_TIMEOUT_SECONDS:-5400}" installer_timeout_seconds="${BMS_INSTALLER_TIMEOUT_SECONDS:-7200}" @@ -4707,7 +4733,9 @@ install_game() { exit_code="$?" if [ "$exit_code" -eq 1 ] || [ "$exit_code" -eq 130 ] || [ "$exit_code" -eq 126 ] || [ "$exit_code" -eq 124 ]; then # 126 = permission denied (ie. noexec on /tmp) - wineserver -k # Kill all wine processes + if [ -n "$install_wineserver_bin" ]; then + "$install_wineserver_bin" -k + fi progress_bar stop # Stop the zenity progress window if [ "$exit_code" -eq 124 ]; then message warning "Wine prefix preparation timed out after ${prefix_setup_timeout_seconds} seconds.\n\nThe install log was written to\n$tmp_install_log\n\nThis usually means a hidden installer dialog blocked automation." @@ -4721,7 +4749,7 @@ install_game() { fi # Add registry key that prevents wine from creating unnecessary file type associations - wine reg add "HKEY_CURRENT_USER\Software\Wine\FileOpenAssociations" /v Enable /d N /f >>"$tmp_install_log" 2>&1 + "$install_wine_bin" reg add "HKEY_CURRENT_USER\Software\Wine\FileOpenAssociations" /v Enable /d N /f >>"$tmp_install_log" 2>&1 # Fix oversized fonts in the WPF / MahApps.Metro .NET Launcher progress_update "Applying display scaling and font fixes..." @@ -4729,7 +4757,7 @@ install_game() { curl -sL "https://github.com/mrbvrz/segoe-ui-linux/archive/refs/heads/master.tar.gz" | tar -xz -C "$tmp_dir" cp "$tmp_dir"/segoe-ui-linux-master/font/*.ttf "$install_dir/drive_c/windows/Fonts/" 2>/dev/null || true - wine reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v LogPixels /t REG_DWORD /d 96 /f >>"$tmp_install_log" 2>&1 + "$install_wine_bin" reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v LogPixels /t REG_DWORD /d 96 /f >>"$tmp_install_log" 2>&1 if [ "$falcon4_source" = "steam" ]; then @@ -4742,7 +4770,9 @@ install_game() { cp -a "$steam_falcon4_dir"/. "$steam_target_dir"/ >>"$tmp_install_log" 2>&1 copy_exit_code="$?" if [ "$copy_exit_code" -ne 0 ] || [ ! -f "$steam_target_dir/falcon4.exe" ]; then - wineserver -k + if [ -n "$install_wineserver_bin" ]; then + "$install_wineserver_bin" -k + fi progress_bar stop message error "Failed to copy Steam Falcon 4.0 files into the Wine prefix.\nThe install log was written to\n$tmp_install_log" cleanup_conf_if_only_firstrun @@ -4750,9 +4780,11 @@ install_game() { fi progress_update "Applying Falcon 4.0 registry keys..." - apply_falcon4_registry_key >>"$tmp_install_log" 2>&1 + apply_falcon4_registry_key "$install_wine_bin" >>"$tmp_install_log" 2>&1 if [ "$?" -ne 0 ]; then - wineserver -k + if [ -n "$install_wineserver_bin" ]; then + "$install_wineserver_bin" -k + fi progress_bar stop message error "Falcon 4.0 registry initialization failed.\nThe install log was written to\n$tmp_install_log" cleanup_conf_if_only_firstrun @@ -4763,9 +4795,9 @@ install_game() { debug_print continue "Installing Falcon 4.0. Please wait; this will take a moment..." progress_update "Running Falcon 4.0 GoG installer..." if [ -n "$selected_gog_installer" ]; then - wine "$selected_gog_installer" /VERYSILENT /NOICONS >>"$tmp_install_log" 2>&1 + "$install_wine_bin" "$selected_gog_installer" /VERYSILENT /NOICONS >>"$tmp_install_log" 2>&1 else - wine "$SCRIPT_DIR/$gog_installer" /VERYSILENT /NOICONS >>"$tmp_install_log" 2>&1 + "$install_wine_bin" "$SCRIPT_DIR/$gog_installer" /VERYSILENT /NOICONS >>"$tmp_install_log" 2>&1 fi else debug_print continue "Internal mode selected: skipping Falcon 4.0 install/source requirements." @@ -4776,7 +4808,9 @@ install_game() { progress_update "Running Falcon BMS installer..." # Build installer arguments suitable for the selected release type. if ! build_bms_installer_args; then - wineserver -k + if [ -n "$install_wineserver_bin" ]; then + "$install_wineserver_bin" -k + fi progress_bar stop cleanup_conf_if_only_firstrun return 1 @@ -4785,15 +4819,17 @@ install_game() { debug_print continue "Falcon BMS selected arguments: ${installer_args[*]}" if [ -n "$selected_bms_installer" ]; then - run_bms_installer_command "wine" "$installer_timeout_seconds" "$selected_bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 + run_bms_installer_command "$install_wine_bin" "$installer_timeout_seconds" "$selected_bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 else - run_bms_installer_command "wine" "$installer_timeout_seconds" "$SCRIPT_DIR/$bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 + run_bms_installer_command "$install_wine_bin" "$installer_timeout_seconds" "$SCRIPT_DIR/$bms_installer" "${installer_args[@]}" >>"$tmp_install_log" 2>&1 fi exit_code="$?" if [ "$exit_code" -eq 1 ] || [ "$exit_code" -eq 58 ] || [ "$exit_code" -eq 124 ]; then # User cancelled or there was an error - wineserver -k # Kill all wine processes + if [ -n "$install_wineserver_bin" ]; then + "$install_wineserver_bin" -k + fi progress_bar stop # Stop the zenity progress window if [ "$exit_code" -eq 124 ]; then message warning "Falcon BMS installer timed out after ${installer_timeout_seconds} seconds.\n\nThe install log was written to\n$tmp_install_log" @@ -4810,7 +4846,9 @@ install_game() { progress_bar stop # Kill the wine process after installation - wineserver -k + if [ -n "$install_wineserver_bin" ]; then + "$install_wineserver_bin" -k + fi # Save the install location to the Helper's config files reset_helper "switchprefix" @@ -5262,47 +5300,55 @@ apply_falcon4_registry_key() { return 1 fi + local wine_bin="${1:-wine}" + local falcon4_reg_file="$WINEPREFIX/drive_c/falcon_4.reg" cat > "$falcon4_reg_file" << 'EOF' Windows Registry Editor Version 5.00 -[HKEY_LOCAL_MACHINE\\Software\\MicroProse] +[HKEY_LOCAL_MACHINE\Software\MicroProse] -[HKEY_LOCAL_MACHINE\\Software\\MicroProse\\Falcon] +[HKEY_LOCAL_MACHINE\Software\MicroProse\Falcon] -[HKEY_LOCAL_MACHINE\\Software\\MicroProse\\Falcon\\4.0] +[HKEY_LOCAL_MACHINE\Software\MicroProse\Falcon\4.0] "baseDir"="C:\\Falcon 4.0" "misctexDir"="C:\\Falcon 4.0\\terrdata\\misctex" "movieDir"="C:\\Falcon 4.0" "objectDir"="C:\\Falcon 4.0\\terrdata\\objects" "theaterDir"="C:\\Falcon 4.0\\terrdata\\korea" -[HKEY_LOCAL_MACHINE\\Software\\MicroProse\\Falcon\\4.0\\MPR] +[HKEY_LOCAL_MACHINE\Software\MicroProse\Falcon\4.0\MPR] "MPRDetect3Dx"=dword:00000001 "MPRDetectCPU"=dword:00000001 "MPRDetectMMX"=dword:00000001 "MPRDetectXMM"=dword:00000001 -[HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse] +[HKEY_LOCAL_MACHINE\Software\Wow6432Node\MicroProse] -[HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse\\Falcon] +[HKEY_LOCAL_MACHINE\Software\Wow6432Node\MicroProse\Falcon] -[HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse\\Falcon\\4.0] +[HKEY_LOCAL_MACHINE\Software\Wow6432Node\MicroProse\Falcon\4.0] "baseDir"="C:\\Falcon 4.0" "misctexDir"="C:\\Falcon 4.0\\terrdata\\misctex" "movieDir"="C:\\Falcon 4.0" "objectDir"="C:\\Falcon 4.0\\terrdata\\objects" "theaterDir"="C:\\Falcon 4.0\\terrdata\\korea" -[HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\MicroProse\\Falcon\\4.0\\MPR] +[HKEY_LOCAL_MACHINE\Software\Wow6432Node\MicroProse\Falcon\4.0\MPR] "MPRDetect3Dx"=dword:00000001 "MPRDetectCPU"=dword:00000001 "MPRDetectMMX"=dword:00000001 "MPRDetectXMM"=dword:00000001 EOF - wine regedit /S "C:\\falcon_4.reg" + "$wine_bin" regedit /S "C:\\falcon_4.reg" local reg_exit_code="$?" + + if [ "$reg_exit_code" -eq 0 ]; then + "$wine_bin" reg query 'HKEY_LOCAL_MACHINE\Software\MicroProse\Falcon\4.0' /v baseDir >/dev/null 2>&1 + reg_exit_code="$?" + fi + rm -f "$falcon4_reg_file" 2>/dev/null || true if [ "$reg_exit_code" -ne 0 ]; then