diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index 4edd0a2d7558..d696a28c627f 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -1310,7 +1310,7 @@ void package_reader::extract_worker() } } -package_install_result package_reader::extract_data(std::deque& readers, std::deque& bootable_paths) +package_install_result package_reader::extract_data(std::deque& readers, std::deque& bootable_paths, bool from_optical_drive) { package_install_result::error_type error = package_install_result::error_type::no_error; usz num_failures = 0; @@ -1362,7 +1362,8 @@ package_install_result package_reader::extract_data(std::deque& if (reader.m_num_failures == 0) { - const usz thread_count = std::min(utils::get_thread_count(), reader.m_install_entries.size()); + // Disc archives don't like multithreaded file reads, so let's just use a single thread here + const usz thread_count = from_optical_drive ? 1 : std::min(utils::get_thread_count(), reader.m_install_entries.size()); atomic_t num_threads_succeeded {0}; // Check if any thread didn't finish. For example when hitting an exception. if (thread_count > 1) diff --git a/rpcs3/Crypto/unpkg.h b/rpcs3/Crypto/unpkg.h index 35b0f091507b..f7802492af7e 100644 --- a/rpcs3/Crypto/unpkg.h +++ b/rpcs3/Crypto/unpkg.h @@ -372,7 +372,7 @@ class package_reader const PKGHeader& get_header() const { return m_header; } const PKGMetaData& get_metadata() const { return m_metadata; } package_install_result check_target_app_version() const; - static package_install_result extract_data(std::deque& readers, std::deque& bootable_paths); + static package_install_result extract_data(std::deque& readers, std::deque& bootable_paths, bool from_optical_drive); const psf::registry& get_psf() const { return m_psf; } result get_result() const { return m_result; }; diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 6cdb75585e62..2942eede5c4b 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -1226,6 +1226,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, std::string inherited_ps3_game_path; bool launching_from_disc_archive = false; + bool launching_from_optical_drive = false; { Init(); @@ -1317,7 +1318,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, std::string disc_info; m_ar->serialize(argv.emplace_back(), disc_info, klic.emplace_back(), m_game_dir, hdd1); - launching_from_disc_archive = is_iso_file(disc_info); + launching_from_disc_archive = is_iso_file(disc_info, nullptr, &launching_from_optical_drive); sys_log.notice("Savestate: is iso archive = %d ('%s')", launching_from_disc_archive, disc_info); @@ -1623,7 +1624,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, } const std::string resolved_path = GetCallbacks().resolve_path(m_path); - if (!launching_from_disc_archive && is_iso_file(m_path)) + if (!launching_from_disc_archive && is_iso_file(m_path, nullptr, &launching_from_optical_drive)) { sys_log.notice("Loading iso archive '%s'", m_path); @@ -2100,7 +2101,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, // Load /dev_bdvd/ from game list if available if (std::string game_path = m_games_config.get_path(m_title_id); !game_path.empty()) { - if (is_iso_file(game_path)) + if (is_iso_file(game_path, nullptr, &launching_from_optical_drive)) { sys_log.notice("Loading iso archive for patch ('%s')", game_path); @@ -2368,9 +2369,9 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, if (!pkgs.empty()) { bool install_success = true; - BlockingCallFromMainThread([this, &pkgs, &install_success]() + BlockingCallFromMainThread([this, &pkgs, &install_success, launching_from_optical_drive]() { - if (!GetCallbacks().on_install_pkgs(pkgs)) + if (!GetCallbacks().on_install_pkgs(pkgs, launching_from_optical_drive)) { install_success = false; } diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 3941851a3b81..3285cb85594c 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -109,7 +109,7 @@ struct EmuCallbacks std::function resolve_path = [](std::string_view arg){ return std::string{arg}; }; // Resolve path using Qt (returns empty string if the file doesn't exist) std::function resolve_path_may_not_exist = [](std::string_view arg){ return std::string{arg}; }; // Resolve path using Qt std::function()> get_font_dirs; - std::function&)> on_install_pkgs; + std::function&, bool)> on_install_pkgs; std::function add_breakpoint; std::function display_sleep_control_supported; std::function enable_display_sleep; diff --git a/rpcs3/Emu/system_utils.cpp b/rpcs3/Emu/system_utils.cpp index e389ed81a5da..875ed8cf90fd 100644 --- a/rpcs3/Emu/system_utils.cpp +++ b/rpcs3/Emu/system_utils.cpp @@ -69,7 +69,7 @@ namespace rpcs3::utils return id; } - bool install_pkg(const std::string& path) + bool install_pkg(const std::string& path, bool from_optical_drive) { sys_log.success("Installing package: %s", path); @@ -82,7 +82,7 @@ namespace rpcs3::utils named_thread worker("PKG Installer", [&] { std::deque bootables; - const package_install_result result = package_reader::extract_data(reader, bootables); + const package_install_result result = package_reader::extract_data(reader, bootables, from_optical_drive); return result.error == package_install_result::error_type::no_error; }); diff --git a/rpcs3/Emu/system_utils.hpp b/rpcs3/Emu/system_utils.hpp index b25f63b0cb2e..0125a8bbc66d 100644 --- a/rpcs3/Emu/system_utils.hpp +++ b/rpcs3/Emu/system_utils.hpp @@ -25,7 +25,7 @@ namespace rpcs3::utils u32 check_user(std::string_view user); - bool install_pkg(const std::string& path); + bool install_pkg(const std::string& path, bool from_optical_drive); // VFS directories and disk usage std::vector> get_vfs_disk_usage(); diff --git a/rpcs3/Loader/ISO.cpp b/rpcs3/Loader/ISO.cpp index b4d871407236..94d5fdcb81bd 100644 --- a/rpcs3/Loader/ISO.cpp +++ b/rpcs3/Loader/ISO.cpp @@ -84,6 +84,11 @@ static bool is_iso_file(iso_file& file, u64* size = nullptr) bool is_iso_file(const std::string& path, u64* size, bool* is_raw_device) { + if (is_raw_device) + { + *is_raw_device = false; + } + if (path.empty()) { return false; diff --git a/rpcs3/main_application.cpp b/rpcs3/main_application.cpp index 77ec4da457b8..d54e07dd04bb 100644 --- a/rpcs3/main_application.cpp +++ b/rpcs3/main_application.cpp @@ -428,11 +428,11 @@ EmuCallbacks main_application::CreateCallbacks() return font_dirs; }; - callbacks.on_install_pkgs = [](const std::vector& pkgs) + callbacks.on_install_pkgs = [](const std::vector& pkgs, bool from_optical_drive) { for (const std::string& pkg : pkgs) { - if (!rpcs3::utils::install_pkg(pkg)) + if (!rpcs3::utils::install_pkg(pkg, from_optical_drive)) { sys_log.error("Failed to install %s", pkg); return false; diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index 0ce7b2674d21..6a73ba4cb294 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -946,7 +946,7 @@ void gui_application::InitializeCallbacks() if (m_show_gui) // If this is false, we already have a fallback in the main_application. { - callbacks.on_install_pkgs = [this](const std::vector& pkgs) + callbacks.on_install_pkgs = [this](const std::vector& pkgs, bool from_optical_drive) { ensure(!pkgs.empty()); QStringList pkg_list; @@ -954,7 +954,7 @@ void gui_application::InitializeCallbacks() { pkg_list << QString::fromStdString(pkg); } - return main_window::InstallPackages(m_main_window, pkg_list, true); + return main_window::InstallPackages(m_main_window, pkg_list, true, from_optical_drive); }; } diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index da6febd2a80e..85305eeb4191 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -881,7 +881,7 @@ bool main_window::InstallFileInExData(const std::string& extension, const QStrin return to.commit(); } -bool main_window::InstallPackages(main_window* mw, QStringList file_paths, bool from_boot) +bool main_window::InstallPackages(main_window* mw, QStringList file_paths, bool from_boot, bool from_optical_drive) { if (file_paths.isEmpty()) { @@ -926,7 +926,7 @@ bool main_window::InstallPackages(main_window* mw, QStringList file_paths, bool return true; } - return InstallPackages(mw, dir_file_paths, from_boot); + return InstallPackages(mw, dir_file_paths, from_boot, from_optical_drive); } } @@ -986,26 +986,23 @@ bool main_window::InstallPackages(main_window* mw, QStringList file_paths, bool if (from_boot) { - return HandlePackageInstallation(mw, file_paths, true); + return HandlePackageInstallation(mw, file_paths, true, from_optical_drive); } - // Handle further installations with a timeout. Otherwise the source explorer instance is not usable during the following file processing. if (mw) { - QTimer::singleShot(0, [mw, paths = std::move(file_paths)]() + // Handle further installations with a timeout. Otherwise the source explorer instance is not usable during the following file processing. + QTimer::singleShot(0, [mw, from_optical_drive, paths = std::move(file_paths)]() { - HandlePackageInstallation(mw, paths, false); + HandlePackageInstallation(mw, paths, false, from_optical_drive); }); - } - else - { - return HandlePackageInstallation(nullptr, file_paths, false); + return true; } - return true; + return HandlePackageInstallation(nullptr, file_paths, false, from_optical_drive); } -bool main_window::HandlePackageInstallation(main_window* mw, QStringList file_paths, bool from_boot) +bool main_window::HandlePackageInstallation(main_window* mw, QStringList file_paths, bool from_boot, bool from_optical_drive) { if (file_paths.empty()) { @@ -1135,9 +1132,9 @@ bool main_window::HandlePackageInstallation(main_window* mw, QStringList file_pa std::deque bootable_paths; // Run PKG unpacking asynchronously - named_thread worker("PKG Installer", [&readers, &result, &bootable_paths] + named_thread worker("PKG Installer", [&readers, &result, &bootable_paths, from_optical_drive] { - result = package_reader::extract_data(readers, bootable_paths); + result = package_reader::extract_data(readers, bootable_paths, from_optical_drive); return result.error == package_install_result::error_type::no_error; }); diff --git a/rpcs3/rpcs3qt/main_window.h b/rpcs3/rpcs3qt/main_window.h index 64f42471b04b..0a3816e7d596 100644 --- a/rpcs3/rpcs3qt/main_window.h +++ b/rpcs3/rpcs3qt/main_window.h @@ -76,7 +76,7 @@ class main_window : public QMainWindow void Init(); QIcon GetAppIcon() const; void OnMissingFw(); - static bool InstallPackages(main_window* mw, QStringList file_paths = {}, bool from_boot = false); + static bool InstallPackages(main_window* mw, QStringList file_paths = {}, bool from_boot = false, bool from_optical_drive = false); static void InstallPup(main_window* mw, QString file_path = ""); Q_SIGNALS: @@ -147,7 +147,7 @@ private Q_SLOTS: void CreateShortCuts(const std::map& paths, std::set locations); static bool InstallFileInExData(const std::string& extension, const QString& path, const std::string& filename); - static bool HandlePackageInstallation(main_window* mw, QStringList file_paths, bool from_boot); + static bool HandlePackageInstallation(main_window* mw, QStringList file_paths, bool from_boot, bool from_optical_drive); static void HandlePupInstallation(main_window* mw, const QString& file_path, const QString& dir_path = ""); void ExtractPup();