diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index cbc0111029..9a7e529fdd 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -757,6 +757,7 @@ + @@ -1368,6 +1369,7 @@ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DHAVE_SDL2 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index bc2110067b..6f4fa09019 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -1164,6 +1164,9 @@ Gui\utils + + Gui\game list + @@ -1370,6 +1373,9 @@ Gui\utils + + Gui\game list + diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt index 29531499a7..60b5ede8e8 100644 --- a/rpcs3/rpcs3qt/CMakeLists.txt +++ b/rpcs3/rpcs3qt/CMakeLists.txt @@ -37,6 +37,7 @@ add_library(rpcs3_ui STATIC gui_application.cpp gl_gs_frame.cpp gs_frame.cpp + gui_game_info.cpp gui_settings.cpp infinity_dialog.cpp input_dialog.cpp diff --git a/rpcs3/rpcs3qt/game_list_base.cpp b/rpcs3/rpcs3qt/game_list_base.cpp index a8a0cd959f..edc33634a8 100644 --- a/rpcs3/rpcs3qt/game_list_base.cpp +++ b/rpcs3/rpcs3qt/game_list_base.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" #include "game_list_base.h" -#include "localized.h" #include #include @@ -189,17 +188,6 @@ QColor game_list_base::GetGridCompatibilityColor(const QString& string) const return QColor(); } -std::string game_list_base::GetGameVersion(const game_info& game) -{ - if (game->info.app_ver == Localized().category.unknown.toStdString()) - { - // Fall back to Disc/Pkg Revision - return game->info.version; - } - - return game->info.app_ver; -} - QIcon game_list_base::GetCustomConfigIcon(const game_info& game) { if (!game) diff --git a/rpcs3/rpcs3qt/game_list_base.h b/rpcs3/rpcs3qt/game_list_base.h index 5e21097b05..66012d9e34 100644 --- a/rpcs3/rpcs3qt/game_list_base.h +++ b/rpcs3/rpcs3qt/game_list_base.h @@ -1,31 +1,10 @@ #pragma once -#include "movie_item_base.h" -#include "game_compatibility.h" -#include "Emu/GameInfo.h" +#include "gui_game_info.h" #include -#include #include -/* Having the icons associated with the game info simplifies logic internally */ -struct gui_game_info -{ - GameInfo info{}; - QString localized_category; - compat::status compat; - QPixmap icon; - QPixmap pxmap; - bool hasCustomConfig = false; - bool hasCustomPadConfig = false; - bool has_hover_gif = false; - bool has_hover_pam = false; - movie_item_base* item = nullptr; -}; - -typedef std::shared_ptr game_info; -Q_DECLARE_METATYPE(game_info) - class game_list_base { public: @@ -45,9 +24,6 @@ public: virtual void repaint_icons(std::vector& game_data, const QColor& icon_color, const QSize& icon_size, qreal device_pixel_ratio); - // Returns the visible version string in the game list - static std::string GetGameVersion(const game_info& game); - /** Sets the custom config icon. */ static QIcon GetCustomConfigIcon(const game_info& game); diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp index 2df8852718..4f699106d6 100644 --- a/rpcs3/rpcs3qt/game_list_frame.cpp +++ b/rpcs3/rpcs3qt/game_list_frame.cpp @@ -839,45 +839,44 @@ void game_list_frame::OnRefreshFinished() const std::string cat_unknown_localized = localized.category.unknown.toStdString(); // Try to update the app version for disc games if there is a patch - for (const auto& entry : m_game_data) + for (const game_info& entry : m_game_data) { - if (entry->info.category == "DG") + if (entry->info.category != "DG") continue; + + for (const auto& other : m_game_data) { - for (const auto& other : m_game_data) + // The patch is game data and must have the same serial and an app version + static constexpr auto version_is_bigger = [](const std::string& v0, const std::string& v1, const std::string& serial, bool is_fw) { - // The patch is game data and must have the same serial and an app version - static constexpr auto version_is_bigger = [](const std::string& v0, const std::string& v1, const std::string& serial, bool is_fw) + std::add_pointer_t ev0, ev1; + const double ver0 = std::strtod(v0.c_str(), &ev0); + const double ver1 = std::strtod(v1.c_str(), &ev1); + + if (v0.c_str() + v0.size() == ev0 && v1.c_str() + v1.size() == ev1) { - std::add_pointer_t ev0, ev1; - const double ver0 = std::strtod(v0.c_str(), &ev0); - const double ver1 = std::strtod(v1.c_str(), &ev1); + return ver0 > ver1; + } - if (v0.c_str() + v0.size() == ev0 && v1.c_str() + v1.size() == ev1) - { - return ver0 > ver1; - } + game_list_log.error("Failed to update the displayed %s numbers for title ID %s\n'%s'-'%s'", is_fw ? "firmware version" : "version", serial, v0, v1); + return false; + }; - game_list_log.error("Failed to update the displayed %s numbers for title ID %s\n'%s'-'%s'", is_fw ? "firmware version" : "version", serial, v0, v1); - return false; - }; - - if (entry->info.serial == other->info.serial && other->info.category != "DG" && other->info.app_ver != cat_unknown_localized) + if (entry->info.serial == other->info.serial && other->info.category != "DG" && other->info.app_ver != cat_unknown_localized) + { + // Update the app version if it's higher than the disc's version (old games may not have an app version) + if (entry->info.app_ver == cat_unknown_localized || version_is_bigger(other->info.app_ver, entry->info.app_ver, entry->info.serial, true)) { - // Update the app version if it's higher than the disc's version (old games may not have an app version) - if (entry->info.app_ver == cat_unknown_localized || version_is_bigger(other->info.app_ver, entry->info.app_ver, entry->info.serial, true)) - { - entry->info.app_ver = other->info.app_ver; - } - // Update the firmware version if possible and if it's higher than the disc's version - if (other->info.fw != cat_unknown_localized && version_is_bigger(other->info.fw, entry->info.fw, entry->info.serial, false)) - { - entry->info.fw = other->info.fw; - } - // Update the parental level if possible and if it's higher than the disc's level - if (other->info.parental_lvl != 0 && other->info.parental_lvl > entry->info.parental_lvl) - { - entry->info.parental_lvl = other->info.parental_lvl; - } + entry->info.app_ver = other->info.app_ver; + } + // Update the firmware version if possible and if it's higher than the disc's version + if (other->info.fw != cat_unknown_localized && version_is_bigger(other->info.fw, entry->info.fw, entry->info.serial, false)) + { + entry->info.fw = other->info.fw; + } + // Update the parental level if possible and if it's higher than the disc's level + if (other->info.parental_lvl != 0 && other->info.parental_lvl > entry->info.parental_lvl) + { + entry->info.parental_lvl = other->info.parental_lvl; } } } @@ -1873,15 +1872,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos) }); connect(configure_patches, &QAction::triggered, this, [this, gameinfo]() { - std::unordered_map> games; - for (const auto& game : m_game_data) - { - if (game) - { - games[game->info.serial].insert(game_list::GetGameVersion(game)); - } - } - patch_manager_dialog patch_manager(m_gui_settings, games, gameinfo->info.serial, game_list::GetGameVersion(gameinfo), this); + patch_manager_dialog patch_manager(m_gui_settings, m_game_data, gameinfo->info.serial, gameinfo->GetGameVersion(), this); patch_manager.exec(); }); connect(check_compat, &QAction::triggered, this, [serial] diff --git a/rpcs3/rpcs3qt/game_list_table.cpp b/rpcs3/rpcs3qt/game_list_table.cpp index 32a9419a74..49aa7962eb 100644 --- a/rpcs3/rpcs3qt/game_list_table.cpp +++ b/rpcs3/rpcs3qt/game_list_table.cpp @@ -332,7 +332,7 @@ void game_list_table::populate( } // Version - QString app_version = QString::fromStdString(game_list::GetGameVersion(game)); + QString app_version = QString::fromStdString(game->GetGameVersion()); if (game->info.bootable && !game->compat.latest_version.isEmpty()) { diff --git a/rpcs3/rpcs3qt/gui_game_info.cpp b/rpcs3/rpcs3qt/gui_game_info.cpp new file mode 100644 index 0000000000..61187a6f11 --- /dev/null +++ b/rpcs3/rpcs3qt/gui_game_info.cpp @@ -0,0 +1,14 @@ +#include "stdafx.h" +#include "gui_game_info.h" +#include "localized.h" + +std::string gui_game_info::GetGameVersion() const +{ + if (info.app_ver == Localized().category.unknown.toStdString()) + { + // Fall back to Disc/Pkg Revision + return info.version; + } + + return info.app_ver; +} diff --git a/rpcs3/rpcs3qt/gui_game_info.h b/rpcs3/rpcs3qt/gui_game_info.h new file mode 100644 index 0000000000..60f89ed9da --- /dev/null +++ b/rpcs3/rpcs3qt/gui_game_info.h @@ -0,0 +1,29 @@ +#pragma once + +#include "movie_item_base.h" +#include "game_compatibility.h" + +#include "Emu/GameInfo.h" + +#include + +/* Having the icons associated with the game info simplifies logic internally */ +struct gui_game_info +{ + GameInfo info{}; + QString localized_category; + compat::status compat; + QPixmap icon; + QPixmap pxmap; + bool hasCustomConfig = false; + bool hasCustomPadConfig = false; + bool has_hover_gif = false; + bool has_hover_pam = false; + movie_item_base* item = nullptr; + + // Returns the visible version string in the game list + std::string GetGameVersion() const; +}; + +typedef std::shared_ptr game_info; +Q_DECLARE_METATYPE(game_info) diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index eaa72807f3..71adff9dbe 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -3070,18 +3070,7 @@ void main_window::CreateConnects() connect(ui->actionManage_Game_Patches, &QAction::triggered, this, [this] { - std::unordered_map> games; - if (m_game_list_frame) - { - for (const game_info& game : m_game_list_frame->GetGameInfo()) - { - if (game) - { - games[game->info.serial].insert(game_list::GetGameVersion(game)); - } - } - } - patch_manager_dialog patch_manager(m_gui_settings, games, "", "", this); + patch_manager_dialog patch_manager(m_gui_settings, m_game_list_frame ? m_game_list_frame->GetGameInfo() : std::vector{}, "", "", this); patch_manager.exec(); }); diff --git a/rpcs3/rpcs3qt/patch_manager_dialog.cpp b/rpcs3/rpcs3qt/patch_manager_dialog.cpp index 47cc299160..c17b296400 100644 --- a/rpcs3/rpcs3qt/patch_manager_dialog.cpp +++ b/rpcs3/rpcs3qt/patch_manager_dialog.cpp @@ -57,12 +57,11 @@ enum node_level : int Q_DECLARE_METATYPE(patch_engine::patch_config_value); -patch_manager_dialog::patch_manager_dialog(std::shared_ptr gui_settings, std::unordered_map> games, const std::string& title_id, const std::string& version, QWidget* parent) +patch_manager_dialog::patch_manager_dialog(std::shared_ptr gui_settings, const std::vector& games, const std::string& title_id, const std::string& version, QWidget* parent) : QDialog(parent) , m_gui_settings(std::move(gui_settings)) , m_expand_current_match(!title_id.empty() && !version.empty()) // Expand first search results , m_search_version(QString::fromStdString(version)) - , m_owned_games(std::move(games)) , ui(new Ui::patch_manager_dialog) { ui->setupUi(this); @@ -71,6 +70,15 @@ patch_manager_dialog::patch_manager_dialog(std::shared_ptr gui_set // Load gui settings m_show_owned_games_only = m_gui_settings->GetValue(gui::pm_show_owned).toBool(); + // Get owned games + for (const auto& game : games) + { + if (game) + { + m_owned_games[game->info.serial].insert(game->GetGameVersion()); + } + } + // Initialize gui controls ui->patch_filter->setText(QString::fromStdString(title_id)); ui->cb_owned_games_only->setChecked(m_show_owned_games_only); diff --git a/rpcs3/rpcs3qt/patch_manager_dialog.h b/rpcs3/rpcs3qt/patch_manager_dialog.h index c554f6f309..4639afd454 100644 --- a/rpcs3/rpcs3qt/patch_manager_dialog.h +++ b/rpcs3/rpcs3qt/patch_manager_dialog.h @@ -5,6 +5,7 @@ #include #include +#include "gui_game_info.h" #include "Utilities/bin_patch.h" #include @@ -39,7 +40,7 @@ class patch_manager_dialog : public QDialog const QString tr_all_versions = tr("All versions"); public: - explicit patch_manager_dialog(std::shared_ptr gui_settings, std::unordered_map> games, const std::string& title_id, const std::string& version, QWidget* parent = nullptr); + explicit patch_manager_dialog(std::shared_ptr gui_settings, const std::vector& games, const std::string& title_id, const std::string& version, QWidget* parent = nullptr); ~patch_manager_dialog(); int exec() override;